Formato do evento
O envelope, o versionamento e exemplos reais de message.received e conversation.closed.
Todo evento chega no mesmo envelope, independente do tipo:
{
"id": "evt_01j8x3z9f9a2e8n4qf3r6h8g1p",
"type": "deal.stage_changed",
"version": 1,
"occurredAt": "2026-10-01T18:22:07.123456Z",
"workspace": { "id": "ws_9f2a...", "slug": "acme" },
"actor": { "type": "api_key", "id": "key_7a1b...", "name": "n8n produção" },
"data": {
"object": { "...snapshot no formato público...": "" },
"previous": { "stageId": "stg_old..." }
},
"test": false
}| Campo | Descrição |
|---|---|
id | Id do evento. Estável entre tentativas e endpoints — use para deduplicar. |
type | Tipo do evento (ver catálogo). |
version | Versão do contrato do envelope. Sempre 1 hoje. |
occurredAt | Quando o evento aconteceu no domínio (não quando foi entregue). Use para ordenar/desempatar — a entrega não garante ordem. |
workspace | Id e slug do workspace dono do evento. |
actor | Quem causou o evento: { type: "user" | "contact" | "automation" | "campaign" | "api_key" | "system", id?, name? }. Com type: "user", o id é o da membership do usuário no workspace (o mesmo de assignee.membershipId); com "contact", o id do contato; com "api_key", o id da chave. Sem marcação específica no caminho que originou a mudança, type é "system". |
data.object | O recurso no formato público da API (o mesmo formato de contato/empresa/negócio da API do CRM; mensagem, conversa, canal e campanha têm formato próprio, novo, feito para o webhook). |
data.previous | Só em eventos *.updated/*_changed: os campos que mudaram, com o valor anterior. Ausente quando não se aplica. |
test | true só no evento disparado manualmente pelo botão "Testar". Omitido (equivalente a false) em eventos reais. |
campo omitido ≠ campo null: trate os dois como "sem valor" ao consumir o payload; não assuma que um campo estará sempre presente.
Política de versão
Mudanças no contrato só são aditivas: um campo novo pode aparecer a qualquer momento em data.object, data.previous ou no próprio envelope, sem aviso prévio — sua integração deve ignorar campos desconhecidos. Renomear ou remover um campo existente, ou mudar o tipo de um tipo de evento, é mudança incompatível: sai como version: 2 (ou um tipo de evento novo), com um período de convivência antes de desligar o formato anterior.
Exemplo: message.received
{
"id": "evt_01j8x40htqb3nxrqz6tftg37z2",
"type": "message.received",
"version": 1,
"occurredAt": "2026-10-01T18:22:07.123456Z",
"workspace": { "id": "ws_9f2a...", "slug": "acme" },
"actor": { "type": "contact", "id": "cta_4f21..." },
"data": {
"object": {
"id": "msg_example",
"conversationId": "conv_example",
"contact": {
"id": "cta_example",
"name": "Maria Oliveira",
"phone": "+5511999990000"
},
"channel": {
"id": "ch_example",
"provider": "WHATSAPP",
"name": "Vendas"
},
"direction": "INBOUND",
"contentType": "TEXT",
"text": "Olá! Gostaria de saber mais sobre o produto.",
"media": null,
"sendStatus": null,
"deliveryStatus": "sent",
"sendError": null,
"createdAt": "2026-10-01T18:22:07.123456Z"
}
}
}Uma mensagem com mídia traz media preenchido, com uma URL assinada que expira em 7 dias (ver assinatura e segurança):
"media": {
"kind": "image",
"mimeType": "image/jpeg",
"size": 48213,
"fileName": "foto.jpg",
"url": "https://vensy.com.br/api/v1/webhook-media/ast_7f3c...?t=ws_9f2a...&exp=1738598400&sig=..."
}Exemplo: conversation.closed
{
"id": "evt_01j8x42n7wf9b3xqk1v5t8m6c4",
"type": "conversation.closed",
"version": 1,
"occurredAt": "2026-10-01T18:40:00.000000Z",
"workspace": { "id": "ws_9f2a...", "slug": "acme" },
"actor": { "type": "user", "id": "mem_8a21...", "name": "Ana Souza" },
"data": {
"object": {
"id": "conv_example",
"status": "CLOSED",
"channel": { "id": "ch_example", "provider": "WHATSAPP", "name": "Vendas" },
"contact": {
"id": "cta_example",
"name": "Maria Oliveira",
"phone": "+5511999990000"
},
"assignee": { "membershipId": "mem_8a21...", "name": "Ana Souza" },
"department": { "id": "dep_example", "name": "Vendas" },
"closureReason": "RESOLVED",
"createdAt": "2026-10-01T18:22:07.123456Z",
"closedAt": "2026-10-01T18:40:00.000000Z"
}
}
}