Webhooks
Webhooks permitem que a API Frota162 avise seu sistema automaticamente quando algo acontece na sua frota — sem precisar consultar a API repetidamente. Sempre que um evento ocorre, a API faz um POST para a URL cadastrada com os dados do evento em JSON.
A entrega é at-least-once: em caso de falha, o mesmo evento pode ser reenviado mais de uma vez. Trate os eventos de forma idempotente (veja Trate duplicatas).
Primeira configuração
O resto desta página é referência — payloads, tipos de evento, endpoints. Se é a sua primeira vez, siga esta ordem. Cada etapa aponta para a seção com o detalhe.
As duas primeiras etapas vêm antes do cadastro de propósito. Cadastrar um webhook com a mesma url + event_id de outro já existente devolve fbk_008, e não existe rota de atualização nem de exclusão — corrigir uma URL errada depende do suporte. Confirme que o endpoint está de pé antes de registrá-lo.
Deixe o endpoint no ar e acessível
A URL precisa ser HTTPS, ter host público e resolver para um IP público — localhost, faixas privadas e loopback são recusados no cadastro. Os critérios completos estão em Cadastrar webhook via API.
Ele também precisa devolver HTTP 200 em menos de 5 segundos. Se o seu processamento for demorado, responda primeiro e processe depois, em fila — o código está em Responda rapidamente.
Se você usa allowlist de IP no firewall, libere os quatro endereços de origem listados em IPs de origem.
Valide a assinatura no recebimento
Todo webhook chega com os mesmos headers HMAC das chamadas da API. Sem conferir o header Key, qualquer um que descubra a sua URL consegue injetar eventos falsos no seu sistema.
O código de validação está em Valide a autenticação; o que a assinatura prova (e o que ela não prova) está em Segurança dos webhooks.
Escolha o evento e cadastre
Localize o event_id do que você quer receber em Tipos de eventos — é um webhook por tipo de evento, e você pode registrar vários numa só chamada enviando um array.
O POST /key/webhooks/add e o exemplo de requisição estão em Cadastrar webhook via API.
Dispare um evento de teste
Não espere um evento real acontecer: o próprio sistema Frota162 dispara um payload fictício do tipo configurado, direto pelo perfil da empresa. O caminho na interface está em Testar o recebimento.
Aproveite para conferir o corpo recebido contra Estrutura dos payloads — é o momento de descobrir divergência de contrato, antes de valer dado real.
Acompanhe as falhas de entrega
Quando o seu servidor devolve erro ou estoura o tempo, a entrega falha e fica registrada. Dá para listar as falhas e reprocessar cada uma sem aguardar o evento acontecer de novo — os dois endpoints estão em Monitorar e reenviar webhooks.
Trate isso como parte da configuração, não como plano de contingência: a entrega é at-least-once, então o mesmo evento pode chegar duplicado desde o primeiro dia. Veja Trate duplicatas.
Tipos de eventos
| Evento | ID | Descrição |
|---|---|---|
| Nova multa cadastrada | 1 | Quando uma infração é registrada |
| Atualização de multa | 2 | Quando uma infração é atualizada |
| Nova notificação cadastrada | 3 | Quando uma notificação de infração é registrada |
| Atualização de notificação | 4 | Quando uma notificação é atualizada |
| Taxa de IPVA | 5 | Quando uma taxa de IPVA é registrada |
| Taxa de DPVAT | 6 | Quando uma taxa de DPVAT é registrada |
| Taxa de licenciamento | 7 | Quando uma taxa de licenciamento é registrada |
| Cronotacógrafo | 8 | Quando um certificado de cronotacógrafo é atualizado |
| Dados de veículo novos | 9 | Quando novos dados de um veículo são consultados |
| Atualização de dados de veículo | 10 | Quando dados de veículo são atualizados |
| Status de indicação de condutor | 11 | Cada mudança de status em uma indicação de condutor — ver Indicação de Motoristas (API v2) |
Cadastrar webhook via API
Antes de montar a chamada, a URL cadastrada precisa atender aos seguintes requisitos:
- HTTPS obrigatório — URLs
http://são rejeitadas. - Host público — endereços privados, de loopback ou reservados são rejeitados (ex.:
localhost,127.0.0.1, faixas10.x,172.16–31.x,192.168.x,169.254.x, IPv6::1e faixas privadas). - Hostname resolvível — o domínio precisa resolver para um IP público válido.
Se a URL não atender a esses critérios, o cadastro do webhook é recusado.
/key/webhooks/addcurl -X POST \
https://apidev.v1.frota162.com.br/key/webhooks/add \
-H 'Authorization: Basic SEU_ACCESS_TOKEN' \
-H 'Key: SUA_ASSINATURA_HMAC' \
-H 'cache-control: no-cache' \
-d '[{
"url": "https://seu-sistema.com/webhooks/frota162",
"event_id": 1,
"company_id": 123
}]'
Você pode cadastrar múltiplos webhooks no mesmo request enviando um array de objetos.
Resposta de sucesso:
{
"events": [
{
"result": {
"url": "https://seu-sistema.com/webhooks/frota162",
"event_id": "1",
"client_id": "123",
"id": 456
},
"code": 201
}
],
"error": false,
"code": "fbk_200"
}
Enviar um webhook com a mesma url + event_id de um já cadastrado retorna erro fbk_008 — a entrada existente não é sobrescrita. A API não expõe rota de atualização ou exclusão de webhooks.
Estrutura dos payloads
- Multas
- Notificações
- IPVA / DPVAT / Licenciamento
- Cronotacógrafo
- Veículo
event_type: "frame"
{
"event_type": "frame",
"id": 1,
"company_id": 1,
"car": {
"car_id": 1,
"car_plate": "ABC1234"
},
"frame": {
"ait": "R1111111",
"type": "MULTA",
"at": "2024-01-11",
"time": "20:26:00",
"expiration_at": "2024-03-02",
"code": "74550",
"description": "TRANSITAR EM VELOCIDADE SUPERIOR A MAXIMA PERMITIDA EM ATE 20%",
"address": "RUA AFONSO GARBUIO, N. 790",
"city_code": "3550308",
"city": "SAO PAULO",
"state": "SP",
"points": 4,
"amount": 130.16,
"discount_amount": 104.13,
"driver_indicate": 1
},
"organization": {
"organization_code": 1,
"organization_name": "DETRAN-SP"
},
"driver": {
"id": 456,
"indicate": "2024-01-20T10:00:00.000Z",
"indicated_recieve_doc_at": "2024-01-21T10:00:00.000Z",
"indicated_sent_doc_org_at": "2024-01-22T10:00:00.000Z",
"name": "JOAO DA SILVA",
"license": "12345678900",
"identification": "123456789",
"identification_state": "SP",
"tax_id": "12345678909",
"address": "RUA EXEMPLO",
"address_number": "100",
"address_zip_code": "01000-000",
"distric": "SP",
"city": "SAO PAULO",
"state": "SP"
},
"payment": {
"paid": true,
"at": "2024-02-01",
"amount": 104.13
},
"link": "https://boleto.example.com/abc123",
"sne_boleto_status": "PAGO",
"created_at": "2024-04-05T20:49:18.000Z",
"updated_at": "2024-04-06T09:00:00.000Z"
}
O campo driver_indicate indica se o condutor já foi identificado: 0 = não indicado, 1 = indicado. Os campos de driver (dados do condutor, CNH, CPF, endereço) são preenchidos quando driver_indicate for 1. O objeto frame traz também city_code (código IBGE da cidade), e no nível raiz link (boleto) e sne_boleto_status (status do boleto no SNE).
Objeto payment
O bloco payment descreve a situação de pagamento da multa:
| Campo | Tipo | Descrição |
|---|---|---|
paid | boolean | Indica se a multa consta como paga. |
at | string | null | Data do pagamento no formato YYYY-MM-DD. null quando não há data registrada. |
amount | number | Valor pago. 0 quando não há valor registrado. |
paid pode ser true com at: null e amount: 0Nem sempre a data e o valor do pagamento estão disponíveis: paid pode vir true com at em null e amount em 0. Use paid como fonte de verdade para saber se a multa foi paga; não infira o pagamento a partir de at/amount.
event_type: "notification"
{
"event_type": "notification",
"id": 1,
"company_id": 1,
"car": {
"car_id": 1,
"car_plate": "ABC1234"
},
"notification": {
"ait": "N1234567",
"at": "2024-01-11",
"time": "20:26:00",
"indication_limit_at": "2024-02-11",
"code": "74550",
"description": "TRANSITAR EM VELOCIDADE SUPERIOR A MAXIMA PERMITIDA",
"address": "RUA EXEMPLO, 100",
"city_code": "3550308",
"city": "SAO PAULO",
"state": "SP",
"amount": 130.16,
"discount_amount": 104.13,
"driver_indicate": 1,
"points": 4
},
"organization": {
"organization_code": 1,
"organization_name": "DETRAN-SP"
},
"driver": {
"id": 456,
"indicate": "2024-01-20T10:00:00.000Z",
"indicated_recieve_doc_at": "2024-01-21T10:00:00.000Z",
"indicated_sent_doc_org_at": "2024-01-22T10:00:00.000Z",
"name": "JOAO DA SILVA",
"license": "12345678900",
"identification": "123456789",
"identification_state": "SP",
"tax_id": "12345678909",
"address": "RUA EXEMPLO",
"address_number": "100",
"address_zip_code": "01000-000",
"distric": "SP",
"city": "SAO PAULO",
"state": "SP"
},
"link": "https://boleto.example.com/abc123",
"linkNotification": "https://notificacao.example.com/abc123",
"sne_boleto_status": "PENDENTE",
"created_at": "2024-04-05T20:49:18.000Z",
"updated_at": "2024-04-06T09:00:00.000Z"
}
Os campos seguem o mesmo padrão de Multas. Exclusivos de notificação: indication_limit_at (prazo-limite para indicar o condutor) e linkNotification (link da notificação, além do link do boleto).
event_type: "DEBITOS-IPVA" / "DEBITOS-DPVAT" / "DEBITOS-LICENCIAMENTO"
O mesmo formato se aplica aos três — o event_type muda conforme o tributo.
{
"event_type": "DEBITOS-IPVA",
"id": 1,
"company_id": 1,
"car": {
"car_id": 1,
"car_plate": "ABC1234"
},
"ammount": 1250.00,
"exercise": "2024",
"occurrence": "01",
"expedition_at": "2024-01-31",
"quote": 1,
"created_at": "2024-01-15T10:00:00.000Z",
"updated_at": null
}
ammount é o valor do tributo, exercise o ano-exercício e quote a cota/parcela.
DEBITOS-Os event_type de débito (DEBITOS-IPVA, DEBITOS-DPVAT, DEBITOS-LICENCIAMENTO) são os únicos que vem em UPPERCASE com o prefixo DEBITOS-. Todos os demais eventos usam event_type em lowercase (frame, notification, cronotacografo, car, driver_indication).
A comparação no seu handler deve ser exata — não aplique toLowerCase() nem qualquer normalização de case antes do match. Se normalizar, DEBITOS-IPVA vira debitos-ipva e nunca vai bater.
Comportamento de created_at / updated_at
Eventos de débito são disparados apenas na criação do registro — não há disparo em atualização. Por isso, updated_at sempre chega como null no payload.
| Campo | Valor no payload | Motivo |
|---|---|---|
created_at | timestamp da criação | O webhook só dispara quando o débito é registrado pela primeira vez |
updated_at | null | Atualizações posteriores do débito não geram webhook |
Como o webhook de débito só dispara na criação, todo payload recebido representa um novo débito — não é necessário diferenciar criação de atualização. Trate o evento como inserção.
Escopo dos tributos com webhook
Apenas os três tributos abaixo geram eventos de webhook:
event_type | Tributo |
|---|---|
DEBITOS-IPVA | IPVA |
DEBITOS-DPVAT | DPVAT |
DEBITOS-LICENCIAMENTO | Licenciamento |
Outros tipos de débito (DETRAN, DER, DERSA, CETESB, RENAINF, municipais, polícia rodoviária) são registrados no sistema, mas não geram webhook — nenhum evento é disparado para esses tributos.
event_type: "cronotacografo"
{
"event_type": "cronotacografo",
"id": 1,
"company_id": 1,
"car": {
"id": 1,
"rim": "22.5",
"tire": "295/80",
"renavam": "00123456789",
"plate": "ABC1234",
"chassi": "9BWZZZ377VT004251"
},
"gru": {
"number": "00190000090123456789",
"ammount": "150.00",
"payment_at": "2024-01-10T14:00:00.000Z"
},
"result": {
"issue_at": "2024-01-01T00:00:00.000Z",
"expiration_at": "2025-01-01T00:00:00.000Z",
"document": "CERTIFICADO",
"document_number": "123456",
"responsible": "FULANO DE TAL"
},
"link": "https://link-do-certificado.pdf",
"sealing": {
"at": "2024-01-01T00:00:00.000Z",
"state": "SP",
"serie": "ABC123",
"brand": "VDO",
"model": "1381"
},
"rehearsal": {
"state": "SP",
"point": "POSTO EXEMPLO",
"at": "2024-01-01T00:00:00.000Z",
"valid": "2025-01-01T00:00:00.000Z",
"updated": "2024-01-01T00:00:00.000Z",
"standard": "PADRAO",
"read_at": "2024-01-01T00:00:00.000Z"
},
"created_at": "2024-01-15T10:00:00.000Z",
"updated_at": null
}
event_type: "car"
{
"event_type": "car",
"id": 1,
"company_id": 1,
"plate": "ABC1234",
"renavam": "00123456789",
"kind": "AUTOMÓVEL",
"chassi": "9BWZZZ377VT004251",
"state": "SP",
"type": "PASSEIO",
"branding": "TOYOTA",
"model": "COROLLA",
"manufactoryYear": "2023",
"color": "BRANCO",
"result": {
"success": true,
"message": "OK"
}
}
Indicação de condutor (event_type: "driver_indication") — API v2
Disparado a cada mudança de status de uma indicação de condutor. Consulte a lista completa de status no módulo de Indicação de Motoristas.
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"driver_id": 12345,
"company_id": 789,
"event_type": "driver_indication",
"status": "CONFIRMED",
"can_reindicate": false,
"vehicle_type": "CAR",
"signer_type": "OWNER",
"notification_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"created_at": "2026-05-14T10:00:00.000Z",
"updated_at": "2026-05-14T10:30:00.000Z"
}
wrong_documentsQuando status for wrong_documents, o payload inclui o campo adicional "can_reindicate": true, indicando que a indicação pode ser corrigida e reenviada.
Segurança dos webhooks
Cada requisição de webhook inclui os mesmos headers de autenticação HMAC usados nas chamadas da API:
Authorization: Basic {SEU_ACCESS_TOKEN}
Key: {ASSINATURA_HMAC}
Content-Type: application/json
Valide esses headers no seu servidor para garantir que o webhook veio da Frota162. O código de validação está na seção Boas práticas abaixo.
IPs de origem
Os webhooks são enviados a partir dos seguintes IPs:
20.84.24.3
18.234.9.54
35.231.115.63
34.227.129.114
Configure seu firewall para aceitar requisições desses IPs caso use allowlisting de IPs no seu servidor.
Boas práticas no recebimento
Responda rapidamente
Seu endpoint deve responder com HTTP 200 em menos de 5 segundos. Se o processamento for demorado, salve o payload em fila e processe de forma assíncrona.
app.post('/webhooks/frota162', async (req, res) => {
// Responda imediatamente
res.status(200).send('OK');
// Processe de forma assíncrona
await fila.adicionar(req.body);
});
Valide a autenticação
const crypto = require('crypto');
app.post('/webhooks/frota162', (req, res) => {
const keyHeader = req.headers['key'];
const assinaturaEsperada = crypto
.createHmac('sha256', process.env.FROTA_SECRET_KEY)
.update(process.env.FROTA_ACCESS_TOKEN)
.digest('hex');
if (keyHeader !== assinaturaEsperada) {
return res.status(401).send('Não autorizado');
}
res.status(200).send('OK');
});
Trate duplicatas
A Frota162 pode reenviar o mesmo webhook em caso de falha. Use o id do evento para detectar e ignorar duplicatas.
const eventosProcessados = new Set();
app.post('/webhooks/frota162', async (req, res) => {
const { id, event_type } = req.body;
const chave = `${event_type}_${id}`;
if (eventosProcessados.has(chave)) {
return res.status(200).send('Já processado');
}
eventosProcessados.add(chave);
// ... processar evento
res.status(200).send('OK');
});
Testar o recebimento
Depois de cadastrar o webhook e preparar seu endpoint, você pode disparar um evento de teste diretamente pelo sistema Frota162 — sem esperar um evento real acontecer e sem precisar abrir chamado no suporte. O disparo envia um payload com dados fictícios do tipo de evento configurado, ideal para validar a conexão e a autenticação do seu endpoint.
Passo a passo
- Acesse o perfil da empresa no sistema Frota162.
- Role a página até a seção Webhooks.
- Localize o webhook cadastrado. Ao lado do botão Logs, clique em Testar webhook.
- O sistema dispara um evento com dados fictícios correspondentes ao tipo de evento configurado naquele webhook.
- Confira no seu endpoint se o
POSTchegou — com os headersAuthorizationeKey(veja Segurança dos webhooks) e o corpo no formato esperado (veja Estrutura dos payloads).
O disparo de teste serve apenas para validação de conexão. Os dados enviados são fictícios e não correspondem a multas, notificações ou veículos reais.
Se o teste não chegar, verifique os erros de entrega em Monitorar e reenviar webhooks e confirme que sua URL aceita POST com content-type JSON e responde rapidamente (veja Responda rapidamente).
Monitorar e reenviar webhooks
Quando seu servidor retorna erro ou não responde dentro do limite de tempo, a entrega falha e fica registrada no log de erros. Use os endpoints abaixo para inspecionar falhas e reprocessá-las sem precisar aguardar que o evento ocorra novamente.
Listar erros de entrega
Retorna os webhooks que não foram entregues com sucesso. Cada entrada inclui o id do log de erro (necessário para reenvio), a URL de destino, o payload que falhou e o código de resposta recebido (ou o motivo do timeout).
/key/webhooks-errors?pagination[page]=1&pagination[perpage]=50curl -X GET \
'https://apidev.v1.frota162.com.br/key/webhooks-errors?pagination[page]=1&pagination[perpage]=50' \
-H 'Authorization: Basic SEU_ACCESS_TOKEN' \
-H 'Key: SUA_ASSINATURA_HMAC' \
-H 'cache-control: no-cache'
O parâmetro
pagination[perpage]aceita no máximo 100 itens por página. Valores acima de 100 são limitados a 100.
Reenviar um webhook com erro
Reprocessa uma entrega específica usando o id retornado pelo endpoint de listagem acima.
/key/webhooks/logs/{evento_id}/resendcurl -X POST \
https://apidev.v1.frota162.com.br/key/webhooks/logs/123/resend \
-H 'Authorization: Basic SEU_ACCESS_TOKEN' \
-H 'Key: SUA_ASSINATURA_HMAC' \
-H 'cache-control: no-cache'
Substitua
123peloiddo log de erro obtido na listagem acima.