Para programadores: API pública, OpenAPI e Markdown
API pública dos preços dos combustíveis e do carregamento elétrico em Portugal: sem chave, com OpenAPI, exemplos com curl e páginas em Markdown.
O que é a API
O combustivel.com.pt tem uma API pública, só de leitura: o preço de cada combustível em todos os postos de Portugal continental (DGEG), os postos mais próximos de uma posição, os pontos de carregamento elétrico da rede MOBI.E com o estado e o preço, o custo de uma viagem com combustível, portagens e paragens, e o estado dos dados. É a mesma que alimenta as páginas do site.
As respostas são JSON, os erros também. Não precisa de chave nem de registo. Há uma descrição OpenAPI 3.1 completa, pronta para ferramentas e para agentes de IA, e todas as páginas do site existem também em Markdown.
- openapi.json: A descrição OpenAPI 3.1 de todos os endereços, com esquemas, exemplos e erros.
- llms.txt: O que o site é, de onde vêm os dados e as páginas principais, para modelos de linguagem.
- llms-full.txt: O essencial em Markdown, num ficheiro de cerca de 40 kB. O resto está em /llms-precos.txt, /llms-distritos.txt, /llms-ev.txt, /llms-blog.txt e /llms-site.txt.
- sitemap.xml: A lista completa de endereços do site.
Acesso e limites
- Sem autenticação: não há chave, conta nem registo. Os endereços estão em https://combustivel.com.pt e terminam sempre com barra.
- Limites: não há quota por cliente. O único limite que a aplicação aplica é o do planeador de viagens: 20 rotas novas por endereço IP e por hora, e 170 por dia no total. A pesquisa de moradas tem o seu: 30 pesquisas novas por endereço IP e por hora, e 400 por dia no total. Uma rota ou uma morada que já esteja em cache nunca é recusada. Quando o limite aperta, a resposta é 429 com o cabeçalho Retry-After.
- Uso razoável: as respostas GET ficam em cache na CDN (o cabeçalho Cache-Control de cada resposta diz quanto tempo) e os dados só mudam de hora a hora, por isso guarde-as também do seu lado e não consulte mais depressa do que os dados mudam. Para volumes grandes ou uso automático intenso, escreva-nos antes. O tráfego abusivo pode ser bloqueado.
- A posição que enviar é arredondada a duas casas decimais (cerca de 1 km), usada só para o cálculo e nunca guardada nem registada. Vai sempre no corpo de um POST, nunca no endereço. A morada que escrever também vai no corpo: guardamos o texto da pesquisa 30 dias, sem o IP, para não a procurar duas vezes, e nunca o registamos.
Os endereços, com exemplos
Cada exemplo é um pedido e uma resposta reais do site, obtidos a 6 de outubro de 2026; as respostas longas estão abreviadas com reticências. O nome de cada operação é o operationId do openapi.json.
Que combustíveis existem
GET/api/mapa/operação listFuelPriceMaps
A lista dos combustíveis com preços por posto e o caminho de cada um. Comece aqui para saber os identificadores (slugs).
curl -s https://combustivel.com.pt/api/mapa/{"fuels":[
{"slug":"gasoleo","label":"Gasóleo","url":"/api/mapa/gasoleo/"},
{"slug":"gasolina-95","label":"Gasolina 95","url":"/api/mapa/gasolina-95/"},
{"slug":"gasoleo-especial","label":"Gasóleo especial","url":"/api/mapa/gasoleo-especial/"},
{"slug":"gasolina-98","label":"Gasolina 98","url":"/api/mapa/gasolina-98/"},
{"slug":"gpl","label":"GPL","url":"/api/mapa/gpl/"}
]}O preço de um combustível em cada posto
GET/api/mapa/{fuel}/operação getFuelPrices
Todos os postos do continente com preço desse combustível, a mediana, o mínimo e o máximo nacionais e um resumo dos 18 distritos. Para o preço hoje num posto, num concelho ou num distrito: procure o posto ou filtre pelo concelho (sétimo valor de cada posto) ou leia a linha do distrito. Os preços são números inteiros em milésimas de euro (2239 é 2,239 € por litro) e cada posto traz a hora a que o comunicou à DGEG. A resposta tem cerca de 280 kB (50 kB comprimida) e fica meia hora em cache.
curl -s https://combustivel.com.pt/api/mapa/gasoleo/{
"fuel": "gasoleo",
"label": "Gasóleo",
"latest": "2026-10-06 06:30",
"median": 2239,
"min": 1939,
"max": 2449,
"count": 2910,
"bands": [2169, 2219, 2249, 2269],
"brands": { "intermarche": "INTERMARCHÉ", "plenergy": "PLENERGY", "bp": "BP", ... },
"stations": [
[67360, 40.6182, -6.8434, 1939, "intermarche", "Intermarche Vilar Formoso", "Almeida", "2026-10-01 08:30"],
[94703, 39.6393, -8.6846, 1979, "plenergy", "Plenergy - Ourém I", "Ourém", "2026-10-05 23:00"],
...
],
"districts": [
{ "name": "Aveiro", "slug": "aveiro", "lat": 40.6405, "lng": -8.6538, "median": 2224, "min": 1999, "max": 2329, "count": 236 },
...
]
}Cada posto é uma lista fixa: [id, latitude, longitude, preço em milésimas de euro, marca, nome, concelho, hora da comunicação à DGEG]. Abreviado: a resposta real tem 2.910 postos e 18 distritos.
Os postos mais próximos de uma posição
POST/api/perto/operação findNearestStations
Os 15 postos mais próximos (até 40 km), do mais perto para o mais longe, com o preço do combustível pedido, a hora da comunicação e a tendência face ao preço anterior. Para os mais baratos à sua volta, ordene a lista por preço. Só aceita POST; a posição é arredondada, usada para a distância e nunca guardada. Nunca fica em cache.
curl -s -X POST https://combustivel.com.pt/api/perto/ \
-H 'content-type: application/json' \
-d '{"lat":38.72,"lng":-9.14,"fuel":"gasoleo"}'{
"fuel": "Gasóleo",
"stations": [
{ "id": 93454, "name": "OZ ENERGIA - GRAÇA", "brand": "OZ Energia", "municipio": "Lisboa",
"address": "Rua da Graça 2-D", "price": 2.184, "updatedAt": "2026-10-04 23:50", "km": 0.9, "trend": null },
{ "id": 66653, "name": "E.S. CASTILHO", "brand": "REPSOL", "municipio": "Lisboa",
"address": "Rua Castilho nº 72-A", "price": 2.269, "updatedAt": "2026-10-05 00:00", "km": 1.2, "trend": "down" },
...
]
}Abreviado: a resposta real traz 15 postos. Aqui o preço é em euros por litro (decimal).
Os locais de carregamento elétrico, com estado e preço
GET/api/carregamento/mapa/operação getChargingMap
Todos os locais da rede pública MOBI.E (continente, Madeira e Açores) de forma compacta: pontos, quantos estavam livres na última leitura, potência máxima, fichas e o preço ad hoc mais baixo por kWh, com IVA. O estado é lido de hora a hora (statusAt): escreva sempre "estado lido às HH:MM", nunca "tempo real". Filtros opcionais: tipo (t2, ccs, chademo, tomada), kw (potência mínima) e livre=1. Cerca de 370 kB (90 kB comprimida), 5 minutos em cache.
curl -s 'https://combustivel.com.pt/api/carregamento/mapa/?tipo=ccs&kw=150&livre=1'{
"v": 1,
"attribution": "Fonte: MOBI.E / NAP Portugal (IMT)",
"statusAt": "2026-10-06T05:05:23.134Z",
"staticAt": "2026-10-06T04:42:51.511Z",
"filter": { "tipo": "ccs", "kw": 150, "livre": true },
"count": { "sites": 757, "points": 1761, "available": 1761 },
"columns": ["id","lat","lng","operator","points","available","outOfOrder","maxKw","types","kwhMili"],
"operators": [["ACCI","Acciona Recarga Portugal"], ["ALFA","Alfa Energia"], ...],
"sites": [
[62, 38.58599, -8.69212, 66, 1, 1, 0, 180, 2, null],
...
]
}Abreviado. Em cada local, operator é um índice na lista operators; types é uma máscara de fichas (1 Tipo 2, 2 CCS, 4 CHAdeMO, 8 tomada) e kwhMili o preço mais baixo em milésimas de euro por kWh.
Os carregadores elétricos mais próximos
POST/api/carregamento/perto/operação findNearbyChargingSites
Até 20 locais de carregamento num raio de 25 km, do mais perto para o mais longe, com os pontos livres na última leitura horária, a potência, as fichas e o preço, já escritos em português. Aceita os mesmos filtros (tipo, kw, livre). A posição é arredondada e nunca guardada.
curl -s -X POST https://combustivel.com.pt/api/carregamento/perto/ \
-H 'content-type: application/json' \
-d '{"lat":38.72,"lng":-9.14,"tipo":"ccs","kw":50,"livre":true}'{
"radiusKm": 25,
"statusAt": "2026-10-06T05:05:23.134Z",
"source": "Fonte: MOBI.E através do NAP (IMT), estado às 06:05",
"sites": [
{ "id": 4090, "href": "/carregamento/posto/4090/", "label": "Atlante - Pingo Doce Lisboa - Campo Santana",
"brand": "Atlante", "place": "Lisboa", "km": 0.22, "points": 1, "available": 1, "outOfOrder": 0,
"tone": "livre", "availability": "1 de 1 ponto livre", "maxKw": 60, "kw": "60 kW", "tier": "rapido",
"connectors": [{ "kind": "ccs", "name": "CCS" }], "price": "0,49 €/kWh", "priced": true },
...
]
}Abreviado: a resposta real traz até 20 locais.
O nome de um local de carregamento
GET/api/carregamento/local/{id}/operação getChargingSiteName
O nome e o sítio de um local, pelo identificador que o mapa compacto traz (o mapa não leva nomes, para ser pequeno). Fica uma hora em cache.
curl -s https://combustivel.com.pt/api/carregamento/local/4090/{"label":"Atlante - Pingo Doce Lisboa - Campo Santana","place":"Lisboa"}O custo de uma viagem: combustível, portagens e paragens
POST/api/viagem/rota/operação planTrip
Entre dois concelhos (ou duas posições) de Portugal continental, para um carro: a rota, onde abastecer mais barato, quantos litros, o custo do combustível, a poupança face à mediana do corredor e as portagens estimadas (classe 1). Com "modo":"eletrico" devolve as paragens para carregar, o tempo total e, quando todos os locais têm preço, o custo. Corpo até 2 KB, nunca fica em cache. Limite: rotas novas, 20 por IP e por hora (as que já estão em cache não contam).
curl -s -X POST https://combustivel.com.pt/api/viagem/rota/ \
-H 'content-type: application/json' \
-d '{"de":{"concelho":"lisboa"},"para":{"concelho":"porto"},"combustivel":"gasoleo",
"carro":{"deposito":50,"consumo":6,"nivel":20},
"opcoes":{"reserva":10,"chegada":20,"desvioMaxKm":5,"custoParagem":1}}'{
"rota": { "distanciaKm": 316.1, "duracaoMin": 190, "geometria": [[-9.13623, 38.70686], ...],
"fornecedor": "openrouteservice", "emCache": true },
"plano": {
"possivel": true, "custoTotal": 38.41, "litros": 19.2,
"paragens": [
{ "postoId": 94864, "nome": "PETROPRIX Castanheira - Vila Franca de Xira", "marca": "PETROPRIX",
"concelho": "Vila Franca de Xira", "kmNaRota": 38.5, "preco": 2.089, "litros": 3.1, ... },
{ "postoId": 94703, "nome": "PLENERGY - OURÉM I", "marca": "PLENERGY",
"concelho": "Ourém", "kmNaRota": 126.3, "preco": 1.979, "litros": 16.2, ... }
],
"precoMedianoCorredor": 2.246, "poupancaVsMediana": 4.8, "postosConsiderados": 154,
"desvioTotalKm": 4, "nivelDestinoPct": 20
},
"portagens": { "classe": 1, "total": 25.05,
"trocos": [{ "via": "A1", "de": "Alverca (A1/A9)", "ate": "Carvalhos", "preco": 25.05, "lancos": 24 }],
"semPreco": [], "fonte": { "nome": "IMT, Taxas de Portagem de 2026", "ano": 2026, ... } },
"dados": { "dgegAte": "2026-10-06T05:30:00.000Z",
"atribuicao": "Rotas: openrouteservice.org (HeiGIT), dados © colaboradores do OpenStreetMap" }
}Abreviado (geometria da rota e campos de cada paragem). Mostre sempre dados.atribuicao junto do resultado.
Uma morada escrita à mão, em coordenadas
POST/api/geo/procurar/operação findAddress
Uma rua e uma localidade, um código postal ou o nome de um sítio, em até 5 lugares de Portugal, com as coordenadas, o concelho e o distrito quando se sabem. Serve para a partida e a chegada do planeador de viagens (os campos de e para aceitam essas coordenadas) e para as pesquisas por perto. Com "ambito":"portugal" inclui a Madeira e os Açores. O texto vai no corpo de um POST (nunca no endereço), fica em cache 30 dias sem o IP e não é registado. Corpo até 1 KB, nunca fica em cache na CDN. Limite: pesquisas novas, 30 por IP e por hora e 400 por dia no total (as que já estão em cache não contam).
curl -s -X POST https://combustivel.com.pt/api/geo/procurar/ \
-H 'content-type: application/json' \
-d '{"q":"Rua Augusta, Lisboa","ambito":"continente"}'{
"candidatos": [
{ "label": "Rua Augusta, Lisboa", "lat": 38.71069, "lng": -9.1377, "tipo": "rua",
"concelho": "Lisboa", "distrito": "Lisboa", "regiao": "continente" },
{ "label": "Rua Maria Augusta Botelho, Mafra", "lat": 38.93712, "lng": -9.33271, "tipo": "rua",
"concelho": "Mafra", "distrito": "Lisboa", "regiao": "continente" },
...
],
"atribuicao": "Moradas: openrouteservice.org (HeiGIT), dados © colaboradores do OpenStreetMap",
"emCache": false
}Abreviado (dois dos cinco candidatos). Mostre sempre atribuicao junto dos resultados.
Se os dados estão em dia
GET/api/saude/operação getServiceHealth
O que fez a última leitura de preços, há quantos minutos acabou a última boa, as falhas das últimas 24 horas e o estado das leituras do carregamento elétrico. Serve para decidir se confia nos números ou se avisa que podem estar atrasados. Fica 60 segundos em cache.
curl -s https://combustivel.com.pt/api/saude/{
"db": true, "db_reads": "on",
"last_run": { "id": 154, "status": "ok", "finished_at": "2026-10-06T05:30:51.221Z", "rows_in": 14238,
"events": 38, "latest_reported_local": "2026-10-06 06:30:00" },
"age_minutes": 29, "gaps_24h": 1, "banner": false,
"ev": { "static": { "status": "ok", "age_minutes": 77, ... }, "status": { "status": "ok", "age_minutes": 54, ... }, "stale": false }
}Abreviado.
Os erros
Todos os erros da API são JSON, em todos os endereços, e um endereço de /api/ que não exista também responde um JSON 404 (nunca uma página HTML). O estado HTTP diz a classe do erro; o código (code) é estável e é por ele que o seu programa deve decidir; a mensagem diz o que aconteceu e a dica o que fazer a seguir, em português.
curl -s -i https://combustivel.com.pt/api/mapa/agua/HTTP/2 404
content-type: application/json
{"error":{"code":"unknown_fuel","message":"Combustível desconhecido.","hint":"Use um dos identificadores de combustível documentados em https://combustivel.com.pt/openapi.json (por exemplo gasoleo ou gasolina-95)."}}| Estado | Códigos | Quando |
|---|---|---|
| 400 | invalid_json, invalid_request, invalid_filter, unknown_fuel, missing_coordinates | O pedido não é válido: JSON mal formado, um valor fora do intervalo ou desconhecido. |
| 404 | not_found, unknown_fuel, unknown_place | Combustível, local ou concelho desconhecido, ou um endereço de /api/ que não existe. |
| 405 | method_not_allowed | O método não é o do endereço (por exemplo GET onde só há POST); o cabeçalho Allow diz qual. |
| 413 | payload_too_large | O corpo é maior do que o endereço aceita (1 KB; 2 KB no planeador de viagens). |
| 422 | out_of_coverage | A posição está fora da zona coberta (os postos de combustível só no continente). |
| 429 | rate_limited | Demasiadas rotas novas no planeador, ou o orçamento do fornecedor de rotas acabou por hoje. Espere o tempo de Retry-After. |
| 502, 503 | upstream_unavailable, data_unavailable | A fonte dos dados (DGEG, MOBI.E) ou a base de dados não respondeu. Tente de novo dentro de minutos. |
Fontes e atribuição
Os dados são públicos e o uso é livre, com atribuição. Não concedemos nem reclamamos exclusividade. O que lhe pedimos:
- Preços dos combustíveis: DGEG
- Fonte: DGEG (Direção-Geral de Energia e Geologia), serviço público Preços dos Combustíveis Online, com os preços que os postos lhe comunicam (Decreto-Lei 243/2008). Diga "Fonte: DGEG" junto de qualquer preço que republique e mantenha a hora da comunicação que a resposta traz. O preço na bomba manda: um posto pode mudar o preço antes de o comunicar e os descontos de cartões não entram. As medianas, os mínimos e as listas são calculados por nós a partir desses preços; não são estatísticas oficiais.
- Carregamento elétrico: MOBI.E
- Fonte: MOBI.E, através do NAP (IMT), a rede pública de carregamento, que a disponibiliza sem licença nem contrato, de livre acesso. Diga "Fonte: MOBI.E / NAP Portugal (IMT)" (a resposta traz-a em attribution ou source). O estado é lido de hora a hora, por isso escreva "estado lido às HH:MM", nunca "tempo real". Os preços são os ad hoc que a MOBI.E publica, com IVA, e não um orçamento.
- Rotas e portagens: openrouteservice e OpenStreetMap
- As rotas são do openrouteservice.org (HeiGIT) e os dados de mapa são © colaboradores do OpenStreetMap (ODbL). Mostre o texto de dados.atribuicao em cada resultado de viagem. As portagens são uma estimativa para a classe 1 (ligeiros) a partir da tabela do IMT de 2026 e dos troços com portagem do OpenStreetMap, assinaladas como estimativa.
- O nosso trabalho
- A combinação dos dados, as medianas e o otimizador de paragens são nossos e de uso livre. Cite o combustivel.com.pt como fonte e guarde as datas e horas que acompanham os números.
De onde vêm os números e como se calcula a mediana está em como funciona.
Markdown, llms.txt e agentes de IA
Cada página do site tem uma versão em Markdown, escrita para ser lida por programas e modelos de linguagem: o mesmo título, o bloco de resposta, as mesmas tabelas e a mesma fonte, sem o resto da página.
- Pedir Markdown ao mesmo endereço
- Peça a página com o cabeçalho Accept: text/markdown. Com Accept: text/html (ou sem preferência) continua a receber HTML. As respostas trazem Vary: Accept.
- Ou acrescentar /md/ ao caminho
- O endereço /combustivel/gasoleo/ tem a versão /md/combustivel/gasoleo/, e a página inicial tem /md/. Só os endereços com versão em Markdown respondem 200.
- Endereços que não existem
- Respondem 404 (o estado HTTP mantém-se) e, se pedir Markdown, com um corpo em Markdown que aponta para o llms.txt e para o sitemap.xml.
- llms.txt
- O ficheiro /llms.txt diz o que o site é, de onde vêm os dados, os limites, quando usar cada página e como citar. O /llms-full.txt junta o Markdown do essencial (a página inicial, como funciona, o gasóleo, a gasolina 95 e a próxima semana); as outras páginas estão em ficheiros por secção: /llms-precos.txt, /llms-distritos.txt, /llms-ev.txt, /llms-blog.txt e /llms-site.txt.
# a página inicial em Markdown, pelo cabeçalho Accept
curl -s -H 'Accept: text/markdown' https://combustivel.com.pt/
# a mesma coisa, pelo endereço /md/
curl -s https://combustivel.com.pt/md/
# o preço do gasóleo em cada distrito
curl -s https://combustivel.com.pt/md/combustivel/gasoleo/Dúvidas, uso intenso ou uma parceria: info@combustivel.com.pt, ou a página de contacto.