Integrações & API

Webhooks customizados

Configure URLs próprias para receber POST com payload JSON do SiteUP em 13 eventos suportados, assinatura HMAC-SHA256 com timestamp, delivery ID único e timeout configurável.

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

  1. Configurações → Integrações → Webhooks → Adicionar webhook
  2. URL: endpoint HTTPS público que vai receber o POST
  3. Eventos: marque um ou mais da lista acima
  4. 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, use await 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 2xx e processe em fila assíncrona; o timeout padrão é apenas 5 segundos.
  • Valide o HMAC antes de qualquer parsing do body, rejeite com 401 se 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-Delivery sempre, 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

Precisam de uma mão?

Contem para a equipe onde vocês precisam de ajuda.