Integration guides
Webhooks
Receive a signed POST when a destination goes down, recovers, expires or reaches its click limit.
Each event sends a JSON POST to a webhook endpoint when a destination goes down, recovers, expires or reaches its click limit. Register the endpoint in the dashboard under Links, Webhooks, and select the events it receives. Webhooks are available on Pro and Business plans.
Available events
| Event | Trigger | Data besides the link |
|---|---|---|
link.fora_do_ar | The link destination is classified as unavailable. | motivo, codigo_http |
link.voltou_ao_ar | The destination responds again after being down. | fora_desde |
link.limite_atingido | A click reaches the link's max_cliques. | max_cliques |
link.expirou | The link's expira_em date arrives. | expira_em |
The dashboard's Test button sends the teste event with only the message "Aviso de teste".
Event body
{ "id": "ent_1042", "evento": "link.fora_do_ar", "criado_em": "2026-10-12T14:03:21-03:00", "dados": { "link": { "id": 4821, "codigo": "promo-outubro", "url_curta": "https://pqno.app/promo-outubro", "url": "https://exemplo.com.br/campanha", "titulo": "Campanha de outubro" }, "motivo": "a página não existe mais (erro 404)", "codigo_http": 404 } }
The id identifies the delivery and stays the same across retries of the same event. Use it to ignore an event already processed.
Headers
| Header | Content |
|---|---|
X-Webhook-Event | Event name, such as link.fora_do_ar. |
X-Webhook-Delivery | The same id as in the body. |
X-Webhook-Signature | t= contains the delivery timestamp in seconds and v1= contains the signature, such as t=1760281401,v1=9f2c.... |
Verify the signature
The signature is the HMAC SHA-256 of momento.corpo, in hexadecimal, calculated using the webhook endpoint's secret. The dashboard shows the secret once when you register the endpoint or generate a new secret. Calculate the same value using the body exactly as received, compare in constant time and reject events with stale timestamps. This example uses Node.js.
const crypto = require('node:crypto');
function assinaturaValida(corpoBruto, cabecalho, segredo) {
const partes = Object.fromEntries(cabecalho.split(',').map((p) => p.split('=')));
const esperado = crypto.createHmac('sha256', segredo).update(`${partes.t}.${corpoBruto}`).digest('hex');
const a = Buffer.from(esperado);
const b = Buffer.from(partes.v1 || '');
const recente = Math.abs(Date.now() / 1000 - Number(partes.t)) < 300;
return recente && a.length === b.length && crypto.timingSafeEqual(a, b);
}
Response and retries
Return any 2xx status code within 8 seconds. Any other code, connection failure or timeout returns the event to the queue. There are up to 5 attempts. The first runs within 1 minute; subsequent attempts wait 1 minute, 5 minutes, 30 minutes and 2 hours. After 10 consecutive events exhaust their delivery attempts, the endpoint is disabled and the account receives a dashboard notification. Fix the problem and enable the endpoint again.
Endpoint requirements
The webhook endpoint must use https, point to a public site and use port 443 or 8443, without a username or password. Redirects are not followed. Each account can have up to 5 webhook endpoints, and the dashboard keeps recent event history for 30 days. There is no per-click event. To track clicks, use the link statistics.

