Integração da API IPMA para Rotas em Portugal: Guia Completo
Integração da API IPMA para Rotas em Portugal
Porque integrar o IPMA nas suas rotas?
O Instituto Português do Mar e da Atmosfera (IPMA) oferece as previsões meteorológicas mais precisas para Portugal. Integrar estes dados no seu sistema de rotas permite:
- Reduzir atrasos em 23% ajustando tempos estimados segundo condições - Evitar riscos em alertas meteorológicos severos (temporais, nevoeiros) - Otimizar consumo adaptando velocidade a condições de vento - Melhorar ETA (hora estimada de chegada) com dados reais
Caso real: Uma frota de transporte refrigerado reduziu os seus atrasos em 31% no inverno após integrar previsões IPMA para antecipar nevoeiros no norte de Portugal.
O que é o IPMA?
O IPMA é o serviço meteorológico oficial de Portugal. As suas vantagens principais:
✅ Dados gratuitos sem limites de consulta ✅ Alta resolução: previsões por coordenadas exatas ✅ Frequência: atualizações de 6 em 6 horas ✅ Cobertura: todo o território português continental e ilhas ✅ API REST: formato JSON padrão
A TRANSCEND integra o IPMA diretamente na sua API de rotas, adicionando uma camada de inteligência meteorológica sem necessidade de gerir múltiplos fornecedores.
Dados meteorológicos disponíveis
Previsões por tipo
| Tipo | Descrição | Utilidade para transporte | | ---------------- | ----------------------------- | --------------------------- | | Temperatura | Atual e sensação térmica | Carga refrigerada/congelada | | Precipitação | Intensidade e probabilidade | Aderência na estrada | | Vento | Velocidade e direção | Consumo de combustível | | Nevoeiro | Visibilidade | Segurança rodoviária | | Trovoada | Alertas de atividade elétrica | Risco de paragem |
Códigos meteorológicos IPMA
| Código | Condição | Impacto na condução | Recomendação | | ------ | ----------------- | ----------------------- | ------------------- | | 1 | Céu limpo | ✅ Ótimo | Velocidade normal | | 2 | Céu pouco nublado | ✅ Bom | Velocidade normal | | 3 | Céu nublado | ✅ Aceitável | Velocidade normal | | 4 | Nevoeiro | ⚠️ Reduzir velocidade | +20% tempo | | 5 | Chuva fraca | ⚠️ Precaução | +10% tempo | | 6 | Chuva | ⚠️ Aumentar distância | +15% tempo | | 7 | Chuva forte | 🚫 Evitar se possível | +30% tempo | | 8 | Neve fraca | ⚠️ Correntes preparadas | +40% tempo | | 9 | Neve | 🚫 Rota alternativa | Evitar | | 10 | Trovoada | 🚫 Não circular | Paragem obrigatória |
Integração passo a passo
Passo 1: Obter credenciais de API
Registe-se em TRANSCEND para obter a sua API key gratuita.
A sua API key terá este aspeto
TRANSCEND_API_KEY=tr_live_abc123xyz789
Passo 2: Instalar dependências
Node.js:
npm install axios
Python:
pip install requests
Passo 3: Implementar integração IPMA
Opção A: Node.js
const axios = require("axios");const TRANSCEND_API_KEY = process.env.TRANSCEND_API_KEY;
const BASE_URL = "https://api.transcend.cargoffer.com/v1";/
* Obtém previsão meteorológica para uma rota
*/
async function obterMeteorologiaRota(origem, destino, horaPartida) {
try {
const response = await axios.post(
${BASE_URL}/weather/route,
{
origin: {
lat: origem.lat,
lon: origem.lon,
},
destination: {
lat: destino.lat,
lon: destino.lon,
},
departureTime: horaPartida, // ISO 8601
interval: 50, // km entre pontos de amostragem
},
{
headers: {
Authorization: Bearer ${TRANSCEND_API_KEY},
"Content-Type": "application/json",
},
},
); return response.data;
} catch (error) {
console.error("Erro ao obter previsão:", error.message);
throw error;
}
}// Exemplo de uso
const rota = {
origem: { lat: 38.7223, lon: -9.1393 }, // Lisboa
destino: { lat: 41.1496, lon: -8.611 }, // Porto
horaPartida: new Date().toISOString(),
};Opção B: Python
import requests
import os
from datetime import datetimeTRANSCEND_API_KEY = os.environ.get('TRANSCEND_API_KEY')
BASE_URL = 'https://api.transcend.cargoffer.com/v1'def obter_meteorologia_rota(origem, destino, hora_partida=None):
"""
Obtém previsão meteorológica para uma rota. Args:
origem: dict com 'lat' e 'lon'
destino: dict com 'lat' e 'lon'
hora_partida: str ISO 8601 (opcional, padrão: agora) Returns:
dict: Dados meteorológicos da rota
"""
if hora_partida is None:
hora_partida = datetime.now().isoformat() payload = {
'origin': origem,
'destination': destino,
'departureTime': hora_partida,
'interval': 50 # km entre pontos
} headers = {
'Authorization': f'Bearer {TRANSCEND_API_KEY}',
'Content-Type': 'application/json'
} try:
response = requests.post(
f'{BASE_URL}/weather/route',
json=payload,
headers=headers
)
response.raise_for_status()
return response.json() except requests.exceptions.RequestException as e:
print(f'Erro ao obter previsão: {e}')
raiseExemplo de uso
if __name__ == '__main__':
rota = {
'origem': {'lat': 38.7223, 'lon': -9.1393}, # Lisboa
'destino': {'lat': 40.6405, 'lon': -8.6538} # Aveiro
} meteo = obter_meteorologia_rota(rota['origem'], rota['destino'])Passo 4: Resposta da API
{
"routeId": "rota_abc123",
"totalDistance": 255.8,
"forecastPoints": [
{
"distance": 0,
"locationName": "Lisboa",
"coordinates": [38.7223, -9.1393],
"timestamp": "2026-02-12T08:00:00Z",
"temperature": 14,
"feelsLike": 12,
"weatherCondition": "Céu limpo",
"weatherCode": 1,
"windSpeed": 12,
"windDirection": "NO",
"windGusts": 22,
"precipitation": 0,
"humidity": 68,
"visibility": 10,
"uvIndex": 3,
"recommendations": {
"drivingConditions": "Boas",
"speedAdjustment": 0,
"timeAdjustment": 0,
"alerts": []
}
},
{
"distance": 85,
"locationName": "Leiria",
"coordinates": [39.7441, -8.8072],
"timestamp": "2026-02-12T09:05:00Z",
"temperature": 13,
"feelsLike": 10,
"weatherCondition": "Chuva fraca",
"weatherCode": 5,
"windSpeed": 18,
"windDirection": "N",
"windGusts": 32,
"precipitation": 1.8,
"humidity": 78,
"visibility": 8,
"uvIndex": 1,
"recommendations": {
"drivingConditions": "Moderadas",
"speedAdjustment": -10,
"timeAdjustment": 8,
"alerts": [
{
"type": "wind",
"severity": "medium",
"message": "Rajadas de vento de 32 km/h. Precaução em troços elevados."
}
]
}
},
{
"distance": 170,
"locationName": "Coimbra",
"coordinates": [40.2033, -8.4103],
"timestamp": "2026-02-12T10:10:00Z",
"temperature": 11,
"weatherCondition": "Nublado",
"windSpeed": 14,
"windDirection": "NO",
"precipitation": 0,
"recommendations": {
"drivingConditions": "Boas",
"speedAdjustment": 0,
"timeAdjustment": 0,
"alerts": []
}
},
{
"distance": 256,
"locationName": "Porto",
"coordinates": [41.1496, -8.611],
"timestamp": "2026-02-12T11:20:00Z",
"temperature": 12,
"weatherCondition": "Céu pouco nublado",
"windSpeed": 15,
"windDirection": "O",
"precipitation": 0,
"recommendations": {
"drivingConditions": "Boas",
"speedAdjustment": 0,
"timeAdjustment": 0,
"alerts": []
}
}
],
"summary": {
"averageTemperature": 12,
"maxWindSpeed": 32,
"totalPrecipitation": 1.8,
"riskLevel": "low",
"overallConditions": "Moderadas com chuva fraca no troço inicial",
"recommendedDeparture": "2026-02-12T08:00:00Z",
"estimatedTimeAdjustment": 8
}
}
Aplicar dados meteorológicos na lógica de rotas
Exemplo: Ajustar ETA segundo condições
function calcularETAcomMeteorologia(duracaoBase, dadosMeteo) {
// Duração base em minutos
let duracaoAjustada = duracaoBase; // Ajustar segundo condições meteorológicas
dadosMeteo.forecastPoints.forEach((ponto) => {
// Adicionar tempo por condições adversas
duracaoAjustada += ponto.recommendations.timeAdjustment; // Reduzir velocidade média se houver alertas
if (ponto.recommendations.alerts.length > 0) {
const multiplicadorSeveridade = {
low: 1.05,
medium: 1.15,
high: 1.3,
}; const severidadeMaxima = ponto.recommendations.alerts
.map((a) => a.severity)
.sort()
.reverse()[0]; duracaoAjustada *= multiplicadorSeveridade[severidadeMaxima] || 1;
}
});Exemplo: Sugerir rotas alternativas
async function encontrarRotaOtimaComMeteorologia(
origem,
destino,
alternativas,
) {
const rotas = []; // Avaliar rota principal + alternativas
for (const rota of [obterRotaPrincipal(origem, destino), ...alternativas]) {
const meteo = await obterMeteorologiaRota(
rota.origem,
rota.destino,
new Date().toISOString(),
); rotas.push({
...rota,
riscoMeteo: meteo.summary.riskLevel,
ajusteTempo: meteo.summary.estimatedTimeAdjustment,
condicoes: meteo.summary.overallConditions,
});
}Considerações específicas para Portugal
Zonas de risco meteorológico
Norte de Portugal:
- Alto risco de nevoeiro no inverno (Douro, Minho) - Chuva intensa no outono/inverno - Vento forte na costa (Figueira da Foz, Aveiro)
Centro de Portugal:
- Trovoadas frequentes no verão - Serra da Estrela: neve no inverno - Calor extremo no verão (Castelo Branco, Évora)
Sul de Portugal:
- Temperaturas elevadas no verão - Risco de incêndios florestais - Algave: nevoeiro matinal no inverno
Épocas críticas
| Época | Risco principal | Regiões afetadas | Mitigação | | ----------- | ---------------- | ---------------- | --------------------- | | Dez-Fev | Nevoeiro, chuva | Norte, Centro | Partida mais cedo | | Mar-Mai | Trovoadas | Todo o país | Monitorização radar | | Jun-Ago | Calor, incêndios | Interior sul | Evitar horas de calor | | Set-Nov | Chuva intensa | Todo o país | Rotas alternativas |
Melhores práticas
1. Guardar em cache as respostas
Os dados do IPMA são atualizados de 6 em 6 horas. Não faça consultas redundantes:
const cacheMeteo = new Map();
const DURACAO_CACHE = 3 60 60 * 1000; // 3 horasasync function obterMeteoComCache(origem, destino) {
const chave = ${origem.lat},${origem.lon}-${destino.lat},${destino.lon};
const emCache = cacheMeteo.get(chave); if (emCache && Date.now() - emCache.timestamp < DURACAO_CACHE) {
return emCache.dados;
} const dados = await obterMeteorologiaRota(origem, destino);
cacheMeteo.set(chave, {
dados: dados,
timestamp: Date.now(),
});2. Tratar erros de forma elegante
async function obterMeteoComFallback(origem, destino) {
try {
return await obterMeteorologiaRota(origem, destino);
} catch (erro) {
console.warn("Erro ao obter previsão, usando condições padrão");
return {
summary: {
riskLevel: "unknown",
estimatedTimeAdjustment: 0,
overallConditions: "Não disponível",
},
};
}
}
3. Pré-carregar para rotas frequentes
// Pré-carregar previsões para rotas habituais a cada 3 horas
const ROTAS_FREQUENTES = [
{
nome: "Lisboa-Porto",
origem: { lat: 38.7223, lon: -9.1393 },
destino: { lat: 41.1496, lon: -8.611 },
},
{
nome: "Porto-Braga",
origem: { lat: 41.1496, lon: -8.611 },
destino: { lat: 41.5454, lon: -8.4265 },
},
{
nome: "Lisboa-Faro",
origem: { lat: 38.7223, lon: -9.1393 },
destino: { lat: 37.0161, lon: -7.935 },
},
];Recursos adicionais
- Documentação completa API Weather - Calculadora de custos de rota - Códigos meteorológicos IPMA - GitHub: Exemplos de código
Perguntas frequentes
O que é o IPMA e porque usá-lo para rotas logísticas?
O IPMA (Instituto Português do Mar e da Atmosfera) é o serviço meteorológico oficial de Portugal. As suas previsões são gratuitas, atualizadas de 6 em 6 horas, e oferecem dados por coordenadas geográficas exatas, ideais para calcular condições meteorológicas ao longo de uma rota de camião em Portugal.
A integração com IPMA é gratuita?
Sim, a TRANSCEND inclui a integração com IPMA em todos os planos, incluindo o gratuito. Não há custos adicionais por consultas meteorológicas. O limite é o do seu plano geral de API (1.000 pedidos/mês no tier gratuito).
Com que frequência são atualizados os dados meteorológicos?
Os dados do IPMA são atualizados de 6 em 6 horas (00:00, 06:00, 12:00, 18:00 UTC). A TRANSCEND guarda estas respostas em cache durante 3 horas para otimizar o desempenho, pelo que as suas consultas terão sempre dados com no máximo 3 horas de antiguidade.
O IPMA cobre as ilhas (Açores e Madeira)?
Sim, o IPMA cobre todo o território português, incluindo o arquipélago dos Açores e a Madeira. As previsões são específicas para cada ilha e localidade.
Posso usar o IPMA sem passar pela TRANSCEND?
Sim, o IPMA tem API pública gratuita. No entanto, a TRANSCEND adiciona valor ao correlacionar automaticamente os dados meteorológicos com a sua rota, calculando ajustes de tempo e alertas específicas para veículos pesados. A integração direta requeria geocodificação e lógica de enriquecimento adicional.
Pronto para implementar? Comece com o sandbox gratuito →
Não requer cartão de crédito. 1.000 pedidos gratuitos mensais. Documentação completa incluída.
_Última atualização: Fevereiro 2026_