Skip to main content

Por que webhooks

Webhooks eliminam a necessidade de polling. Em vez de consultar o status repetidamente, o kycert notifica o seu servidor assim que o run é concluído. O endpoint recebe uma requisição POST com o resultado completo — você processa e responde em milissegundos.

Configuração

No dashboard kycert, vá em Settings → Webhooks e cadastre a URL do seu endpoint. Alternativamente, passe webhook_url diretamente no POST /runs para sobrescrever o padrão por requisição.

Requisitos do endpoint

  • HTTPS obrigatório em produção (HTTP aceito apenas em sandbox)
  • Responder 2xx em até 30 segundos
  • Idempotente — o mesmo evento pode ser entregue mais de uma vez

Eventos disponíveis

EventoQuando é disparado
run.completedRun finalizado com decisão (completed, blocked, pending_review, partial)
run.failedFalha técnica irrecuperável — run não produziu resultado

Estrutura do payload

{
  "id": "evt_01J4ZR...",
  "object": "event",
  "event": "run.completed",
  "created": 1718200818,
  "livemode": true,
  "data": {
    "object": "run",
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "decision": "approved",
    "operative_decision": null,
    "risk_band": "baixo",
    "subject_type": "pf",
    "template_id": "661e9511-f3ac-52e5-b827-557766551111",
    "external_id": "cust_abc123",
    "metadata": { "channel": "app_mobile" },
    "created_at": "2026-06-12T14:00:00Z",
    "completed_at": "2026-06-12T14:00:18Z"
  }
}

Payload completo para run.failed

{
  "id": "evt_9a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d",
  "object": "event",
  "event": "run.failed",
  "created": 1781477806,
  "livemode": true,
  "data": {
    "object": "run",
    "id": "9ad7a680-0232-4da5-a3c5-934d65a87b1a",
    "status": "blocked",
    "decision": "rejected",
    "operative_decision": "rejected",
    "risk_band": "alto",
    "subject_type": "pf",
    "template_id": "f716ee22-3933-407b-9bf3-d82ab391ef94",
    "external_id": null,
    "metadata": {},
    "checks_summary": {
      "total": 19,
      "valid": 0,
      "invalid": 5,
      "no_data": 0,
      "error": 14
    },
    "created_at": "2026-06-14T22:56:44.091Z",
    "completed_at": "2026-06-14T22:56:44.091Z"
  }
}
run.failed usa status blocked quando o run foi bloqueado por regra crítica (decision: "rejected"), ou failed quando houve falha técnica irrecuperável (decision: null). Em ambos os casos, o formato do payload é idêntico.

Política de retry

Se o seu endpoint retornar um status fora de 2xx ou não responder em 30 segundos, o kycert tenta novamente com backoff exponencial:
TentativaDelay
15 min
215 min
330 min
41h
52h
66h
712h
Após 7 tentativas sem sucesso (total ~24h), o evento é marcado como failed e nenhuma nova tentativa é realizada. O histórico de tentativas fica disponível no dashboard.
Nunca retorne 4xx por erros de lógica interna. Se o seu código falhar após receber um evento válido, responda 200 e trate o erro internamente. Um 4xx indica ao kycert que o evento foi rejeitado — e ele não tentará novamente.

Deduplicação

O campo id do evento é único. Armazene os IDs processados para ignorar duplicatas em caso de retry:
// Exemplo com Redis
const wasProcessed = await redis.get(`webhook:${event.id}`)
if (wasProcessed) return // já processado
await redis.setex(`webhook:${event.id}`, 86400, '1')

// processar evento

Verificação de assinatura

Todo webhook inclui o header kycert-signature. Sempre verifique — qualquer servidor pode fazer POST para o seu endpoint. Consulte Segurança para o procedimento completo de verificação com exemplos em 3 linguagens.

Sandbox

Em sandbox, os webhooks são entregues normalmente. Use um serviço como webhook.site ou ngrok durante o desenvolvimento. O campo livemode: false identifica eventos de sandbox.