Voltar ao site
Syncro

Webhooks

Assine eventos e receba notificações em tempo real na sua URL, com cada entrega assinada via HMAC.

Base URLhttps://app.syncro.chat/api/v1AuthX-API-Key: crm_SUA_CHAVE_AQUI

Listar assinaturas

GET/webhooks
Permissão: webhooks:read

Lista as assinaturas de webhook da conta.

Requisição
curl "https://app.syncro.chat/api/v1/webhooks" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Resposta
{
  "success": true,
  "data": [
    {
      "id": 1,
      "target_url": "https://seu-sistema.com/webhooks/syncro",
      "events": [
        "lead.created",
        "lead.updated"
      ],
      "source": "api",
      "is_active": true,
      "failure_count": 0,
      "last_success_at": "2026-06-30T10:05:00Z",
      "last_failure_at": null,
      "created_at": "2026-06-15T14:30:00Z"
    }
  ],
  "supported_events": [
    "lead.created",
    "lead.updated",
    "lead.stage_changed",
    "..."
  ]
}

Criar assinatura

POST/webhooks
Permissão: webhooks:write

Cria uma assinatura apontando para a sua URL e escolhe quais eventos receber.

Parâmetros do body

target_urlstring (URL)obrigatório
URL que receberá os POST
eventsarray(string)obrigatório
Eventos a assinar (ver lista)
sourcestringopcional
api (padrão) ou n8n
secretstringopcional
Segredo do HMAC. Se omitido, o Syncro **gera um** e o retorna
i

Guarde o secret: você vai usá-lo para validar a assinatura de cada entrega.

Requisição
curl -X POST "https://app.syncro.chat/api/v1/webhooks" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "target_url": "https://seu-sistema.com/webhooks/syncro",
    "events": [
      "lead.created",
      "lead.won",
      "task.completed"
    ]
  }'
Resposta
{
  "success": true,
  "id": 1,
  "secret": "f3a9c2...e1",
  "events": [
    "lead.created",
    "lead.won",
    "task.completed"
  ]
}

Detalhe de uma assinatura

GET/webhooks/1
Permissão: webhooks:read

Retorna os dados de uma assinatura específica.

Requisição
curl "https://app.syncro.chat/api/v1/webhooks/1" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Resposta
{
  "success": true,
  "id": 1,
  "target_url": "https://seu-sistema.com/webhooks/syncro",
  "events": [
    "lead.created",
    "lead.updated"
  ],
  "source": "api",
  "is_active": true,
  "failure_count": 0,
  "last_success_at": "2026-06-30T10:05:00Z",
  "last_failure_at": null,
  "last_failure_reason": null
}

Atualizar assinatura

PUT/webhooks/1
Permissão: webhooks:write

Atualize a URL, os eventos ou ative/desative. Reativar (is_active: true) zera o contador de falhas.

Parâmetros (body, todos opcionais)

target_urlstring (URL)opcional
Nova URL
eventsarray(string)opcional
Nova lista de eventos
is_activebooleanopcional
Ativa/desativa
Requisição
curl -X PUT "https://app.syncro.chat/api/v1/webhooks/1" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      "lead.created"
    ],
    "is_active": true
  }'
Resposta
{
  "success": true,
  "id": 1,
  "events": [
    "lead.created"
  ],
  "is_active": true
}

Remover assinatura

DELETE/webhooks/1
Permissão: webhooks:write

Remove uma assinatura de webhook.

Requisição
curl -X DELETE "https://app.syncro.chat/api/v1/webhooks/1" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Resposta
{
  "success": true
}

Como a entrega funciona

Quando um evento assinado ocorre, o Syncro faz um POST (JSON) na sua target_url.

Envelope

Todo evento chega neste formato:

{
  "event": "lead.created",
  "tenant_id": 1,
  "emitted_at": "2026-06-30T10:00:00Z",
  "data": {
    "...": "payload específico do evento"
  }
}

Headers da entrega

Header Valor
Content-Type application/json
User-Agent Syncro-CRM-Webhook/1.0
X-Syncro-Event nome do evento (ex.: lead.created)
X-Syncro-Delivery ID único da entrega
X-Syncro-Signature sha256=<hmac> — assinatura HMAC do corpo

Validando a assinatura (HMAC)

