O que você vai configurar
- Um endpoint que recebe eventos do Elido, como
link.created,link.updated,link.deleted,member.invitededomain.verified. - Verificação HMAC-SHA256 do cabeçalho
X-Elido-Signature, para que seu servidor possa confirmar que cada entrega veio do Elido. - Três tentativas de entrega por evento, um registro de entregas com um botão manual de Retry e rotação de segredo com uma sobreposição de 7 dias.
Os webhooks enviam eventos do Elido para seu servidor conforme acontecem, para que você não precise consultar a API repetidamente. Usos comuns: sincronizar metadados de links com um CRM, manter um índice interno de links atualizado ou iniciar um job quando um link é publicado.
Os webhooks abrangem alterações em links, domínios, membros e no workspace. Eles não transportam cliques individuais. Para dados de cliques, use a exportação de cliques ou uma integração de eventos, como o Mixpanel. Eventos de webhook por clique estão planejados.
Adicionar um endpoint de webhook
- Vá para Dashboard → Webhooks.
- Informe a URL para a qual devemos fazer o POST e uma descrição opcional.
- Escolha o tipo de endpoint: Events (você escolhe os tipos de evento) ou SIEM (firehose) (todos os eventos do workspace).
- Em um endpoint de Events, marque os tipos de evento desejados. Os eventos
link.*vêm marcados por padrão. - Clique em Add endpoint. O segredo de assinatura aparece uma vez, logo abaixo do formulário. Copie-o agora: o Elido não o mostrará novamente.
A URL deve ser HTTPS. URLs http:// simples são rejeitadas ao salvar o endpoint, exceto localhost e 127.0.0.1, que continuam permitidos para desenvolvimento local.
Você pode pausar e retomar um endpoint na lista. Um endpoint pausado não recebe novas entregas, e tudo o que ainda estiver na fila para esse endpoint aguardará até que você o retome.
Quem pode gerenciar webhooks
Qualquer pessoa no workspace pode visualizar os endpoints e o registro de entregas. Criar, editar, pausar, excluir, rotacionar o segredo e tentar entregar novamente exigem a permissão workspace.edit, que as funções integradas Admin e Owner possuem. Uma chave de API pode chamar os mesmos endpoints de webhook da API se sua função tiver essa permissão.
Tipos de endpoint
- Events (
event): recebe somente os tipos de evento aos quais você se inscreveu. Assinado. - SIEM (
siem): recebe todos os eventos publicados para o workspace, incluindoaudit.eventpara cada entrada do registro de auditoria. Assinado. Destinado a pipelines de logs e ferramentas de segurança. - Discord, Telegram e Sentry: canais de chat e alertas que reutilizam o mesmo sistema de entrega, mas enviam o formato de mensagem próprio do fornecedor. Eles se autenticam pela URL ou pelo token do fornecedor, portanto não carregam cabeçalhos de assinatura. Consulte Discord, Telegram e Sentry.
Tudo o que vem abaixo sobre assinaturas e segredos se aplica somente aos endpoints Events e SIEM.
Catálogo de eventos
Os nomes seguem <resource>.<action>. O formulário do dashboard oferece os mais comuns; pela API, você pode inscrever um endpoint Events em qualquer tipo desta lista, e um endpoint SIEM recebe todos eles.
No seletor do dashboard:
link.created: um link curto foi criado, incluindo links criados em massa.link.updated: um link mudou (destino, título, tags, expiração e assim por diante), foi restaurado, teve o status alterado ou teve o status de segurança alterado pela moderação.link.deleted: um link foi excluído de forma reversível.workspace.updated: as configurações do workspace mudaram.workspace.created: publicado quando um workspace é criado. Como nenhum endpoint pode existir em um workspace antes de sua criação, normalmente você não receberá este evento.member.invited: alguém entrou no workspace por adição direta, aceitação de convite ou provisionamento SCIM.member.removed: um membro foi removido manualmente ou pelo SCIM.audit.event: um evento para cada entrada do registro de auditoria.
Disponíveis pela API ou por um endpoint SIEM:
link.expired: um link passou da data de expiração.link.cap_reached: um link atingiu seu limite de cliques.dataincluicapeclicks.link.broken: a verificação de integridade de links do Elido detectou que o destino está falhando.dataincluistatus_code,error_messageefirst_seen_at.link.encrypted_createdelink.encryption_rotated: para links criptografados.domain.verified: um domínio personalizado passou na verificação de DNS.domain.ssl_failed: os registros DNS de um domínio personalizado ainda não foram encontrados 24 horas depois de sua adição. Apesar do nome, isso diz respeito à verificação de DNS, não à renovação do certificado.member.role_changed: a função de um membro mudou.dataincluiold_role,new_roleechanged_by_user_id.invitation.createdeinvitation.accepted.- Eventos de cobrança:
subscription.*(por exemplo,subscription.activated,subscription.renewed,subscription.canceled) eusage.threshold_80,usage.threshold_100.
Planejados e não enviados atualmente: link.clicked.aggregated (contagens de cliques por link e por janela), eventos por clique, conversion.recorded, domain.tls_renewed, qr.generated e um evento separado abuse.flagged. Atualmente, uma decisão de moderação sobre um link chega como link.updated com o novo abuse_status.
Estrutura do payload
Cada entrega assinada é um POST com Content-Type: application/json, User-Agent: Elido-Webhooks/1.0 e este envelope:
{
"type": "link.created",
"workspace_id": 4123,
"timestamp": "2026-09-22T09:42:11Z",
"data": {
"id": 891234,
"workspace_id": 4123,
"domain_id": 12,
"slug": "spring-2026",
"destination_url": "https://acme.com/spring-sale",
"title": "Spring sale",
"tags": ["email"],
"status": "active",
"expires_at": null,
"created_by_user_id": 5821,
"created_at": "2026-09-22T09:42:11Z"
}
}
typeé o tipo do evento. Ele também está no cabeçalhoX-Webhook-Event.timestampindica quando o evento aconteceu, em UTC.datadepende do evento. Para eventoslink.*, é o objeto completo do link (o exemplo acima está resumido). Para os outros eventos, é um objeto pequeno com os IDs e campos listados no catálogo.- Os segredos nunca saem do Elido: campos como o hash da senha de um link ou um token de convite são removidos de
dataantes da entrega.
Ainda não há um campo id de evento no corpo; um ID por evento está planejado. Para idempotência, use o cabeçalho X-Webhook-Delivery, descrito abaixo.
Cabeçalhos e assinaturas
Cada entrega para um endpoint Events ou SIEM contém:
| Cabeçalho | Valor |
|---|---|
X-Elido-Signature | v1= seguido da assinatura HMAC-SHA256 em hexadecimal |
X-Webhook-Signature | Mesmo valor de X-Elido-Signature, mantido para integrações antigas |
X-Webhook-Timestamp | Hora Unix em segundos em que esta requisição foi assinada |
X-Webhook-Event | O tipo do evento, por exemplo link.created |
X-Webhook-Delivery | O ID da entrega. Ele permanece igual nas novas tentativas da mesma entrega |
X-Elido-Signature-Previous | Somente durante uma rotação de segredo: a mesma assinatura feita com a chave antiga |
A assinatura é calculada assim:
v1=hex( HMAC-SHA256( secret, "{X-Webhook-Timestamp}.{raw request body}" ) )
A chave é toda a sua string secreta, incluindo o prefixo whsec_, usada como está. Assine os bytes brutos recebidos, não um objeto JSON serializado novamente, e compare em tempo constante. Um exemplo curto em Node (Express):
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";
const SECRET = process.env.ELIDO_WEBHOOK_SECRET; // full whsec_... value
function same(a, b = "") {
const x = Buffer.from(a);
const y = Buffer.from(b);
return x.length === y.length && timingSafeEqual(x, y);
}
const app = express();
app.post(
"/webhooks/elido",
express.raw({ type: "application/json" }),
(req, res) => {
const ts = req.get("X-Webhook-Timestamp") ?? "";
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(400).send("stale timestamp");
}
const expected =
"v1=" +
createHmac("sha256", SECRET)
.update(`${ts}.`)
.update(req.body)
.digest("hex");
const ok = [
req.get("X-Elido-Signature"),
req.get("X-Elido-Signature-Previous"),
].some((sig) => same(expected, sig));
if (!ok) return res.status(401).send("bad signature");
const event = JSON.parse(req.body.toString("utf8"));
// queue event for processing, then answer quickly
res.sendStatus(200);
},
);
Para versões em Python e Go, um vetor de teste e os erros comuns, consulte como verificar assinaturas de webhook.
Rotacionar o segredo de assinatura
Abra o endpoint em Dashboard → Webhooks e clique em Rotate secret. O novo segredo whsec_ é exibido uma vez, e o Elido passa a assinar com ele a partir desse momento.
A chave antiga permanece válida durante uma janela de tolerância de 7 dias. Durante essa janela, cada entrega contém duas assinaturas: X-Elido-Signature com a chave nova e X-Elido-Signature-Previous com a antiga, para que um receptor que ainda não tenha feito a troca continue verificando. Aceite qualquer um dos cabeçalhos enquanto distribui o novo segredo.
Endpoints criados antes de 22 de setembro de 2026 são uma exceção: a primeira rotação deles não produz X-Elido-Signature-Previous, portanto o segredo original deixa de funcionar imediatamente. Implante o novo segredo logo após essa primeira rotação. Endpoints criados desde então assinam com as duas chaves desde a primeira rotação. A partir da segunda rotação, aplica-se a sobreposição de 7 dias.
Novas tentativas
Uma entrega falha com qualquer resposta que não seja 2xx, um erro de rede ou nenhuma resposta em até 10 segundos. Cada entrega recebe 3 tentativas no total:
- A primeira tentativa, alguns segundos após o evento.
- Uma nova tentativa cerca de 5 minutos após a primeira falha.
- Uma última tentativa cerca de 15 minutos após a segunda falha.
Se a terceira tentativa falhar, a entrega é marcada como failed e não recebe novas tentativas automáticas. O endpoint permanece ativo e novos eventos continuam sendo entregues. Seu endpoint pode ver a mesma entrega mais de uma vez (por exemplo, quando processou uma requisição, mas respondeu depois do tempo limite de 10 segundos), portanto elimine duplicatas usando X-Webhook-Delivery.
Registro de entregas
Abra um endpoint em Dashboard → Webhooks para ver suas 100 entregas mais recentes. Para cada uma, você recebe o tipo do evento, o status (pending, delivered ou failed), o status HTTP retornado pelo seu servidor, o tempo de resposta, as tentativas usadas de um total de 3, quando ela foi criada e concluída, o próximo horário de nova tentativa para as pendentes, o último erro e o payload completo enviado.
Qualquer entrega entregue ou com falha tem um botão Retry. Ele coloca a mesma entrega novamente na fila (com o mesmo ID X-Webhook-Delivery, assinada novamente) com um novo orçamento de 3 tentativas. Pela API, GET /v1/workspaces/{workspace_id}/webhooks/{id}/deliveries pagina pelas entregas antigas com limit (até 100) e offset, e POST .../deliveries/{delivery_id}/retry faz o mesmo que o botão. Se você não puder reproduzir uma entrega por conta própria, o suporte do Elido poderá reproduzi-la para você.
O registro do corpo da resposta do seu servidor está planejado.
Testes locais
Um comando de CLI que encaminha webhooks para localhost (npx @elido/cli webhooks forward) está planejado. Até lá, exponha seu servidor local por meio de um túnel, como ngrok ou Cloudflare Tunnel, adicione a URL HTTPS do túnel como endpoint e remova-a quando terminar.
Limites
- 10 segundos para seu endpoint responder.
- 3 tentativas de entrega por evento, além de novas tentativas manuais.
- A API do registro de entregas retorna no máximo 100 entregas por página.
Solução de problemas
A assinatura nunca corresponde. As causas mais comuns são: seu framework analisou e serializou novamente o JSON antes de você calcular o hash (calcule o hash do corpo bruto), você removeu o prefixo whsec_ da chave ou está assinando com o timestamp do corpo em vez do cabeçalho X-Webhook-Timestamp. A publicação sobre verificação de assinaturas tem um vetor de teste para comparar com seu código.
A assinatura parou de corresponder após uma rotação. Seu servidor ainda tem o segredo antigo. Implante o novo. Em um endpoint criado antes de 22 de setembro de 2026, a primeira rotação não tem X-Elido-Signature-Previous para servir como alternativa.
Alguns eventos chegam duas vezes. O Elido tentou entregar novamente porque seu endpoint respondeu com um erro ou levou mais de 10 segundos. Elimine duplicatas usando X-Webhook-Delivery e responda com 2xx antes de executar trabalhos demorados.
Um tipo de evento nunca chega. Verifique se o endpoint está inscrito nele, não está pausado e se o tipo está no catálogo acima. Os tipos marcados como planejados ainda não são enviados.