Fluxo completo end-to-end — o caminho principal para produção
Webhook é o caminho recomendado para produção. O fluxo é simples:
1. Configure o webhook endpoint (uma vez, no dashboard)2. POST /api/v1/bureau/runs → receba run_id3. kycert processa o bureau (5 a 30 segundos)4. kycert faz POST para seu endpoint com o resultado5. Verifique a assinatura6. Aja com base na decision
No dashboard kycert, vá em Settings → Webhooks e cadastre o URL HTTPS do seu servidor. O kycert enviará todos os resultados para esse endpoint.Alternativamente, passe webhook_url no corpo de cada POST /runs para sobrescrever o padrão por requisição.
Sempre verifique a assinatura. Qualquer pessoa na internet pode fazer POST para o seu endpoint — a verificação garante que o evento veio realmente do kycert.
import express from 'express'import crypto from 'crypto'function verifyKycertSignature( payload: Buffer, signature: string, secret: string,): boolean { // Formato: "t=1234567890,v1=abc123..." const parts = Object.fromEntries( signature.split(',').map(p => p.split('=') as [string, string]) ) const timestamp = parts['t'] const expected = parts['v1'] if (!timestamp || !expected) return false // Rejeitar eventos com mais de 5 minutos de diferença if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) return false const computed = crypto .createHmac('sha256', secret) .update(`${timestamp}.${payload.toString()}`) .digest('hex') return crypto.timingSafeEqual( Buffer.from(computed), Buffer.from(expected), )}const app = express()app.post( '/webhooks/kycert', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['kycert-signature'] as string const secret = process.env.KYCERT_WEBHOOK_SECRET! if (!verifyKycertSignature(req.body, signature, secret)) { return res.sendStatus(401) } // Responda 200 imediatamente — processe de forma assíncrona res.sendStatus(200) const event = JSON.parse(req.body.toString()) setImmediate(() => handleKycertEvent(event)) })async function handleKycertEvent(event: Record<string, unknown>) { if (event['event'] === 'run.completed') { const data = event['data'] as Record<string, unknown> const { decision, risk_band, external_id } = data as { decision: string risk_band: string external_id: string } console.log(`Run ${external_id}: ${decision} (${risk_band})`) // ex: atualizar status do cliente no banco de dados }}