Saltar para o conteúdo principal
Webhooks permitem que a Vendaze notifique seu aplicativo quando eventos ocorrem no workspace. Em vez de polling, seu servidor recebe um POST HTTP no momento em que algo muda. Webhooks podem ser criados e gerenciados de duas formas:
  • Pelo cliente da Vendaze diretamente no painel da plataforma
  • Via API pública, usando o scope webhooks:manage

Como funciona

  1. Um webhook é criado com uma URL de destino e a lista de eventos a monitorar
  2. Quando um evento ocorre, a Vendaze enfileira a entrega e faz um POST para essa URL
  3. Seu servidor processa o payload e retorna 2xx em até 10 segundos

Gerenciar webhooks via API

Webhooks criados via API são visíveis apenas para o app OAuth que os criou. Eles não aparecem no painel da Vendaze e não podem ser gerenciados por outros apps, mesmo que esses apps acessem o mesmo workspace.
EndpointDescrição
GET /v1/webhooksLista os webhooks criados pelo seu app
POST /v1/webhooksCria um webhook
GET /v1/webhooks/:idBusca um webhook pelo ID
PATCH /v1/webhooks/:idAtualiza um webhook
DELETE /v1/webhooks/:idDeleta um webhook

Autenticação de entregas

Quando auth_enable: true é enviado na criação do webhook, a Vendaze gera um webhook_secret (formato: whsec_...) e o inclui na resposta de POST /v1/webhooks. Guarde-o: ele será usado para verificar as entregas recebidas. Cada entrega para o seu endpoint incluirá o header Webhook-Signature. Consulte Verificação de assinatura para os detalhes de implementação. Alterar auth_enable em um webhook existente afeta o secret:
  • false para true: um novo webhook_secret é gerado e retornado
  • true para false: o webhook_secret existente é deletado permanentemente

Payload

Cada entrega é um POST com Content-Type: application/json. A estrutura do envelope é:
CampoTipoDescrição
idstringID único da entrega. Use para deduplicação.
eventstringNome do evento, ex: person.created
versionstringSempre v1
created_atstringTimestamp ISO 8601 UTC de quando o evento foi disparado
<entidade>objectOs dados da entidade. A chave corresponde ao tipo do evento: person, company, deal, task, activity, tag, product, pipeline ou member
{
  "id": "event_3f9a1c8b2d...",
  "event": "person.created",
  "version": "v1",
  "created_at": "2026-05-26T14:00:00.000Z",
  "person": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "full_name": "Ana Costa",
    "email": { "1": "ana@empresa.com" },
    "created_at": "2026-05-26T14:00:00Z"
  }
}

Verificação de assinatura

Quando auth_enable é true, cada entrega inclui:
Webhook-Signature: sha256=<hex>
O valor é HMAC-SHA256 calculado sobre os bytes brutos do corpo da requisição, codificado em hex. Leia sempre os bytes brutos antes de fazer parsing: re-serializar o body pode alterar espaços ou ordem de chaves e causar falha na verificação. Node.js:
const crypto = require('crypto');

function isValidSignature(rawBody, receivedSignature, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(expected));
}

// Express: leia os bytes brutos antes de qualquer parsing de JSON
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['webhook-signature'];
  if (!sig || !isValidSignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).end();
  }
  const payload = JSON.parse(req.body);
  res.sendStatus(200);
  processEvent(payload); // assíncrono, após responder
});
Python:
import hmac, hashlib

def is_valid_signature(raw_body: bytes, received: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(received, expected)
Use sempre comparação em tempo constante (timingSafeEqual / hmac.compare_digest). Comparação de strings comum é vulnerável a ataques de timing.

Eventos disponíveis

EventoGatilho
person.createdUma pessoa é criada
person.updatedUma pessoa é atualizada
person.deletedUma pessoa é deletada
EventoGatilho
company.createdUma empresa é criada
company.updatedUma empresa é atualizada
company.deletedUma empresa é deletada
EventoGatilho
deal.createdUm negócio é criado
deal.updatedUm negócio é atualizado
deal.stage_changedUm negócio muda de etapa
deal.wonUm negócio é marcado como ganho
deal.lostUm negócio é marcado como perdido
deal.deletedUm negócio é deletado
EventoGatilho
task.createdUma tarefa é criada
task.updatedUma tarefa é atualizada
task.completedUma tarefa é concluída
task.deletedUma tarefa é deletada
EventoGatilho
activity.createdUma atividade é registrada
activity.updatedUma atividade é atualizada
activity.deletedUma atividade é deletada
EventoGatilho
product.createdUm produto é criado
product.updatedUm produto é atualizado
product.deletedUm produto é deletado
EventoGatilho
tag.createdUma tag é criada
tag.updatedUma tag é atualizada
tag.deletedUma tag é deletada
EventoGatilho
pipeline.createdUm pipeline é criado
pipeline.updatedUm pipeline é atualizado
pipeline.deletedUm pipeline é deletado
EventoGatilho
member_invitedUm membro é convidado para o workspace
member_joinedUm membro entra no workspace
member_removedUm membro é removido do workspace
EventoGatilho
usage_logs.createdUm registro de uso é gerado

Reenvios e garantias de entrega

Se seu servidor não retornar 2xx em 10 segundos, a Vendaze tenta a entrega até 3 vezes, cada tentativa com 15 minutos de espera. Após esgotar todas as tentativas, o evento é descartado permanentemente. Não existe mecanismo de suspensão: entregas não concluídas são perdidas.
TentativaEspera
1 (inicial)Imediata
215 minutos após tentativa 1
315 minutos após tentativa 2
415 minutos após tentativa 3
A Vendaze entrega com semântica at-least-once. O mesmo evento pode ser entregue mais de uma vez por problemas de rede ou sobreposição de reenvios. Deduplique usando o campo id do envelope.
async function handleWebhook(payload) {
  if (await db.events.findOne({ id: payload.id })) return;
  await db.events.insert({ id: payload.id, processedAt: new Date() });
  await processEvent(payload);
}

Boas práticas

  • Retorne 200 imediatamente e processe de forma assíncrona. Qualquer handler que demore mais de 10 segundos vai disparar um reenvio.
  • Rejeite assinaturas ausentes ou inválidas com 401. Nunca processe uma entrega de um endpoint autenticado sem verificar a assinatura antes.
  • Retenha os payloads recebidos por pelo menos 30 dias para facilitar debugging e auditoria.
  • Retorne 200 para tipos de evento não reconhecidos. Novos eventos serão adicionados ao longo do tempo e ignorá-los silenciosamente mantém seu handler estável nas atualizações da API.