A assinatura é o HMAC-SHA256 do corpo bruto da requisição, usando o secret da assinatura como chave. O header vem como sha256=<hash_hexadecimal>.

Calcule o HMAC sobre o corpo bruto recebido (não re-serialize o JSON) e compare com o valor após sha256=.

Node.js (Express)

const crypto = require('crypto');

// use o corpo BRUTO: app.use(express.raw({ type: 'application/json' }))
function verify(req, secret) {
  const header = req.get('X-Syncro-Signature') || '';
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(req.body) // Buffer com o corpo bruto
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

PHP

$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
$ok = hash_equals($expected, $_SERVER['HTTP_X_SYNCRO_SIGNATURE'] ?? '');

Responda com 2xx para confirmar o recebimento. Qualquer outro status é tratado como falha.

Reentregas e retry

  • O Syncro tenta entregar até 4 vezes, com espera crescente: 10s, 1min, 5min, 15min.
  • Respostas 5xx, 408 e 429 são reenviadas. Respostas 4xx (exceto 408/429) não são reenviadas (erro do receptor).
  • Após 10 falhas consecutivas, a assinatura é desativada automaticamente (reative com PUT /webhooks/{id} e is_active: true).
  • Faça o seu endpoint idempotente (pode receber a mesma entrega mais de uma vez); use o X-Syncro-Delivery para deduplicar.

Eventos disponíveis

Evento Quando dispara
lead.created Lead criado
lead.updated Lead atualizado
lead.stage_changed Lead mudou de etapa
lead.won Lead marcado como ganho
lead.lost Lead marcado como perdido
lead.deleted Lead excluído
lead.assignment_changed Responsável do lead mudou
lead.merged Leads mesclados
lead.tags_changed Tags do lead mudaram
sale.created Venda registrada
note.added Nota adicionada a um lead
nps.answered Pesquisa NPS respondida
task.created Tarefa criada
task.updated Tarefa atualizada
task.completed Tarefa concluída
conversation.message_received Reservado (ainda não emitido)

Exemplos de payload

Exemplos do campo data:

lead.created / lead.updated / lead.deleted

{
  "id": 123,
  "name": "João Silva",
  "email": "[email protected]",
  "phone": "+5511999887766",
  "company": "ACME",
  "value": 5000.0,
  "source": "site",
  "status": "open",
  "pipeline_id": 1,
  "pipeline_name": "Vendas",
  "stage_id": 5,
  "stage_name": "Proposta",
  "assigned_to": 12,
  "owner": { "id": 12, "name": "Ana", "email": "[email protected]" },
  "tags": ["vip"],
  "utm_source": "google",
  "utm_medium": "cpc",
  "utm_campaign": "verao_2026",
  "utm_term": null,
  "utm_content": null,
  "fbclid": null,
  "gclid": null,
  "custom_fields": { "tamanho_empresa": "100+" },
  "created_at": "2026-06-30T10:00:00Z",
  "updated_at": "2026-06-30T10:00:00Z"
}

lead.stage_changed / lead.won / lead.lost — o mesmo objeto de lead, mais:

{
  "previous_stage_id": 4,
  "new_stage_id": 5,
  "new_stage_name": "Proposta"
}

sale.created

{
  "sale_id": 1,
  "lead_id": 123,
  "pipeline_id": 1,
  "value": 5000.0,
  "closed_by": 12,
  "closed_at": "2026-06-30T10:05:00Z",
  "lead": {
    "id": 123,
    "name": "João Silva",
    "email": "[email protected]",
    "phone": "+5511999887766",
    "company": "ACME",
    "pipeline_id": 1,
    "stage_id": 10,
    "owner": { "id": 12, "name": "Ana", "email": "[email protected]" }
  }
}

task.created / task.updated / task.completed

{
  "id": 45,
  "subject": "Enviar proposta",
  "type": "email",
  "status": "completed",
  "priority": "high",
  "due_date": "2026-07-01",
  "due_time": "09:00",
  "completed_at": "2026-06-30T11:30:00Z",
  "lead_id": 123,
  "assigned_to": 12,
  "created_at": "2026-06-30T08:00:00Z",
  "updated_at": "2026-06-30T11:30:00Z"
}

note.added, nps.answered, lead.assignment_changed, lead.merged e lead.tags_changed seguem o mesmo envelope, com o data específico do evento (incluindo o lead de contexto quando aplicável).