Entrega, reenvios e idempotência
Tempo limite, tentativas, espera entre elas, ordem dos eventos, como evitar processar duas vezes e dicas para testar um receptor de webhook.
Receber um webhook parece simples, mas três fatos do mundo real decidem se a sua integração é confiável: a rede falha, o mesmo aviso pode chegar duas vezes e dois avisos podem chegar na ordem trocada. Esta página descreve exatamente o que a Venddor garante e o que cabe ao seu receptor.
O que conta como entrega bem-sucedida
A plataforma faz um POST para a sua URL e espera a resposta por até 30 segundos (conexão, envio e leitura somados). O resultado cai em um destes casos:
| Resposta do seu servidor | Resultado | Reenvia? |
|---|---|---|
2xx ou 3xx final | Sucesso | Não |
4xx | Falha registrada como HTTP 4xx | Não |
5xx | Falha registrada como HTTP 5xx | Sim |
| Sem resposta, recusa de conexão, erro de TLS, DNS, tempo esgotado | Falha com a mensagem do erro | Sim |
Outros detalhes do envio:
- A plataforma segue até 5 redirecionamentos e valida cada destino. Um redirecionamento para endereço interno é recusado.
- Não há conexão reaproveitada: cada tentativa abre uma conexão nova.
- Do corpo da sua resposta, a plataforma guarda só os primeiros 4096 bytes no registro. Não devolva páginas grandes.
- URLs
httpsão aceitas, mas usehttps: o corpo carrega dados de clientes e pedidos.
Tentativas e espera
Uma entrega automática tem no máximo 3 tentativas.
| Tentativa | Quando acontece |
|---|---|
| 1 | Imediatamente, assim que o evento ocorre |
| 2 | 30 segundos depois da falha da tentativa 1 |
| 3 | 5 minutos depois da falha da tentativa 2 |
Só 5xx e falhas de rede disparam nova tentativa. Um 4xx (inclusive 408 e 429) encerra a entrega: se o seu servidor está sobrecarregado, responda 503, que será tentado de novo. Cada tentativa gera uma linha no registro de entregas com o número em attempt.
Depois da terceira falha a plataforma desiste. Duas saídas: reenviar manualmente pela rota retry quando o seu servidor voltar, ou reconciliar lendo a API (por exemplo, listar os pedidos alterados desde a última sincronização).
Ordem dos eventos
Não há garantia de ordem. Cada evento é enviado em paralelo, e a espera de uma tentativa de reenvio faz um evento antigo chegar depois de um novo. Exemplo real: o order.statusChanged "pending para processing" falha, o seguinte "processing para shipped" passa, e 30 segundos depois o primeiro chega.
Formas seguras de lidar com isso:
- Compare o
timestampdopayloadcom o último que você processou para aquele pedido e ignore o mais velho. - Leia o estado atual. Use o evento como gatilho e consulte o recurso na API (Obter pedido). O que importa é o estado de agora, não o que o evento diz.
- Em
order.statusChanged, useold_statusenew_statuspara detectar lacunas na sequência.
Idempotência: processar uma vez só
A entrega é pelo menos uma vez. O mesmo evento pode chegar duplicado, por exemplo quando o seu servidor processou, mas a resposta se perdeu e a plataforma tentou de novo. Seu receptor deve produzir o mesmo resultado se receber o evento duas vezes.
Os eventos comuns não trazem um id de evento. O envelope tem webhook_id, que identifica o cadastro do webhook, e não o evento. A chave de deduplicação que funciona é montada a partir do próprio payload, que é idêntico em todas as tentativas do mesmo evento (o timestamp do payload não muda, ao contrário do timestamp do envelope).
import crypto from "node:crypto";
// Chave estável: o mesmo evento gera a mesma chave em qualquer tentativa.
function eventKey(envelope) {
const body = JSON.stringify(envelope.payload);
return envelope.event + ":" + crypto.createHash("sha256").update(body).digest("hex");
}
async function handle(envelope) {
const key = eventKey(envelope);
// INSERT ... ON CONFLICT DO NOTHING em uma tabela com a chave como PRIMARY KEY.
const firstTime = await db.insertIfAbsent("processed_events", key);
if (!firstTime) return; // duplicado: já foi tratado
await applyBusinessLogic(envelope);
}Para os eventos de incentivo, use event.event_id, que a plataforma fornece.
Responda rápido
Faça o mínimo antes de responder: verifique a assinatura, grave o evento em uma fila ou tabela e devolva 200. O trabalho pesado (chamar o ERP, enviar e-mails) vai para um processo separado. Um receptor que demora mais de 30 segundos é tratado como falha e recebe o mesmo evento de novo, o que cria duplicatas.
Testar
- Exponha um receptor público
A URL precisa ser alcançável pela internet. Em desenvolvimento use um túnel HTTPS para a sua máquina.
localhost, IPs privados e domínios.localsão recusados no cadastro. - Envie o evento de teste
Enviar evento de teste faz uma chamada real e assinada com
event: "test"e a resposta já vem na requisição (status, tempo e erro). - Cheque a assinatura com o exemplo fixo
Use o par secret/corpo/assinatura de Verificar a assinatura para provar o seu código sem depender da rede.
- Provoque uma falha
Faça o receptor devolver
503uma vez e confira no registro de entregas a segunda tentativa 30 segundos depois (attempt: 2). - Reenvie uma entrega real
Use a rota
retrysobre uma entrega do registro para reproduzir um evento real sem precisar gerá-lo na loja. O corpo reenviado leva"retry": true.