Documentação de Webhook
O que é um Webhook
Webhook é um mecanismo que permite ao seu sistema receber notificações automáticas sobre eventos por meio de solicitações HTTP. Quando um determinado evento ocorre em nosso sistema (por exemplo, uma campanha é concluída), enviamos uma solicitação POST com informações detalhadas para a URL que você especificar.
Configuração de Webhook
Você pode configurar webhooks no painel de controle web:
- Vá para a seção Integrações.
- Clique no cartão Webhooks.
- Clique em Criar Webhook.
- Preencha os campos:
- Nome do webhook — para sua identificação pessoal do webhook.
- URL para enviar o webhook — o endereço do seu servidor que receberá as notificações.
- Eventos — selecione da lista os eventos sobre os quais deseja receber notificações.
- Clique em Criar Webhook.
Após a criação, o webhook aparecerá na lista geral. Seu cartão exibe todas as informações principais:
- Status (Ativo / Inativo)
- Nome do webhook e URL para enviar o webhook
- Lista de eventos rastreados
- Hora do último envio bem-sucedido
- Atividade (número total de eventos enviados)
As seguintes ações estão disponíveis no menu (⋮) no canto do cartão:
- Testar
- Editar
- Ativar / Desativar
- Excluir
Formato de Notificações
{
"eventId": "<uuid>",
"trigger": "<entity>.<event>",
"occurredAt": "2023-10-27T12:35:01.123Z",
"payload": {
"someStringField": "string",
"numberField": 42
}
}Campos da solicitação:
eventId— identificador único do evento.trigger— tipo de evento no formatoentidade.evento(veja a lista abaixo).occurredAt— hora em que o evento ocorreu no formato ISO 8601 (UTC).payload— objeto com dados específicos para cada evento.
Evento de Teste
Quando você clicar no botão Testar no menu (⋮) no canto do cartão, receberá uma solicitação POST com o seguinte payload:
{
"eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"trigger": "emailmassivo.webhook_test",
"occurredAt": "2030-12-31T20:59:59.999Z",
"payload": {
"timestamp": "2030-12-31T20:59:59.999Z",
"stringField": "someString",
"numberField": 42,
"booleanField": true,
"objectField": {
"nestedString": "value",
"nestedNumber": 123
},
"arrayField": ["item1", "item2", 3, false]
}
}Disparadores Disponíveis
Entidade: Campanhas de email (mail_distribution)
Payload Comum para eventos de campanha
Para os eventos mail_distribution.started, mail_distribution.completed, mail_distribution.moderating, mail_distribution.approved e mail_distribution.rejected, é usada a seguinte estrutura de payload:
{
"mailDistributionId": 12345,
"mailDistributionName": "Nome da campanha",
"mailDistributionSubject": "Assunto do email"
}mail_distribution.started— a campanha foi iniciada (Iniciada).mail_distribution.completed— a campanha foi concluída com sucesso (Concluída).mail_distribution.moderating— a campanha foi enviada para revisão (Em moderação).mail_distribution.approved— a campanha foi aprovada pelo moderador (Aprovada).mail_distribution.rejected— a campanha foi rejeitada pelo moderador (Rejeitada).mail_distribution.banned— a campanha está bloqueada (Interrompida pelo sistema). Este evento tem umpayloadestendido.
Payload:
{
"mailDistributionId": 12345,
"mailDistributionName": "Nome da campanha",
"mailDistributionSubject": "Assunto do email",
"negative": {
"reason": "hard_bounced",
"explanation": "Descrição detalhada do motivo do bloqueio"
}
}O campo reason conterá uma das seguintes strings:
hard_bouncedsoft_bouncederror_spamcomplain
Requisitos de Processamento
1. Resposta do servidor e tempo limite
Seu servidor deve responder à solicitação dentro de 30 segundos.
- Status HTTP
200–299: significa que o evento foi recebido e processado com sucesso. - Qualquer outro status (
3xx,4xx,5xx) ou tempo limite esgotado: é considerado um erro, após o qual tentaremos entregar o evento novamente.
2. Idempotência
Nosso sistema garante a entrega com o princípio de pelo menos uma vez (at-least-once). Isso significa que, devido a problemas de rede ou erros no lado do seu servidor, o mesmo evento pode ser entregue mais de uma vez. Use o campo eventId para prevenir o processamento duplicado.
3. Tentativas
Em caso de falha na entrega, faremos 6 tentativas de retry com intervalos crescentes.
| Tentativa | Atraso após a anterior |
|---|---|
| 1 | 1 minuto |
| 2 | 2 minutos |
| 3 | 4 minutos |
| 4 | 8 minutos |
| 5 | 15 minutos |
| 6 | 15 minutos |
No total, podemos enviar até 7 solicitações para um evento (envio inicial + 6 tentativas). Após a última tentativa falhada, pararemos de entregar o evento e ele será marcado como não entregue.
4. Requisitos de URL
Seu manipulador de URL deve usar o protocolo HTTPS e ter um certificado SSL válido. Notificações para endereços HTTP não serão entregues.
Exemplo de Manipulador
PHP
<?php
// Obtemos o corpo raw da solicitação
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data || !isset($data['eventId'])) {
http_response_code(400); // Bad Request
exit('Invalid payload');
}
// Verificamos se o evento já foi processado
if (isEventProcessed($data['eventId'])) {
http_response_code(200);
exit('OK. Already processed.');
}
// Processamos o evento
switch ($data['trigger']) {
case 'mail_distribution.completed':
handleMailDistributionCompleted($data['payload']);
break;
case 'mail_distribution.banned':
handleMailDistributionBanned($data['payload']);
break;
// ... outros eventos
}
// Marcamos o evento como processado
markEventAsProcessed($data['eventId']);
http_response_code(200);
echo 'OK';
?>Node.js (Express)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const { eventId, trigger, payload } = req.body;
// Verificamos a idempotência
if (isEventProcessed(eventId)) {
return res.status(200).send('OK. Already processed.');
}
// Processamos o evento
switch (trigger) {
case 'mail_distribution.completed':
handleMailDistributionCompleted(payload);
break;
case 'mail_distribution.banned':
handleMailDistributionBanned(payload);
break;
// ... outros eventos
}
// Marcamos como processado
markEventAsProcessed(eventId);
res.status(200).send('OK');
});Recomendações de Desenvolvimento
1. Processe as solicitações de forma assíncrona
Seu servidor deve responder com HTTP 200 OK o mais rápido possível. Não execute operações de longa duração (chamadas para outras APIs, processamento de arquivos) no momento de receber o webhook. Em vez disso, adicione a tarefa a uma fila (por exemplo, RabbitMQ, Redis, SQS) e retorne a resposta imediatamente. Isso o protegerá de tempos limite esgotados e facilitará o dimensionamento do processamento.
2. Esteja preparado para novos campos
Novos campos podem ser adicionados ao objeto payload no futuro. Seu código deve ser resiliente a isso e não falhar se chaves desconhecidas aparecerem no JSON.
3. Configure o monitoramento
Configure o monitoramento para seu manipulador de URL. Os alertas ajudarão você a reagir aos problemas rapidamente e corrigi-los antes que os eventos comecem a ser perdidos após todas as tentativas de retry.
4. Use ambientes de teste
Não use sua URL principal (produção) para depuração. Crie um webhook separado para um ambiente de teste ou staging para fazer alterações no código com segurança.
Perguntas Frequentes (FAQ)
Configurei um webhook mas não estou recebendo notificações. O que devo fazer?
Verifique o seguinte:
- Status na UI: Certifique-se de que o webhook está Ativo.
- Evento de teste: Use o botão Testar no cartão do webhook.
- URL pública: Certifique-se de que a URL esteja acessível da internet (não
localhost). - HTTPS: Certifique-se de que a URL comece com
https://e tenha um certificado SSL válido. - Logs do servidor: Verifique os logs do seu servidor web (Nginx, Apache) ou da aplicação para ver entradas de solicitações recebidas.
Por que vocês enviam o mesmo evento (
eventId) várias vezes?Repetimos o envio se não recebermos confirmação de entrega bem-sucedida do seu servidor (resposta com código HTTP 200–299) dentro de 30 segundos. Isso pode acontecer por duas razões principais:
- Seu servidor retornou um erro (por exemplo, status
500 Internal Server Error). - Ocorreu um problema de rede, devido ao qual não recebemos a resposta, mesmo que sua aplicação a tenha enviado e processado o evento com sucesso.
Portanto, seu sistema sempre deve estar preparado para duplicatas (veja a seção Idempotência).
- Seu servidor retornou um erro (por exemplo, status
A ordem de entrega de eventos está garantida?
Não, não está. Devido ao comportamento da rede ou à lógica de tentativas, um evento que ocorreu mais tarde pode ser entregue antes. Sempre confie no carimbo de data/hora
occurredAtno corpo da solicitação, não na ordem em que são recebidos.O que acontece se meu servidor não estiver disponível por muito tempo?
Tentaremos entregar o evento por aproximadamente 45 minutos. Se seu servidor permanecer indisponível por mais tempo, o evento será perdido. Planeje a manutenção tendo em mente esta janela.
Posso usar a mesma URL para vários webhooks?
Sim. Esta é uma prática comum. Em seu código, use o campo
triggerpara roteamento e chamada da lógica de processamento apropriada.