Skip to main content
O webhook é o caminho recomendado para produção. Polling é uma alternativa válida para integrações simples, depuração ou quando estimated_seconds for pequeno (abaixo de 30s).

Quando usar polling

CenárioRecomendado
estimated_seconds ≤ 30Polling com backoff
estimated_seconds > 30Webhook (evita timeout de serverless)
Debug / desenvolvimentoPolling é conveniente
Produção com alta volumetriaWebhook — polling em escala gera carga desnecessária

Algoritmo recomendado: backoff exponencial

Não faça polling em intervalo fixo. Use backoff exponencial com limite máximo:
TentativaAguardar antes de verificar
12s
25s
310s
4+30s (máximo)
Defina um timeout máximo de 5 minutos. Se o run ainda estiver em andamento após esse tempo, trate como falha e investigue via dashboard.

Exemplo Node.js

async function pollRunResult(
  runId: string,
  apiKey: string,
  timeoutMs = 5 * 60 * 1000,
): Promise<{ status: string; decision: string | null }> {
  const delays = [2_000, 5_000, 10_000]
  const maxDelay = 30_000
  const deadline = Date.now() + timeoutMs

  for (let attempt = 0; ; attempt++) {
    const res = await fetch(
      `https://admin.kycert.com.br/api/v1/bureau/runs/${runId}`,
      { headers: { 'x-api-key': apiKey } },
    )

    if (res.status === 200) {
      // Run finalizado
      return res.json()
    }

    if (res.status === 202) {
      // Run ainda em execução
      const { retry_after_seconds } = await res.json() as { retry_after_seconds: number }
      const delay = Math.min(
        retry_after_seconds ? retry_after_seconds * 1000 : (delays[attempt] ?? maxDelay),
        maxDelay,
      )

      if (Date.now() + delay > deadline) {
        throw new Error(`Run ${runId} não completou em ${timeoutMs / 1000}s`)
      }

      await new Promise(r => setTimeout(r, delay))
      continue
    }

    const err = await res.json().catch(() => ({}))
    throw new Error(`kycert error ${res.status}: ${JSON.stringify(err)}`)
  }
}

// Uso
const result = await pollRunResult('550e8400-...', process.env.KYCERT_API_KEY!)
console.log(result.status, result.decision)

Resposta durante execução (202)

Enquanto o run está em andamento, GET /bureau/runs/{run_id} retorna 202:
{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "running",
  "retry_after_seconds": 8,
  "livemode": true
}
Use retry_after_seconds como sugestão de quando verificar novamente.

Resposta quando finalizado (200)

{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "decision": "approved",
  "operative_decision": "approved",
  "risk_band": "baixo",
  "created_at": "2026-06-12T14:00:00Z",
  "completed_at": "2026-06-12T14:00:18Z",
  "livemode": true
}

Alternativa: webhook para runs de longa duração

Para runs com estimated_seconds > 30, o webhook é mais eficiente. Configure a URL de webhook no corpo do POST /runs:
{
  "template_id": "...",
  "subject": { "type": "pf", "doc": "12345678901" },
  "webhook_url": "https://seu-servidor.com/webhooks/kycert"
}
Consulte o Guia de webhook para o fluxo completo.