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:
{
"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
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
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
# 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