Pular para o conteúdo
Voltar para a home

Domínios e entrega

Webhooks e eventos

Oito tipos de evento, entregues no seu endpoint com assinatura HMAC, ou consultados sob demanda em /v1/events.

A ida está em O caminho da mensagem, e termina no destinatário. Esta página começa exatamente ali.

Os oito eventos

TipoQuando dispara
sendA mensagem foi aceita e saiu daqui.
deliveryO servidor do destinatário confirmou o recebimento.
bounceDevolveu. O motivo vem em data.
complaintA pessoa marcou como spam.
rejectRecusada antes de sair, por exemplo por supressão.
rendering_failureO template não conseguiu ser montado.
openAbertura, se o tracking estiver ligado.
clickClique em link, se o tracking estiver ligado.

Para ver cada um destes acontecendo sem depender da realidade, mande para os apelidos de teste.

Registrar um webhook

shell
curl -X POST https://api.jetsend.com.br/v1/webhooks \  -H "Authorization: Bearer $JETSEND_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "url": "https://seusistema.com.br/hooks/jetsend",    "eventos": ["delivery", "bounce", "complaint"]  }'

A resposta traz o segredo da assinatura. Ele aparece uma vez; guarde. A URL precisa ser http:// ou https:// completa e apontar para um endereço público: endpoint que resolve para IP interno é recusado no cadastro, porque aceitar isso transformaria o nosso servidor numa ponte para a sua rede privada.

O que chega

json
{  "type": "bounce",  "message_id": "9f1c0f2e-6d3b-4f0a-9a1e-2c7d8b5a3e10",  "to": "cliente@exemplo.com",  "subject": "Sua fatura de setembro",  "occurred_at": "2026-09-28T14:12:03.221Z",  "data": null}

Junto vão três cabeçalhos:

  • x-jetsend-event, o tipo, igual ao type do corpo;
  • x-jetsend-timestamp, o instante em segundos;
  • x-jetsend-signature, o HMAC SHA-256.

Conferir a assinatura

A assinatura é o HMAC SHA-256 de timestamp + "." + corpo, com o seu segredo como chave. Confira antes de processar: sem isso, qualquer um que descubra a sua URL pode inventar uma devolução e fazer o seu sistema dar baixa num cliente que está ativo.

javascript
import { createHmac, timingSafeEqual } from "node:crypto";export function assinaturaConfere(req, segredo) {  const timestamp = req.headers["x-jetsend-timestamp"];  const recebida = req.headers["x-jetsend-signature"];  const corpo = req.rawBody; // o corpo CRU, antes do JSON.parse  const esperada = createHmac("sha256", segredo)    .update(`${timestamp}.${corpo}`)    .digest("hex");  const a = Buffer.from(esperada, "utf8");  const b = Buffer.from(String(recebida), "utf8");  if (a.length !== b.length) return false;  return timingSafeEqual(a, b);}

Dois detalhes que costumam morder. Use o corpo cru, antes de qualquer JSON.parse: reserializar muda espaços e a ordem das chaves, e a assinatura não bate mais. E compare com timingSafeEqual, não com ===: comparação de string vaza pelo tempo o tamanho do prefixo correto, e isso é suficiente para descobrir a assinatura tentativa a tentativa.

Consultar sem webhook

shell
curl "https://api.jetsend.com.br/v1/events?tipo=bounce&limit=50" \  -H "Authorization: Bearer $JETSEND_API_KEY"

GET /v1/events aceita messageId, tipo, limit (até 200) e cursor para paginar. Serve para reconciliar depois de uma queda do seu endpoint, quando você quer buscar o que perdeu em vez de esperar.

Lista de supressão

Devolução permanente e marcação de spam entram automaticamente na lista de supressão da sua conta, e envios seguintes para aquele endereço são recusados antes de sair. GET /v1/bloqueios lista, e DELETE /v1/bloqueios/:id remove uma entrada sua. Entradas globais da plataforma não são removíveis pela conta.