Evento `ORDER_DELAY`
Webhook disparado quando um pedido atrasa — ou quando entra em risco de atrasar. Vale para qualquer pedido com prazo de cliente, e o payload diz qual dos dois casos disparou.
Evento enviado ao seller quando um pedido fura o prazo prometido ao cliente — ou quando entra em risco de furar, se você configurou marcadores de risco. Vale para qualquer pedido que tenha prazo de cliente, com ou sem marcador.
O disparo é agendado no momento em que o pedido nasce, a partir do prazo informado na criação, e acontece no instante exato desse prazo (ou da antecedência da regra de risco). Nesse instante a Abbiamo revalida o pedido: se ele já foi entregue, cancelado, baixado manualmente ou devolvido, nada é enviado.
Para assinar, crie um webhook em Configurações → Webhooks apontando para o seu endpoint e selecione o evento ORDER_DELAY.
Os dois gatilhos
O campo trigger diz por que o evento chegou. Ele é a primeira coisa que o seu consumidor deve olhar.
trigger | Quando dispara | O que vem no payload |
|---|---|---|
DELAYED | O prazo prometido ao cliente estourou e o pedido não foi concluído | overdue: true, risk_marker: null, rule_id: null |
RISK_MARKER | Uma regra de risco que você configurou acendeu um marcador antes do prazo | risk_marker preenchido, rule_id preenchido, overdue normalmente false |
DELAYED é automático e vale para todo pedido com prazo de cliente — não precisa configurar nada. RISK_MARKER só existe se você criou regras em Configuração → Marcadores de risco de entrega.
Um mesmo pedido pode gerar os dois: primeiro o RISK_MARKER (faltando 30 min), depois o DELAYED (quando o prazo estourou de fato).
Este evento não é uma mudança de status. O pedido continua no status em que estava — o campo status vem só como contexto do momento do disparo. Se você já trata ORDER_STATUS_CHANGE, trate este num caminho separado.
Duas datas diferentes, não confunda. Este evento usa o promised_delivery_date — o prazo que você prometeu ao cliente final e nos enviou em POST /v2/order. Não é o expected_delivery_date do ORDER_STATUS_CHANGE, que é o prazo combinado com a transportadora. O ORDER_DELAY mede o compromisso com o cliente, não com o parceiro logístico.
Estrutura base
A cada disparo, a Abbiamo faz um POST no seu endpoint com este corpo:
{
"event_type": "ORDER_DELAY",
"trigger": "DELAYED",
"order_id": "3f9a1c22-0000-0000-0000-000000000000",
"order_number": "1042",
"invoice_number": "000123456",
"external_order_id": "PED-98213",
"tracking": "AB12CD34EF",
"seller_id": "8c1e4b70-0000-0000-0000-000000000000",
"seller_group_id": "b7d2f011-0000-0000-0000-000000000000",
"seller_identifier": "loja-centro",
"order_type": "DELIVERY",
"status": "START_DELIVERY",
"sub_status": null,
"delivery_type": "BEE",
"promised_delivery_date": "2026-07-27T21:00:00.000Z",
"threshold_minutes": 0,
"minutes_to_deadline": 0,
"overdue": true,
"risk_marker": null,
"rule_id": null,
"event_at": "2026-07-27T21:00:03.482Z",
"timestamp": 1785186003482
}Glossário de campos
| Campo | Tipo | Notas |
|---|---|---|
event_type | string | sempre "ORDER_DELAY" |
trigger | "DELAYED" | "RISK_MARKER" | por que o evento chegou — veja a tabela acima |
order_id | string (uuid) | identificador do pedido na Abbiamo |
order_number | string | número do pedido no painel |
invoice_number | string | null | número da nota fiscal |
external_order_id | string | null | seu identificador, enviado na criação |
tracking | string | código de rastreio público |
seller_id | string (uuid) | filial dona do pedido |
seller_group_id | string (uuid) | marca (seller group) |
seller_identifier | string | null | identificador externo da filial |
order_type | string | DELIVERY, TAKEOUT, RETURN… |
status | string | status do pedido no momento do disparo (contexto, não mudança) |
sub_status | string | null | sub-status correspondente |
delivery_type | string | null | transportadora atribuída, ou null se ainda não despachado. Mesmo vocabulário do delivery_type do ORDER_STATUS_CHANGE |
promised_delivery_date | ISO datetime | prazo prometido ao cliente que serviu de âncora — o mesmo valor que você enviou em POST /v2/order |
threshold_minutes | number | antecedência da regra; sempre 0 quando trigger = "DELAYED" |
minutes_to_deadline | number | minutos restantes até o prazo; negativo se já estourou |
overdue | boolean | true quando o prazo já passou no momento do disparo |
risk_marker | objeto | null | null quando trigger = "DELAYED" |
risk_marker.id | string (uuid) | marcador de risco aplicado |
risk_marker.name | string | nome que você deu ao marcador (ex.: "Risco de Entrega Grave") |
risk_marker.color | string | cor em hexadecimal, a mesma exibida no painel |
rule_id | string (uuid) | null | regra de risco que originou o disparo; null quando trigger = "DELAYED" |
event_at | ISO datetime | data/hora do disparo |
timestamp | number | mesmo instante em epoch (ms) |
Garantias de entrega
Leia esta seção antes de escrever o consumidor — as garantias aqui são diferentes das do ORDER_STATUS_CHANGE.
- Entrega é at-least-once: deduplique do seu lado. O normal é chegar um evento por gatilho, mas uma repetição é possível. Trate
order_id+trigger(+risk_marker.id, quando houver) como chave e ignore o que já processou — é a única garantia da qual vale depender. - Um
RISK_MARKERpor par (pedido, marcador). Se duas regras acendem o mesmo marcador no mesmo pedido, chega um evento — o da primeira que vencer. Regras que acendem marcadores diferentes geram eventos distintos. - Nada é enviado para pedido já concluído. No instante do disparo o pedido é revalidado:
SUCCESSFUL,CANCELED,MANUAL_HANDLE(baixa manual) eRETURNEDcancelam o envio silenciosamente. - Prazo em branco não dispara. Pedido sem
promised_delivery_datenunca geraORDER_DELAY. O prazo é lido na criação do pedido — é ali que o disparo é agendado. - Retirada em loja fica de fora. Pedidos
TAKEOUTnão têm prazo de entrega ao cliente — é o mesmo recorte da coluna Situação de entrega, que mostra "Sem info" para eles. - Não há evento de "saiu do atraso". O disparo é de mão única; a conclusão você recebe pelo
ORDER_STATUS_CHANGEcomstatus: "SUCCESSFUL". - Retentativas: até 3 tentativas com timeout de 20s por chamada, igual aos demais webhooks. Todos os disparos ficam auditáveis em Configurações → Logs → Webhooks.
Exemplos
{
"event_type": "ORDER_DELAY",
"trigger": "DELAYED",
"status": "START_DELIVERY",
"promised_delivery_date": "2026-07-27T21:00:00.000Z",
"threshold_minutes": 0,
"minutes_to_deadline": 0,
"overdue": true,
"risk_marker": null,
"rule_id": null
}{
"event_type": "ORDER_DELAY",
"trigger": "RISK_MARKER",
"status": "START_DELIVERY",
"promised_delivery_date": "2026-07-27T21:00:00.000Z",
"threshold_minutes": 30,
"minutes_to_deadline": 30,
"overdue": false,
"risk_marker": {
"id": "d81f9a3c-0000-0000-0000-000000000000",
"name": "Risco de Entrega Grave",
"color": "#D92D20"
},
"rule_id": "0a55c7e2-0000-0000-0000-000000000000"
}{
"event_type": "ORDER_DELAY",
"trigger": "DELAYED",
"status": "PENDING",
"promised_delivery_date": "2026-07-27T18:00:00.000Z",
"threshold_minutes": 0,
"minutes_to_deadline": -45,
"overdue": true,
"risk_marker": null,
"rule_id": null
}Como consumir
O caso de uso mais direto é abrir um alerta interno (ticket, mensagem no canal do time, linha num painel) sem depender de alguém olhando a lista de Pedidos.
app.post('/abbiamo/webhook', (req, res) => {
const e = req.body
if (e.event_type !== 'ORDER_DELAY') return res.sendStatus(200)
if (e.trigger === 'DELAYED') {
abrirOcorrencia(e.order_id, `Pedido ${e.order_number} atrasou`)
} else {
avisarTime(e.order_id, `${e.order_number}: ${e.risk_marker.name}`)
}
res.sendStatus(200)
})Sugestões práticas:
- Ramifique sempre pelo
trigger. UmRISK_MARKERé um aviso preventivo; umDELAYEDé um fato consumado. Tratar os dois igual gera ruído no time. - Deduplique por
order_id+trigger(+risk_marker.id, quando houver). O mesmo pedido gera umRISK_MARKERe depois umDELAYED— são eventos distintos —, e a entrega é at-least-once. minutes_to_deadlinejá vem calculado a partir dopromised_delivery_date— não recalcule se o seu servidor estiver em outro fuso.- Combine com o
ORDER_STATUS_CHANGE: ao receberSUCCESSFULpara um pedido que atrasou, feche o alerta.