Webhooks customizados
Webhooks são a forma mais leve de reagir em tempo real a eventos do SiteUp sem depender de um orquestrador externo. Você cadastra uma URL HTTPS, escolhe os eventos que interessam e o SiteUp envia POST com payload JSON sempre que algum deles ocorre. Esta página documenta os eventos disponíveis, a estrutura do payload, a assinatura HMAC, o tratamento de falhas e o fluxo de validação local.
Tipos de webhook
O SiteUp suporta dois escopos:
- Webhook de conta (
account_type) — recebe eventos de toda a conta. Cadastrado em Configurações → Integrações → Webhooks. - Webhook de inbox API (
api_inbox_webhook) — exclusivo de inboxes do tipo API; recebe eventos apenas das conversas daquela caixa. Configurado nas opções da inbox.
Este artigo foca no webhook de conta, que é o caso de uso mais comum.
Eventos suportados
Os 13 eventos abaixo são os únicos aceitos pelo validador da plataforma. Use exatamente esses nomes (com underscore, em minúsculo) ao assinar o webhook:
| Evento | Disparado quando |
|---|---|
conversation_created |
Uma conversa é aberta |
conversation_updated |
Atributos da conversa mudam (atribuição, prioridade, equipe, custom attributes) |
conversation_status_changed |
A conversa muda de status (open, resolved, pending, snoozed) |
conversation_typing_on |
Um atendente começa a digitar na conversa |
conversation_typing_off |
Um atendente para de digitar |
message_created |
Mensagem (incoming, outgoing, activity ou template) é criada |
message_updated |
Mensagem existente é atualizada (status de entrega, edição etc.) |
contact_created |
Novo contato é criado na conta |
contact_updated |
Atributos do contato são alterados |
inbox_created |
Nova caixa de entrada é criada |
inbox_updated |
Configurações de uma caixa mudam |
webwidget_triggered |
Visitante interage com o widget de site (pré-conversa) |
Eventos não listados aqui não estão disponíveis — o cadastro do webhook valida os nomes e rejeita os desconhecidos.
Cadastrando o webhook
- Configurações → Integrações → Webhooks → Adicionar webhook
- URL: endpoint HTTPS público que vai receber o POST
- Eventos: marque um ou mais da lista acima
- Salvar
Cada webhook recebe um secret aleatório no momento da criação. Esse valor é usado para gerar a assinatura HMAC e deve ser armazenado pelo seu servidor para validação.
Estrutura do payload
Todo POST tem Content-Type: application/json e o corpo segue um envelope com a chave event indicando o tipo:
json { "event": "conversation_created", "id": 5821, "status": "open", "inbox_id": 12, "contact_inbox": { "contact": { "id": 8123, "name": "Maria Silva", "phone_number": "+5511999998888", "email": null } }, "messages": [ { "id": 88421, "content": "Olá, gostaria de saber sobre o plano Premium", "message_type": "incoming", "created_at": 1714324921 } ], "additional_attributes": {}, "custom_attributes": {} }
Eventos de atualização (conversation_updated, contact_updated, inbox_updated, conversation_status_changed, message_updated) incluem ainda a chave changed_attributes com o diff aplicado. Eventos de digitação (conversation_typing_on/off) trazem user, conversation e is_private.
A estrutura específica de cada payload acompanha o presenter do recurso correspondente — a forma mais segura é capturar uma entrega real em ambiente de teste e gerar o tipo a partir dela.
Headers de cada entrega
Todo POST do SiteUp inclui:
| Header | Descrição |
|---|---|
Content-Type |
application/json |
X-Chatwoot-Delivery |
UUID único da tentativa de entrega — use para idempotência |
X-Chatwoot-Timestamp |
Unix timestamp (segundos) de quando o payload foi assinado |
X-Chatwoot-Signature |
sha256=<hex> — HMAC-SHA256 de <timestamp>.<body_raw> usando o secret |
Os prefixos
X-Chatwoot-*derivam do projeto upstream que dá base à plataforma e são mantidos para compatibilidade com bibliotecas de cliente já existentes no ecossistema.
Validando a assinatura HMAC
A string assinada é a concatenação <timestamp>.<body_bruto> (ponto literal entre os dois). Use o secret recebido no cadastro do webhook como chave HMAC-SHA256 e compare em tempo constante.
Node.js
``javascript const crypto = require("crypto");
function verifySiteupSignature(rawBody, headers, secret) {
const timestamp = headers["x-chatwoot-timestamp"];
const signatureHeader = headers["x-chatwoot-signature"] || "";
const expectedHex = crypto
.createHmac("sha256", secret)
.update(${timestamp}.${rawBody})
.digest("hex");
const received = signatureHeader.replace(/^sha256=/, "");
if (received.length !== expectedHex.length) return false; return crypto.timingSafeEqual( Buffer.from(received, "hex"), Buffer.from(expectedHex, "hex") ); } ``
Python
``python import hmac import hashlib
def verify_siteup_signature(raw_body: bytes, headers: dict, secret: str) -> bool: ts = headers.get("X-Chatwoot-Timestamp", "") received = headers.get("X-Chatwoot-Signature", "").removeprefix("sha256=") expected = hmac.new( secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256, ).hexdigest() return hmac.compare_digest(received, expected) ``
Importante: assine o corpo bruto da requisição, antes de qualquer parsing JSON. Em frameworks como Express, ative
express.raw({ type: "application/json" })na rota do webhook; em FastAPI, useawait request.body()direto.
Timeout, retry e falhas
| Parâmetro | Valor padrão |
|---|---|
| Timeout da requisição | 5 segundos (configurável globalmente via WEBHOOK_TIMEOUT) |
Retry em 429/5xx (webhooks de conta) |
Sim — controlado pelo job de fila |
| Retry em outras exceções | Sim, com captura de erro registrada em log |
Quando o webhook é de uma inbox API e o evento é message_created/message_updated, falhas resultam em atualização do status da mensagem para failed automaticamente. Para webhooks de conta, falhas são registradas mas não alteram o estado dos recursos.
Como o mesmo evento pode ser reentregue em caso de falha intermitente, sempre use X-Chatwoot-Delivery (UUID) como chave de deduplicação. Salve em uma tabela e ignore duplicatas.
Testando localmente com ngrok
``bash
1. Suba seu servidor local na porta 3000
node server.js
2. Em outro terminal, exponha via ngrok
ngrok http 3000
3. Copie a URL pública (https://abc123.ngrok-free.app)
4. Cole no painel SiteUp como URL do webhook, marque os eventos e salve
5. Dispare um evento (ex.: criar conversa de teste)
``
A interface do ngrok em http://localhost:4040 mostra cada requisição com headers e body — útil para inspecionar o X-Chatwoot-Signature e validar seu código de verificação.
Boas práticas
- Responda rapidamente (idealmente < 1s) com
2xxe processe em fila assíncrona; o timeout padrão é apenas 5 segundos. - Valide o HMAC antes de qualquer parsing do body — rejeite com
401se a assinatura não bater. - Verifique também a janela do timestamp (ex.: rejeitar entregas com mais de 5 minutos de diferença) para mitigar replay.
- Logue
X-Chatwoot-Deliverysempre — facilita correlação com logs internos do SiteUp em tickets de suporte. - Versione seu endpoint (
/webhooks/siteup/v1) para evoluir o handler sem quebrar o existente. - Monitore taxa de falha com alertas — falhas reiteradas geralmente indicam mudanças de schema ou indisponibilidade do seu servidor.
Próximos passos
- Automações com n8n — alternativa visual com triggers de webhook prontos
- API REST: autenticação — para responder ao evento atualizando dados na plataforma
- MCP Server — para acionar agentes IA em reação a eventos