Conceitos
Receber eventos por webhook
Um webhook envia eventos JSON por POST à URL que você configura na aplicação. Use os eventos para atualizar seu sistema e o histórico do painel para diagnosticar falhas no receptor.
Nesta página
Configure o receptor na aplicação
No painel, abra Aplicações → sua aplicação → Webhook e informe a URL e o token do seu receptor.
| Configuração | Regra |
|---|---|
| URL | HTTPS, sem usuário ou senha na URL, com destino público. Endereços locais ou privados são rejeitados; redirecionamentos não são seguidos. |
| Token | De 16 a 200 caracteres ASCII visíveis, sem espaços. Guarde o mesmo valor no servidor receptor. |
| Eventos | Escolha ao menos um dos seis eventos abaixo. A aplicação começa com todos selecionados. |
| Incluir o código | Desligado por padrão. Inclui code apenas em send.sent, enquanto o código estiver válido. |
O token nunca aparece nas respostas ou no histórico. Ao editar, deixe o campo vazio para preservar o valor salvo. Na configuração JSON, omita token para preservá-lo; token_set informa se existe um token salvo.
Salvar outra configuração, remover o webhook ou revogar a aplicação interrompe as entregas pendentes da configuração anterior.
Eventos disponíveis
Você recebe somente os eventos selecionados para a aplicação:
| Evento | Quando ocorre |
|---|---|
send.sent | O canal aceitou a mensagem. SMS e e-mail podem encerrar a entrega e a cobrança nesse estado, sem recibo de entrega. |
send.delivered | O canal confirmou a entrega, quando esse recibo está disponível. |
send.read | O canal confirmou a leitura, quando esse recibo está disponível. |
send.failed | O envio encerrou com falha após as alternativas de entrega. |
send.verified | O código foi verificado com sucesso. |
send.expired | Um código pendente atingiu o prazo de validade. |
Os estados de entrega e verificação são independentes. Nem todo canal fornece confirmação de entrega ou leitura.
Valide os cabeçalhos antes de processar
Cada POST leva estes cabeçalhos:
Content-Type: application/json
Aut2fa-Token: seu_token_privado_do_webhook
Aut2fa-Event: send.delivered
Aut2fa-Delivery: whd_01m4prwckhd0kyjgv5vw8a5wjrCompare Aut2fa-Token com o token guardado no seu servidor antes de confiar no corpo. A autenticação usa o próprio token, sem assinatura HMAC.
Aut2fa-Event corresponde a type no JSON. Aut2fa-Delivery identifica a entrega de evento e permanece igual nas retentativas.
No Node.js, esta função compara os bytes sem revelar o ponto da divergência:
import { timingSafeEqual } from "node:crypto";
export function validWebhookToken(received, expected) {
if (typeof received !== "string" || !expected) return false;
const receivedBytes = Buffer.from(received);
const expectedBytes = Buffer.from(expected);
return receivedBytes.length === expectedBytes.length
&& timingSafeEqual(receivedBytes, expectedBytes);
}Passe o cabeçalho recebido e process.env.AUT2FA_WEBHOOK_TOKEN à função. Rejeite requisições sem token válido e evite registrar tokens e códigos em logs.
Corpo JSON do evento
O exemplo descreve uma confirmação de entrega com dados sintéticos:
{
"type": "send.delivered",
"created_at": "2026-10-12T14:02:13Z",
"data": {
"id": "snd_01m4prwckhd0kyjgv5vw8a5wjr",
"application_id": "app_01m4prwckhd0kyjgv5vw8a5wjr",
"to": "+5500000000000",
"channel": "whatsapp",
"from": null,
"status": "delivered",
"verification": "pending",
"expires_at": "2026-10-12T14:12:13Z"
}
}| Campo | Significado |
|---|---|
type | Um dos seis eventos selecionáveis. |
created_at | Data e hora do evento em RFC 3339. |
data.id | ID do envio OTP. Use em status e verificação. |
data.application_id | Aplicação que criou o envio. |
data.to | Destino completo normalizado. Trate esse dado pessoal no seu servidor. |
data.channel | Canal real ou planejado na simulação: whatsapp, sms ou email. null antes do roteamento. |
data.from | Remetente usado, ou null enquanto não estiver definido. |
data.status | Estado da entrega no momento do evento. |
data.verification | Estado da verificação no momento do evento. |
data.expires_at | Prazo de validade do código em RFC 3339. |
data.code | Opcional, apenas em send.sent com inclusão habilitada e código válido. |
test | true somente no teste manual com dados sintéticos. |
O código não fica no JSON persistido do evento nem no histórico. Em uma retentativa depois da validade, code será omitido.
Confirme o recebimento e evite duplicatas
Responda com HTTP 2xx após guardar o evento de forma durável. Você pode processar a operação na sua própria fila depois desse aceite.
A requisição tem prazo total de 10 segundos. Falha de rede, timeout ou resposta fora de 2xx permite outra tentativa; respostas 3xx não redirecionam.
Guarde Aut2fa-Delivery com uma restrição de unicidade. Ao receber novamente um ID já aceito, confirme com 2xx sem repetir a operação.
Uma falha de conexão pode acontecer depois que seu servidor processou o evento. Os eventos também podem chegar fora de ordem; consulte o status atual do envio quando precisar reconciliar estados.
Prazos das retentativas
Uma entrega automática tem até seis tentativas: a original e cinco retentativas. Cada intervalo começa após a falha anterior:
| Tentativa | Intervalo após a falha anterior |
|---|---|
| 1 | Sem espera programada. |
| 2 | 10 segundos. |
| 3 | 1 minuto. |
| 4 | 5 minutos. |
| 5 | 30 minutos. |
| 6 | 2 horas. |
Depois de um 2xx, não há nova tentativa programada. Depois da sexta falha, a entrega encerra. Os prazos indicam o agendamento; a execução depende do processamento da fila.
Teste o receptor pelo painel
Salve a configuração e clique em Enviar evento de teste. O painel executa um POST real ao receptor e mostra o status HTTP recebido.
O teste usa o primeiro evento selecionado, test: true e um ID snd_test_…. O canal é o primeiro permitido na aplicação. Para e-mail, o destino sintético é [email protected]; para telefone, +5500000000000. O prazo sintético é de dez minutos.
O teste manual tem attempt: 1 e max_attempts: 1, sem retentativas automáticas. Ele não cria um envio OTP, não entrega uma mensagem ao destinatário e não cobra a conta.
Aplicações no modo test também podem enviar eventos ao webhook durante a simulação. No callback, data.channel informa o canal planejado: e-mail para esse destino ou o primeiro canal da rota para telefone. A API de envio e status continua retornando channel: sandbox. O campo test: true distingue o botão de teste manual.
Consulte o histórico de entregas
Abra Aplicações → sua aplicação → Entregas para consultar as últimas 50 entregas de eventos. Cada linha tem um ID único e mostra a tentativa mais recente:
| Campo | Uso |
|---|---|
id | Mesmo identificador de Aut2fa-Delivery, preservado nas retentativas. |
event | Tipo do evento entregue. |
status_code | HTTP do receptor ou null se não houve resposta. |
attempt / max_attempts | Tentativa mais recente e limite da entrega. |
duration_ms | Duração da tentativa em milissegundos, quando disponível. |
error | Falha da tentativa ou null no sucesso. |
next_attempt_at | Próximo agendamento ou null quando não há outra tentativa prevista. |
created_at | Quando a entrega de evento foi criada. |
As retentativas atualizam a mesma linha. O histórico contém metadados da entrega; nunca inclui o token, o código ou o corpo do evento.
Contrato de configuração do painel
Estas rotas exigem uma sessão autenticada no painel e acesso à aplicação. A chave ak_live_… ou ak_test_… da API de envios não autentica essas operações:
| Método | Caminho | Resposta |
|---|---|---|
| PUT | /v1/panel/applications/{id}/webhook | 200: aplicação completa com webhook aninhado. |
| DELETE | /v1/panel/applications/{id}/webhook | 204: sem corpo. |
| POST | /v1/panel/applications/{id}/webhook/test | 201: { delivery }, com o resultado da tentativa executada. |
| GET | /v1/panel/applications/{id}/webhook/deliveries | 200: { data: Delivery[] }, limitado às 50 entregas mais recentes. |
O corpo do PUT recebe url, events, include_code e token opcional após o primeiro cadastro. A resposta da aplicação sempre inclui webhook com url, events, include_code e token_set.
Antes da configuração, url é null, todos os eventos estão selecionados e os dois campos booleanos são false. Consulte o OpenAPI para o contrato do POST recebido pelo seu servidor.