Voltar para Documentação

Webhooks

Beta

Receba notificações em tempo real quando eventos importantes acontecem na Riskora — sem precisar fazer polling. Ideal para integrações transacionais com ERP, sistemas de checkout, CRM e ferramentas de comunicação interna.

Funcionalidade em Beta

O catálogo de eventos abaixo é o contrato público que vamos entregar. A implementação está sendo finalizada — o lançamento para clientes acontece ao longo do trimestre. O formato dos payloads e eventos documentados aqui é estável e não sofrerá breaking changes no lançamento.

Quer participar do beta e integrar antes do lançamento geral? Fale com nossa equipe.

Quando usar webhooks

A API REST da Riskora permite consultar o estado de qualquer análise a qualquer momento. Mas consultar em loop (polling) é caro, lento e pouco elegante quando você precisa reagir no segundo que algo muda. Webhook é o mecanismo canônico para:

  • Checkout transacional: cliente esperando aprovação — cada segundo importa. Receba analysis.finalized e libere o pedido automaticamente.
  • Alerta de equipe: análise caiu em revisão manual — notifique o analista de plantão via Slack, Teams ou sistema de tickets.
  • Sincronização de ERP: mantenha o limite de crédito do cliente no seu ERP sempre atualizado — sem cron diário, sem polling.
  • Notificação ao vendedor: vendedor recebe aviso imediato quando sua análise é aprovada, rejeitada ou precisa de reenvio de documentos.

Catálogo de eventos

analysis.finalized

A análise transitou para um estado final: aprovada, rejeitada, cancelada ou expirada. Este é o evento mais importante — provavelmente o único que a maioria das integrações precisa consumir.

Uso típico: ERP libera pedido no checkout, dispara envio de contrato, atualiza dashboard.
Payload de exemplo
json
{
  "event": "analysis.finalized",
  "event_id": "evt_01hxyza1b2c3d4e5f6g7h8j9k0",
  "timestamp": "2026-04-08T14:22:10.123Z",
  "version": "1",
  "data": {
    "analysis_value": "RK-PJ_AVANCADA_IC943",
    "analysis_id": 1000156,
    "reference_no": "PED-2026-1234",
    "evaluee": {
      "value": "13823508000131",
      "reference_no": "CLI-0042",
      "type": "PJ",
      "name": "Grupo Mundo do Café S/A"
    },
    "policy": { "id": 1000001, "value": "PJ_AVANCADA" },
    "status": "AP",
    "status_label": "Aprovado",
    "final_score": 782,
    "tier": "B",
    "risk_level": "L",
    "requested_amount": 50000,
    "approved_limit": 45000,
    "calculated_limit": 50000,
    "ai_recommendation": "APROVAR",
    "ai_opinion_short": "Empresa com bom histórico e faturamento estável",
    "requires_approval": false,
    "approved_at": "2026-04-08T14:22:08.456Z",
    "approved_by": "analista@cliente.com.br"
  }
}

analysis.manual_review_required

A análise precisa de decisão humana. Pode ser por tier, alçada, hard stop de warning, ou divergência detectada pela IA. Carrega o motivo estruturado e link direto para o cockpit.

Uso típico: Notificar equipe de risco no Slack/Teams, criar ticket, disparar alerta SMS.
Payload de exemplo
json
{
  "event": "analysis.manual_review_required",
  "event_id": "evt_...",
  "timestamp": "2026-04-08T14:22:10.123Z",
  "version": "1",
  "data": {
    "analysis_value": "RK-PJ_AVANCADA_IC944",
    "reference_no": "PED-2026-1235",
    "evaluee": { "value": "13823508000131", "type": "PJ" },
    "reason": "TIER_REQUIRES_APPROVAL",
    "reason_label": "Tier C exige aprovação manual",
    "final_score": 612,
    "tier": "C",
    "risk_level": "M",
    "requested_amount": 80000,
    "calculated_limit": 30000,
    "required_approval_level": 2,
    "cockpit_link": "https://app.riskora.ai/cockpit/analysis/1000157",
    "pending_since": "2026-04-08T14:22:08.456Z"
  }
}

analysis.parameter_rejected

O analista rejeitou um ou mais parâmetros e solicitou reenvio. Útil para que seu ERP abra ticket de pendência ou dispare notificação própria ao avaliado, além da comunicação padrão da Riskora.

Uso típico: Criar ticket de pendência no ERP, enviar notificação personalizada ao cliente, adiar cobrança.
Payload de exemplo
json
{
  "event": "analysis.parameter_rejected",
  "event_id": "evt_...",
  "timestamp": "2026-04-08T14:22:10.123Z",
  "version": "1",
  "data": {
    "analysis_value": "RK-PJ_AVANCADA_IC943",
    "reference_no": "PED-2026-1234",
    "evaluee": { "value": "13823508000131" },
    "rejected_parameters": [
      {
        "value": "CONTRATO_SOCIAL",
        "name": "Contrato Social",
        "rejection_reason": "Documento ilegível — favor reenviar"
      }
    ],
    "rejected_by": "analista@cliente.com.br",
    "rejected_at": "2026-04-08T14:22:10.123Z",
    "resubmission_link": "https://riskora.ai/eval/collect/a1b2c3d4...",
    "resubmission_expires_at": "2026-04-15T14:22:10.123Z"
  }
}

evaluee.score_changed

