Appearance
Webhooks
Configure um endpoint HTTPS para receber eventos em tempo real (entrega, bounce, abertura, clique, descadastro, recebimento de e-mail).
Criar um webhook
POST /v1/webhooksjson
{
"url": "https://meuservico.com/webhooks/viapost",
"event_types": ["delivered", "hard_bounce", "open", "click"]
}Tipos de evento suportados: queued, sent, delivered, deferred, soft_bounce, hard_bounce, complaint, open, click, unsubscribe, rejected, failed, inbound.received.
A url não pode apontar para um endereço IP privado/loopback (proteção anti-SSRF).
Resposta — 201 Created:
json
{
"endpoint": {
"id": "uuid",
"url": "https://meuservico.com/webhooks/viapost",
"event_types": ["delivered", "hard_bounce"],
"enabled": true,
"max_attempts": 8,
"created_at": "..."
},
"secret": "base64-aleatorio-32-bytes"
}WARNING
secret é retornado apenas nesta resposta e nunca pode ser recuperado depois — guarde-o com segurança, é usado para validar a assinatura dos payloads recebidos.
Listar webhooks
GET /v1/webhooks200 — {"webhooks": [ {endpoint}, ... ]} — nunca inclui o secret.
Remover um webhook
DELETE /v1/webhooks/{id}204 No Content.
Formato do payload entregue
Cada evento é entregue como POST ao endpoint configurado, com os seguintes headers:
| Header | Descrição |
|---|---|
Content-Type | application/json |
X-ViaPost-Event | Tipo do evento (ex.: delivered, open) |
X-ViaPost-Delivery | UUID único desta entrega |
X-ViaPost-Signature | sha256=<hmac-sha256 hex do corpo> |
Corpo para eventos de envio (queued, sent, delivered, bounced, open, click etc.):
json
{
"event_type": "delivered",
"message_id": "uuid",
"recipient": "cliente@exemplo.com",
"occurred_at": "2026-08-29T12:00:00Z"
}Eventos click incluem também click_url.
Corpo para inbound.received:
json
{
"inbound_message_id": "uuid",
"from": "remetente@externo.com",
"to": "contato@meudominio.com",
"subject": "Assunto",
"received_at": "2026-08-29T12:00:00Z",
"attachments": [
{ "filename": "arquivo.pdf", "content_type": "application/pdf", "size_bytes": 45213 }
],
"raw_message_url": "https://.../presigned-url-eml"
}Validando a assinatura
Calcule o HMAC-SHA256 do corpo bruto da requisição (bytes exatamente como recebidos, sem reserializar o JSON) usando o secret retornado na criação do webhook, e compare (em tempo constante) com o valor após sha256= no header X-ViaPost-Signature.
Exemplo em Node.js:
js
const crypto = require('crypto')
function isValidSignature(rawBody, signatureHeader, secret) {
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
const received = signatureHeader.replace(/^sha256=/, '')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))
}Retentativas
Entregas com falha (timeout, erro 5xx do seu endpoint) são reenviadas até max_attempts vezes (default 8), com backoff entre tentativas.
Deduplicação
X-ViaPost-Delivery identifica o evento de origem, não a tentativa: o mesmo valor é reenviado em cada retentativa da mesma entrega, e também é compartilhado quando o mesmo evento é entregue a mais de um endpoint seu. Use o par (endpoint, X-ViaPost-Delivery) como chave de deduplicação do lado do seu servidor, não apenas o header isoladamente.