Skip to content
Idioma: Português

API para programadores

Webhooks: eventos, payload e assinatura

Atualizado a 1 de novembro de 2026 7 min de leitura

Configure webhooks no painel, receba entregas e verifique a assinatura HMAC – com exemplos para curl, Node.js e PHP.

Um webhook envia um pedido HTTP para o seu servidor assim que algo acontece no seu espaço de trabalho – por exemplo, quando uma página é publicada. Assim, não precisa de perguntar constantemente se algo mudou. Cada entrega é assinada, para que o seu servidor consiga distinguir mensagens autênticas de mensagens falsificadas.

Requisitos

  • Proprietário ou admin no espaço de trabalho – o item de menu «Webhooks» só aparece para estas funções
  • A partir do Creator Pro; no Creator Free aparece «Os webhooks estão disponíveis a partir do Creator Pro.»
  • Até 5 webhooks no Creator Pro, 25 no Creator Agency, 100 no Enterprise (ajustável)
  • Um servidor acessível num endereço https público

Os webhooks só se gerem no painel. Não podem ser criados nem alterados com chaves de API.

Criar um webhook

Página «Webhooks» sem webhooks e com o botão «+ Novo webhook»
A página «Webhooks» no espaço de trabalho
  1. Abra «Webhooks» no menu
  2. Clique em «+ Novo webhook»
  3. Introduza o URL de destino e escolha os eventos
  4. Opcional: introduza uma descrição e escolha o estado
  5. Clique em «Criar webhook»
  6. No passo «Concluído», copie o segredo de assinatura («Segredo de assinatura – visível só agora») e guarde-o no seu servidor – só é mostrado nesse momento
  7. Teste o webhook com «Testar». O resultado fica no cartão até ao teste seguinte: «Entregue com sucesso» ou «Não entregue» com o código HTTP (ou «sem resposta»), a duração e o início da resposta
