Alertas por webhook
Como receber os alertas no seu sistema por um POST assinado, com o formato do corpo, a verificação da assinatura e as retentativas.
Atualizado em
Neste artigo
Um canal de webhook envia cada alerta como um POST com corpo JSON para uma URL sua. Cada requisição é assinada com um segredo do canal, o Secret do webhook, para que o seu sistema confira que ela veio do Notifex.
Os alertas saem quando um incidente abre e quando é resolvido, e também nos avisos de expiração de certificado SSL e de domínio. Quais monitores usam o canal é explicado em Canal padrão e canais do monitor.
Criar um canal de webhook#
- Abra Canais de alerta e clique em Novo canal.
- Em Tipo, escolha Webhook.
- Preencha o Nome e a URL do webhook, com
http://ouhttps://. - Ligue Canal padrão se for o caso e deixe Ativo ligado.
- Clique em Criar canal.
A URL precisa ser pública. Endereços de rede interna e portas de e-mail são recusados com a mensagem Endereço não aceito: use uma URL pública (sem rede interna nem portas de e-mail). A URL é verificada de novo a cada envio.
O Secret do webhook#
Logo depois de criar o canal, o detalhe mostra o Secret do webhook, com o aviso Copie e guarde este valor agora. Use Mostrar para ver o valor e Copiar para copiá-lo.
O valor da imagem é só um exemplo: cada canal tem o seu.
Atenção
O secret aparece uma única vez, na criação do canal e a cada rotação. Ao sair da tela ou recarregar a página, ele não é mostrado de novo. Se você não guardou, a saída é rotacionar.
Rotacionar o secret#
- Abra o canal e, em Ações, clique em Rotacionar secret.
- Confirme em Rotacionar.
- Copie o novo valor, que aparece uma única vez, e atualize o seu sistema.
O secret anterior deixa de valer imediatamente. Alertas enviados entre a rotação e a atualização do seu sistema vão falhar na verificação.
A requisição#
- Método
POST, corpo JSON. - Qualquer resposta 2xx conta como entregue. Qualquer outra conta como falha.
- Redirecionamentos não são seguidos: uma resposta 3xx é falha.
- O tempo limite é de 10 segundos.
Cabeçalhos enviados:
| Cabeçalho | Valor |
|---|---|
Content-Type | application/json |
User-Agent | Notifex-Webhook/1.0 |
X-Notifex-Event | O evento: incident.opened, incident.resolved, ssl.expiring, domain.expiring ou channel.test |
X-Notifex-Delivery | O id da entrega, um por canal e por evento. Igual em todas as tentativas |
X-Notifex-Timestamp | O instante do envio, em segundos (Unix). Muda a cada tentativa |
X-Notifex-Signature | sha256=<hex>, o HMAC-SHA256 descrito abaixo |
O corpo#
O corpo é um JSON numa linha só, sem espaços extras. Formatado para leitura, um incident.opened fica assim:
{
"id": "6f1d2c3b-8a4e-4f5b-9c7d-1e2f3a4b5c6d-incident_opened",
"event": "incident.opened",
"version": 1,
"createdAt": "2026-11-14T15:34:21.000Z",
"organization": {
"id": "0b7e5a1c-2d3f-4e5a-8b9c-0d1e2f3a4b5c",
"name": "Loja Exemplo"
},
"monitor": {
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Página de pagamento",
"type": "http",
"target": "https://example.com/pagamento"
},
"incident": {
"id": "6f1d2c3b-8a4e-4f5b-9c7d-1e2f3a4b5c6d",
"kind": "downtime",
"status": "open",
"startedAt": "2026-11-14T15:34:10.000Z",
"resolvedAt": null,
"durationSeconds": null,
"cause": { "code": "http_status", "message": "unexpected status 404" }
}
}| Campo | O que é |
|---|---|
id | Identificador do evento. É o mesmo em todos os canais que recebem o evento |
event | O mesmo valor de X-Notifex-Event |
version | Versão do formato. Hoje, 1 |
createdAt | Instante do evento (ISO 8601, UTC). Na abertura, é a confirmação da falha, alguns segundos depois de incident.startedAt |
organization | id e name da organização |
monitor.type | http, tcp, ping, heartbeat, ssl ou domain |
monitor.target | O alvo do monitor (URL sem query nem credenciais, host:porta, host ou domínio). null em heartbeat e em monitor já excluído |
incident.kind | downtime, ssl_expiring ou domain_expiring |
incident.status | open ou resolved |
incident.resolvedAt, incident.durationSeconds | Preenchidos em incident.resolved |
incident.cause | code e message da causa, em inglês. Pode ser null |
expiry | Só em ssl.expiring e domain.expiring: kind, threshold, daysRemaining e expiresAt |
Verificar a assinatura#
A assinatura é o HMAC-SHA256, com o secret do canal como chave, sobre o texto <timestamp>.<corpo>: o valor de X-Notifex-Timestamp, um ponto e o corpo exatamente como chegou. O resultado em hexadecimal vai no cabeçalho com o prefixo sha256=.
Exemplo em Node.js. rawBody é o corpo bruto, exatamente como recebido, e headers é o objeto de cabeçalhos do Node (req.headers), com os nomes em minúsculas:
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: o corpo exatamente como chegou (texto ou Buffer), sem re-serializar o JSON
export function isValidNotifexSignature(rawBody, headers, secret) {
const timestamp = headers["x-notifex-timestamp"];
const received = headers["x-notifex-signature"] ?? "";
const expected =
"sha256=" +
createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const a = Buffer.from(received);
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}Atenção
Calcule sobre o corpo cru. Se o seu framework já converteu o JSON em objeto, serializar de novo pode mudar espaços ou a ordem dos campos, e a assinatura não confere.
O mesmo exemplo aparece no detalhe de cada canal de webhook, na seção Como validar a assinatura, visível só para quem pode editar canais.
Retentativas#
Um alerta que falha é tentado até 5 vezes. A espera dobra a cada falha: 2, 4, 8 e 16 minutos depois da tentativa anterior, cerca de 30 minutos no total. Depois da quinta falha, a notificação fica como Falhou.
- Todas as tentativas levam o mesmo
X-Notifex-Delivery. Use esse valor para ignorar entregas repetidas. - Cada tentativa tem um
X-Notifex-Timestampnovo e é assinada de novo. - Um canal excluído ou desativado antes do envio não recebe a requisição.
O resultado de cada envio fica no incidente, em Notificações enviadas, com as colunas Tentativas e Erro. Veja Incidentes. Erros comuns:
| Erro | Significado |
|---|---|
webhook responded 500 | O seu sistema respondeu com um status fora de 2xx (o número muda) |
webhook timed out | Não houve resposta em 10 segundos |
webhook connection failed | Não foi possível conectar à URL |
webhook target not allowed | A URL passou a apontar para um endereço não aceito |
O texto do erro pode vir seguido de um código entre parênteses, por exemplo webhook connection failed (ECONNREFUSED).
Enviar teste#
Em Ações, Enviar teste manda um evento channel.test na hora. O teste é tentado uma vez só, sem retentativas, e o resultado aparece na tela: Teste entregue ou A entrega do teste falhou, com o motivo. Cada canal aceita até 5 testes por minuto.
O corpo do teste usa um monitor fictício e não traz incidente:
{
"id": "11111111-1111-4111-8111-111111111111",
"event": "channel.test",
"version": 1,
"createdAt": "2026-11-14T12:00:00.000Z",
"organization": {
"id": "0b7e5a1c-2d3f-4e5a-8b9c-0d1e2f3a4b5c",
"name": "Loja Exemplo"
},
"monitor": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Notifex — teste de canal",
"type": "http",
"target": null
},
"incident": null
}Não encontrou o que procurava?
Escreva para a gente pelo formulário de contato do site.