Autenticação, endpoints, payloads, erros e webhooks. Preços e recursos de cada plano estão nas páginas dos modelos — aqui é só o que o seu programador precisa.
https://rotapro.net.br/v1Toda chamada exige sua API key no header — server-to-server apenas, nunca exponha a key no front-end ou no app. A key é gerada (e revogada) por você mesmo no painel do parceiro e exibida uma única vez na emissão.
Authorization: Bearer rl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key ausente ou inválida → 401. Limite de requisições excedido → 429 (padrão 60 req/min, ajustável por contrato). Período de teste encerrado → 402 (500 pedidos grátis / 30 dias — depois disso, liberação de produção via contrato).
/v1/pingcurl -H "Authorization: Bearer rl_live_SUA_KEY" https://rotapro.net.br/v1/ping
{ "success": true, "message": "pong", "partner": { "nome": "Sua Plataforma", "slug": "sua-plataforma" }, "ts": "..." }
/v1/resolveRecebe até 25 pedidos por chamada e devolve endereços geocodificados, ordem otimizada de entrega e link do Google Maps. Stateless: nada fica gravado — quem guarda o resultado é você.
lat/lng e reutilize. Vários estabelecimentos? Envie o origin correspondente em cada chamada. Sem ele → 400 ORIGIN_REQUIRED.
{
"origin": { "lat": -26.4851, "lng": -49.0713, "city": "Guaramirim", "uf": "SC" },
"orders": [
{
"external_id": "pedido-8841",
"structured": {
"numero_pedido": "8841",
"cliente_nome": "Maria Silva",
"telefone": "47999990000",
"localizador": "ABC123",
"valor_total": 54.90,
"forma_pagamento": "PIX",
"endereco": {
"logradouro": "Rua 28 de Agosto", "numero": "2200",
"bairro": "Centro", "cidade": "Guaramirim",
"uf": "SC", "cep": "89270-000",
"complemento": "Apto 32", "referencia": "Próximo ao mercado"
}
}
},
{ "external_id": "pedido-8842", "text": "texto integral da comanda..." },
{ "external_id": "pedido-8843", "image": { "fileName": "comanda.jpg", "data": "<base64>" } }
]
}
| Forma | Quando usar | Observações |
|---|---|---|
structured | Você já tem os campos no seu sistema | Mais rápido e preciso. Só endereco é obrigatório. Sem custo adicional |
text | Só tem o texto cru da comanda | Máx. 20.000 caracteres. Processado por IA, sem custo adicional |
image | Só tem foto/scan da comanda | Base64, máx. ~6 MB. OCR + IA — adicional de R$ 0,05/pedido (repasse do custo de processamento) |
200{
"success": true,
"mapsLink": "https://www.google.com/maps/dir/?api=1&travelmode=driving&waypoints=...&destination=...",
"mapsAppLink": "https://www.google.com/maps/dir/?api=1&...",
"orders": [
{
"external_id": "pedido-8841",
"order": 1,
"numero_pedido": "8841",
"cliente_nome": "Maria Silva",
"telefone": "47999990000",
"valor_total": 54.90,
"forma_pagamento": "PIX",
"troco": null,
"endereco": { "logradouro": "Rua 28 de Agosto", "numero": "2200", "bairro": "Centro", "cidade": "Guaramirim", "uf": "SC" },
"lat": -26.4702,
"lng": -49.0028,
"number_not_confirmed": false,
"city_mismatch": false
}
],
"rejected": [
{ "external_id": "pedido-8842", "reason": "NO_GOOGLE_RESULTS" }
]
}
| Campo | Significado |
|---|---|
orders[] | Já na ordem otimizada de entrega (order: 1, 2, 3...) |
mapsLink | Abre a rota completa no Google Maps, paradas na ordem certa |
number_not_confirmed | true = o número exato não foi confirmado pelo geocoder; a coordenada é do logradouro — avise o entregador |
city_mismatch | true = a cidade encontrada difere da informada, mas está dentro do raio aceitável |
rejected[] | Pedidos não roteirizáveis, com o motivo — não bloqueiam os demais. Motivos: INSUFFICIENT_DATA, NO_GOOGLE_RESULTS, EXTRACT_FAILED, EXTRACT_EMPTY |
structured quando tiver os dados · cacheie o origin geocodificado · sempre envie external_id (é como você reconcilia resposta e rejeitados) · trate os rejected no seu operador · agrupe pedidos da mesma leva numa única chamada — a ordenação só faz sentido com os pedidos juntos.
Mesmo payload do /v1/resolve — mas em vez de devolver só os dados, a RotaLink cria uma sessão de entrega e devolve a URL que o seu app abre no webview do entregador (com a sua marca). Guia completo com código Android/iOS, acompanhamento e segurança: baixe no painel do parceiro.
| Endpoint | O que faz |
|---|---|
POST/v1/sessions | Cria a sessão (resolve os endereços) e devolve session_id + url assinada. ⚠️ A url só aparece nesta resposta — guarde-a. Validade: 12h |
GET/v1/sessions/:id | Status da corrida: delivery_status por pedido (pendente → entregue), telefone coletado, completed automático na última entrega |
POST/v1/sessions/:id/refresh | Nova URL/token (sessão expirada ou token vazado). Sessão concluída não renova (404) |
telefone do cliente habilita os 4 botões de aviso por WhatsApp · localizador (iFood) habilita copiar em 1 clique + abrir o site de confirmação · sem telefone, o entregador coleta na porta e o número volta pra você via GET/webhook.
Configure a URL no painel (card Webhooks, com botão "Enviar teste"). Todo POST vem assinado — valide antes de processar.
| Evento | Quando dispara |
|---|---|
delivery.confirmed | Entregador confirmou uma entrega (session_id, external_id, numero_pedido, delivered_at) |
phone.collected | WhatsApp coletado na porta (session_id, external_id, telefone) |
session.completed | Última entrega da rota concluída (session_id, total_orders) |
webhook.test | Botão de teste do painel |
| Header | Uso |
|---|---|
X-RotaLink-Signature | sha256=<hmac> — HMAC-SHA256 do corpo bruto com o signing secret (exibido uma vez ao salvar a URL) |
X-RotaLink-Delivery | ID único da entrega — use para idempotência (retries reenviam o mesmo id) |
Esperamos 2xx em até 8s. Falhou? Retry com backoff exponencial (30s → 1h), até 8 tentativas.
| HTTP | error | Significado |
|---|---|---|
| 400 | ORIGIN_REQUIRED | origin ausente ou sem lat/lng nem endereco |
| 400 | ORDERS_REQUIRED | orders vazio ou ausente |
| 400 | TOO_MANY_ORDERS | Mais de 25 pedidos na chamada |
| 400 | INVALID_ORDER | Item sem forma de entrada válida (detalhe em message) |
| 401 | INVALID_API_KEY | Key ausente, inválida ou revogada |
| 402 | TRIAL_EXHAUSTED | Período de teste (500 pedidos / 30 dias) encerrado — fale com a RotaLink para liberar produção |
| 403 | MODEL_NOT_ENABLED | Sessões fazem parte do Modelo 2 — troque de plano no painel |
| 422 | ORIGIN_NOT_GEOCODED | Endereço de origem não geocodificável |
| 422 | NO_VALID_ADDRESSES | Nenhum pedido pôde ser geocodificado (rejected traz os motivos) |
| 429 | RATE_LIMIT_EXCEEDED | Limite de req/min excedido |
| 500 | INTERNAL_ERROR | Erro interno — repita a chamada |
| HTTP | error | Significado |
|---|---|---|
| 401 | INVALID_SESSION_TOKEN | Token da URL inválido |
| 401 | SESSION_EXPIRED | Sessão expirou (12h) — use o refresh |
| 410 | SESSION_COMPLETED | Rota já concluída |
| 404 | SESSION_NOT_FOUND | ID inexistente, de outro parceiro — ou, no refresh, sessão já concluída |