O score, limite, tier ou nível de risco de um avaliado mudou como resultado de uma análise aprovada. Ideal para manter um cache local no ERP sem precisar fazer polling periódico.

Uso típico: Atualizar credit_limit no ERP, alertar se risk_level piorou, atualizar score no CRM.
Payload de exemplo
json
{
  "event": "evaluee.score_changed",
  "event_id": "evt_...",
  "timestamp": "2026-04-08T14:22:10.123Z",
  "version": "1",
  "data": {
    "evaluee_value": "13823508000131",
    "reference_no": "CLI-0042",
    "name": "Grupo Mundo do Café S/A",
    "type": "PJ",
    "previous": { "score": 720, "limit": 30000, "tier": "C", "risk_level": "M" },
    "current":  { "score": 782, "limit": 45000, "tier": "B", "risk_level": "L" },
    "delta": {
      "score": 62,
      "limit": 15000,
      "tier_changed": true,
      "risk_level_changed": true
    },
    "triggered_by_analysis": {
      "value": "RK-PJ_AVANCADA_IC943",
      "id": 1000156
    },
    "changed_at": "2026-04-08T14:22:08.456Z"
  }
}

analysis.created

Dispara imediatamente após uma análise ser criada (via API ou cockpit). Opcional — a maioria das integrações já tem essa informação pela resposta síncrona da criação. Útil para auditoria centralizada.

Uso típico: Audit trail externo, dashboards de volume, replicação de eventos para data warehouse.

analysis.hard_stop_triggered

Um hard stop crítico bloqueou a análise automaticamente (por exemplo, score de bureau abaixo do mínimo, CNPJ com restrição). Evento silenciado por padrão — ative explicitamente se sua organização precisar monitorar tentativas bloqueadas.

Uso típico: Dashboards de compliance, integração com sistema antifraude, blacklist compartilhada.

Envelope comum

Todo evento segue a mesma estrutura base, com campos fixos no envelope e payload específico em data.

typescript
interface WebhookEnvelope<T> {
  /** Nome do evento, dot-namespaced. Ex: "analysis.finalized" */
  event: string;
  /** ID único do evento. Use como chave de idempotência. */
  event_id: string;
  /** Timestamp ISO 8601 UTC com milissegundos */
  timestamp: string;
  /** Versão do schema. Breaking changes => bump. */
  version: "1";
  /** Payload específico do evento */
  data: T;
}

Segurança — HMAC Signature

Toda requisição enviada pela Riskora é assinada com HMAC-SHA256 usando um secret compartilhado. O consumidor deve validar a assinatura antes de processar o evento — sem isso, qualquer um que descobrir sua URL pode forjar eventos.

Headers enviados

http
POST /webhooks/riskora HTTP/1.1
Host: erp.cliente.com
Content-Type: application/json
User-Agent: Riskora-Webhooks/1.0
X-Riskora-Event: analysis.finalized
X-Riskora-Event-Id: evt_01hxyza...
X-Riskora-Timestamp: 1712587330
X-Riskora-Signature: sha256=a591a6d40bf42040...
X-Riskora-Delivery-Attempt: 1

Como validar

javascript
// 1. Recebe o raw body ANTES de JSON.parse
const rawBody = await req.text();

// 2. Verifica janela de 5 minutos contra replay
const timestamp = req.headers.get('x-riskora-timestamp');
const age = Math.floor(Date.now() / 1000) - Number(timestamp);
if (age > 300) throw new Error('Timestamp expirado');

// 3. Calcula HMAC esperado
const signed = `${timestamp}.${rawBody}`;
const expected = 'sha256=' + crypto
  .createHmac('sha256', WEBHOOK_SECRET)
  .update(signed)
  .digest('hex');

// 4. Comparação timing-safe
const received = req.headers.get('x-riskora-signature');
if (!crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(received)
)) {
  throw new Error('Assinatura inválida');
}

// 5. OK — processar o evento
const payload = JSON.parse(rawBody);

Retry e idempotência

A Riskora entrega cada evento com garantia at-least-once: em caso de falha (timeout, erro HTTP 5xx), reenviamos com backoff exponencial. Sucesso é considerado quando seu endpoint retorna HTTP 2xx.

TentativaDelayJanela acumulada
1imediato0s
2+30s30s
3+2min2min 30s
4+15min17min 30s
5+1h1h 17min
6+6h7h 17min
desistemarca delivery_failed

Idempotência é responsabilidade do consumidor: como o mesmo evento pode chegar mais de uma vez, sempre armazene o event_id e rejeite eventos já processados. Esta é a garantia mais forte que webhooks conseguem oferecer sem sacrificar disponibilidade.

Quero integrar. E agora?

  1. 1.Entre em contato com nossa equipe pelo formulário de contato informando seu interesse em consumir webhooks.
  2. 2.Receba suas credenciais (URL do ambiente de homologação + webhook secret) e documentação de endpoint para teste.
  3. 3.Configure o endpoint de destino no seu sistema seguindo o guia de validação HMAC acima.
  4. 4.Testamos juntos com eventos sintéticos em sandbox antes de habilitar em produção.
  5. 5.Após validação, ativação em produção e monitoramento conjunto da primeira semana.
Solicitar acesso ao beta

Ainda com dúvidas?

Nossa equipe técnica pode revisar seu caso de uso e recomendar a melhor estratégia de integração (API, webhook, ou ambos).

Falar com a equipe