«URL de destino (https://…)»
Até 2048 caracteres. Apenas https, sem credenciais no URL, sem endereços localhost e sem nomes internos como .local, .internal ou .lan. O nome tem de apontar para endereços IP públicos; o LinkHarbor volta a verificar isto antes de cada entrega.
«Eventos»
Pelo menos um evento. Cada grupo tem «Selecionar tudo» e «Desmarcar tudo».
«Descrição»
Opcional, até 255 caracteres – por exemplo, para que serve o webhook.
«Estado»
«Ativo» ou «Desativado». Os webhooks desativados não recebem entregas.

Eventos

EventoNo painelQuandoConteúdo de data
page.publishedPágina publicadaUma página foi publicada – no painel, através da API ou por um assistente de IApage_id, version, checksum, published_by_user_id (null para chaves de API e assistentes de IA)
form.submittedFormulário enviadoUm visitante enviou um formulário numa das suas páginasform_id, form_name, submission_id, page_id, block_id, submitted_at, values (chave do campo → valor), consent (chave do consentimento → true/false)
domain.verifiedDomínio verificadoUm domínio próprio foi verificado com sucessodomain_id, hostname, verification_method, status
domain.disabledDomínio desativadoUm domínio próprio foi desativado no painel (não num downgrade)domain_id, hostname, status
webhook.test– (botão «Testar»)Clica em «Testar»message (texto no idioma da conta de quem faz o teste – não o use para comparações)

form.submitted contém os valores exatamente como o visitante os enviou, mas nunca o endereço IP nem o browser. A entrega decorre em segundo plano: o visitante não espera por ela, e uma entrega falhada não impede a submissão.

Estrutura de uma entrega

O LinkHarbor envia cada entrega como POST com um corpo JSON e estes cabeçalhos:

CabeçalhoConteúdo
Content-Typeapplication/json
X-LinkHarbor-EventNome do evento, por exemplo page.published
X-LinkHarbor-Delivery-IdID único desta entrega (UUID), idêntico a id no corpo
X-LinkHarbor-TimestampMomento do envio em segundos Unix
X-LinkHarbor-Signaturesha256= seguido da assinatura HMAC-SHA256 em hexadecimal
X-LinkHarbor-Signature-Versionv1
Exemplo de payload para page.published
{
  "id": "3f1c2a9e-8d4b-4a51-9f0e-6b7c1d2e3f40",
  "event": "page.published",
  "created_at": "2026-11-01T09:30:12+00:00",
  "data": {
    "page_id": 42,
    "version": 8,
    "checksum": "9b1e5c…",
    "published_by_user_id": 7
  }
}

Os reenvios recebem um novo id e ainda os campos redelivery_of (o ID da entrega que é repetida) e delivery_root (o ID da primeira entrega desta cadeia).

Verificar a assinatura

Cada webhook tem o seu próprio segredo de assinatura (32 caracteres hexadecimais). Vê-o exatamente uma vez: no último passo, ao criar o webhook, e logo após «Segredo ↺». Copie-o de imediato para o seu servidor – o LinkHarbor não o volta a mostrar mais tarde. O LinkHarbor usa-o para calcular a assinatura desta forma:

  1. Formar a mensagem: timestamp, ponto, ID da entrega, ponto, corpo em bruto – ou seja, timestamp.delivery_id.body
  2. Calcular o HMAC-SHA256 sobre esta mensagem com o segredo de assinatura como chave
  3. Enviar o resultado como string hexadecimal com o prefixo sha256=

O seu servidor deve verificar a assinatura com uma comparação de tempo constante, recusar entregas com um timestamp com mais de 300 segundos e guardar os IDs das entregas pelo menos durante esse tempo, para reconhecer repetições. Importante: é assinado o corpo em bruto, exatamente como chega – não um JSON que tenha voltado a codificar.

Node.js (Express): receber e verificar um webhook
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const SECRET = process.env.LH_WEBHOOK_SECRET;
const seen = new Set(); // em produção: uma base de dados ou Redis com expiração

app.post('/webhooks/linkharbor', express.raw({ type: 'application/json' }), (req, res) => {
  const ts = req.get('X-LinkHarbor-Timestamp') || '';
  const id = req.get('X-LinkHarbor-Delivery-Id') || '';
  const sig = req.get('X-LinkHarbor-Signature') || '';

  if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
    return res.status(400).send('timestamp');
  }

  const expected = 'sha256=' + crypto
    .createHmac('sha256', SECRET)
    .update(ts + '.' + id + '.')
    .update(req.body) // corpo em bruto como Buffer
    .digest('hex');

  const a = Buffer.from(expected);
  const b = Buffer.from(sig);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).send('signature');
  }

  const event = JSON.parse(req.body.toString('utf8'));
  const key = event.delivery_root || event.id; // reconhecer reenvios da mesma cadeia
  if (!seen.has(key)) {
    seen.add(key);
    // processar aqui, de preferência de forma assíncrona numa fila
  }
  res.sendStatus(200);
});

app.listen(3000);
PHP: receber e verificar um webhook
<?php
$secret = getenv('LH_WEBHOOK_SECRET');
$body   = file_get_contents('php://input');
$ts     = $_SERVER['HTTP_X_LINKHARBOR_TIMESTAMP'] ?? '';
$id     = $_SERVER['HTTP_X_LINKHARBOR_DELIVERY_ID'] ?? '';
$sig    = $_SERVER['HTTP_X_LINKHARBOR_SIGNATURE'] ?? '';

if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300) {
    http_response_code(400);
    exit('timestamp');
}

$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $id . '.' . $body, $secret);
if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    exit('signature');
}

$event = json_decode($body, true);
// Reconhecer entregas duplicadas por $event['delivery_root'] ?? $event['id'],
// e depois processar.
http_response_code(200);

Testar o seu endpoint com curl

Este script envia uma entrega de teste corretamente assinada para o seu próprio servidor – útil antes de criar o webhook no LinkHarbor:

Simular uma entrega de teste assinada
SECRET="o-seu-segredo-de-assinatura"
URL="https://example.com/webhooks/linkharbor"
TS=$(date +%s)
ID=$(uuidgen | tr 'A-Z' 'a-z')
BODY='{"id":"'"$ID"'","event":"webhook.test","created_at":"2026-11-01T09:30:12+00:00","data":{"message":"Este é um evento de teste para este webhook."}}'
SIG="sha256=$(printf '%s' "$TS.$ID.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"

