Webhooks
Eventos enviados para o seu servidor à medida que acontecem: um estafeta à porta, uma entrega concluída, um veículo que não se mexe.
Nesta página
Os webhooks vêm com o seguimento de frota. Referência dos webhooks
Eventos
| Evento | Quando | data |
|---|---|---|
task.created | Foi criada uma entrega | task |
task.assigned | A entrega foi atribuída a um veículo (ou outro assumiu-a) | task |
task.arriving | O estafeta está a menos de arrivingS da tarefa (3 minutos por omissão) ou a menos de 250 m do ponto de entrega | task |
task.completed | Marcada como entregue | task |
task.failed | Marcada como falhada | task |
vehicle.offline | Um veículo não enviou nada durante offlineAfterS (10 minutos por omissão), uma vez por silêncio | vehicle |
task.updated | Alterou a entrega (PATCH /tasks/{id}); changed lista os campos | task, changed |
task.started | Um motorista N-Ways iniciou a entrega (ligação de motoristas) | task |
delivery.rated | O cliente avaliou a entrega (1 a 5 estrelas, visível apenas para a sua empresa) | task, rating |
zone.entered, zone.exited | Um veículo entrou ou saiu de uma das suas zonas | vehicle, zone |
connection.approved, connection.declined | Um motorista N-Ways aceitou ou recusou o seu convite | connection ou invite |
connection.revoked, connection.ended | O motorista deixou de partilhar consigo, ou a sua empresa terminou a ligação | connection |
driver.availability_changed | Um motorista ligado ativou ou desativou Disponível para si | connection |
dispatch.offered, .accepted, .declined, .expired, .withdrawn | Um pedido de entrega a um motorista N-Ways, e o que lhe aconteceu | offer, task |
Equipas de ERP (SAP, Odoo, Microsoft Dynamics): veja Ligar o seu ERP para a correspondência de campos, a verificação de assinaturas em C#, Groovy e Python, e a reconciliação com a API de exportação.
Os alertas (uma área abandonada, uma zona em que se entrou, um veículo em silêncio ou parado) chegam também como eventos asset.*, e podem seguir por e-mail, notificação, Google Sheets, Telegram ou Excel: veja Alertas e reencaminhamento.
Adicionar um ponto de receção
Indique um endereço HTTPS no seu servidor e os eventos que pretende receber (nenhum na lista significa todos). A resposta contém o secret de assinatura do ponto de receção: só é mostrado agora, por isso guarde-o.
curl -X POST "https://nways.ng/maps/v1/fleet/webhooks" \
-H "X-NWays-Api-Key: A_SUA_CHAVE_DE_SERVIDOR" -H "Content-Type: application/json" \
-d '{"url": "https://example.com/nways/events", "events": ["task.arriving", "task.completed", "task.failed"]}'POST /webhooks/{id}/test envia um evento ping para verificar que funciona; GET /webhooks/{id}/deliveries mostra o que foi enviado, as respostas do seu servidor e a próxima nova tentativa.
O que chega, e como verificar que vem de nós
Cada evento é um POST com um corpo JSON (id, type, createdAt, data) e estes cabeçalhos:
| Cabeçalho | Valor |
|---|---|
X-NWays-Event | O tipo de evento |
X-NWays-Delivery | O identificador deste envio (dlv_…), o mesmo em cada nova tentativa |
X-NWays-Signature | t=<unix seconds>,v1=<hex>, em que v1 é o HMAC-SHA256 de "<t>.<raw body>" com o segredo do seu ponto de receção |
Verifique a assinatura sobre o corpo em bruto, antes de o analisar, e recuse uma marca temporal com mais de 5 minutos de diferença:
import { createHmac, timingSafeEqual } from 'node:crypto'
import { createServer } from 'node:http'
const SECRET = process.env.NWAYS_WEBHOOK_SECRET
function verified(raw, header) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false
const want = createHmac('sha256', SECRET).update(`${parts.t}.${raw}`).digest('hex')
return want.length === parts.v1?.length && timingSafeEqual(Buffer.from(want), Buffer.from(parts.v1))
}
createServer((req, res) => {
let raw = ''
req.on('data', (c) => (raw += c))
req.on('end', () => {
if (!verified(raw, req.headers['x-nways-signature'] ?? '')) return res.writeHead(401).end()
const event = JSON.parse(raw)
if (event.type === 'task.arriving') console.log(`Encomenda ${event.data.task.id}: o estafeta está a chegar`)
res.writeHead(204).end() // responda depressa; faça o trabalho demorado depois
})
}).listen(8080)import hashlib
import hmac
import os
import time
SECRET = os.environ["NWAYS_WEBHOOK_SECRET"].encode()
def verified(raw: bytes, header: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
if abs(time.time() - int(parts.get("t", 0))) > 300:
return False
want = hmac.new(SECRET, parts["t"].encode() + b"." + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, parts.get("v1", ""))Novas tentativas e ordem
- Responda com qualquer código 2xx em menos de 10 segundos. Qualquer outra resposta leva a nova tentativa após 30 segundos, 2 minutos, 10 minutos, 30 minutos, 1, 3, 6 e 12 horas, e depois o envio é marcado como falhado.
- Um evento pode chegar mais de uma vez ou fora de ordem: guarde os
iddos eventos já tratados, e confie nostatusda tarefa em vez da ordem de chegada dos eventos. - Os redirecionamentos não são seguidos, e o endereço tem de ser público.
- Um segredo foi divulgado?
POST /webhooks/{id}/rotate-secretdá um novo de imediato.