curl -X POST "$URL" \
  -H "Content-Type: application/json" \
  -H "X-LinkHarbor-Event: webhook.test" \
  -H "X-LinkHarbor-Delivery-Id: $ID" \
  -H "X-LinkHarbor-Timestamp: $TS" \
  -H "X-LinkHarbor-Signature: $SIG" \
  -H "X-LinkHarbor-Signature-Version: v1" \
  -d "$BODY"

Resposta, timeout e reenvio

  • Qualquer resposta com estado 2xx conta como sucesso; os redirecionamentos (3xx) não são seguidos
  • O seu servidor tem 10 segundos para responder e no máximo 5 segundos para estabelecer a ligação
  • Todos os webhooks de um evento partilham um total de 25 segundos; os que ainda não tiveram a sua vez nessa altura são marcados como falhados e podem ser reenviados
  • O LinkHarbor não repete automaticamente as entregas falhadas
  • Pode reenviar manualmente as entregas falhadas, mas não uma que entretanto tenha tido sucesso. O reenvio tem um novo id e um novo created_at
  • São permitidas no máximo 3 tentativas por evento, incluindo a primeira entrega; depois disso, a entrega vai para «Dead Letters» e já não pode ser reenviada

Entregas no painel

«Entregas» abre o registo de um webhook. Tem três separadores:

«Todas as entregas»
Todas as entregas, com filtros por evento, estado («Sucesso (2xx)», «Erro do cliente (4xx)», «Erro do servidor (5xx)», «Falhou») e «Limite». «↺ Repetir» volta a enviar uma entrega falhada, desde que não exista uma posterior com sucesso. Um clique numa linha mostra o pedido, a resposta, o corpo e o JSON em bruto.
«Reenvios»
Cadeias de reenvios com o resultado «Recuperado» ou «Continua a falhar» e o número de tentativas.
«Dead Letters»
Entregas em que todas as tentativas permitidas falharam – a primeira entrega e os reenvios em conjunto. O separador é só de consulta: já não podem ser reenviadas. Verifique o seu endpoint; depois, os novos eventos são entregues normalmente. Se precisar dos dados, obtenha-os através da API.

Se um reenvio não for feito, o painel indica o motivo:

«Não reenviado: este evento já falhou … vezes, não são possíveis mais tentativas. Encontra-o em “Dead Letters”.»
As 3 tentativas foram todas usadas.
«Não reenviado: este evento entretanto já foi entregue com sucesso.»
Uma entrega posterior da mesma cadeia já teve sucesso.

Verificação no painel

Em «Verificação» encontra duas ajudas:

«Kit de verificação»
«Carregar kit» mostra o algoritmo, os nomes dos cabeçalhos, o formato da mensagem assinada e a tolerância recomendada de 300 segundos. O segredo propriamente dito não está incluído.
«Verificar assinatura»
Introduza o ID da entrega, o timestamp, a assinatura e o corpo do pedido em bruto de uma entrega recebida. O LinkHarbor indica então «Assinatura válida» ou «Assinatura inválida». Copie o timestamp e a assinatura dos cabeçalhos X-LinkHarbor-Timestamp e X-LinkHarbor-Signature. A verificação só funciona para entregas dos últimos 5 minutos; para entregas mais antigas, indica «Assinatura inválida» mesmo que a assinatura esteja correta.

Rodar o segredo, desativar, eliminar

  • «Segredo ↺» gera um novo segredo de assinatura e mostra-o uma vez; o antigo deixa de funcionar de imediato, e o seu servidor tem de passar a usar o novo
  • Em «Editar», defina o estado como «Desativado» para pausar as entregas
  • O ícone do caixote do lixo elimina o webhook; até fechar a mensagem, pode cancelar com «Anular»

Quando passa para um plano mais pequeno, os webhooks acima do novo limite são desativados, e no Creator Free são todos desativados. Mantêm-se guardados; depois de um upgrade, o LinkHarbor volta a ativar automaticamente os webhooks desativados até ao limite do novo plano – incluindo os que desativou manualmente.

Não encontrou o que procura?

Diga-nos de que precisa e a nossa equipa de suporte ajuda-o pessoalmente.

Contactar o suporte