Voltar para Documentação

Webhooks

Estável

Receba eventos da Riskora no seu sistema (outbound) ou envie eventos do seu sistema pra Riskora (inbound). Em ambas as direções, a comunicação é HTTP POST assinada com HMAC-SHA256.

Duas direções

O sistema de webhooks da Riskora suporta as duas pontas da integração transacional. Headers, formato de assinatura, retry e idempotência seguem contratos públicos versionados — mudanças com impacto são comunicadas com antecedência aos clientes integrados.

Outbound

Riskora envia POST assinado pro seu sistema sempre que acontece uma mudança na entidade que você assinou (criação, alteração, finalização, etc.).

Inbound

Seu sistema envia POST assinado pra um endpoint da Riskora; o payload dispara um processo configurado (ex: atualizar histórico do avaliado, criar análise).

Outbound · Riskora → seu sistema

Quando usar

A API REST permite consultar o estado de qualquer registro a qualquer momento, mas consultar em loop é caro. Webhook é o canônico pra reagir no segundo que algo muda.

  • Checkout transacional: cliente esperando aprovação. Receba a finalização da análise e libere o pedido automaticamente.
  • Sincronização de ERP: mantenha limite de crédito e score do avaliado no seu ERP sempre atualizado, sem cron diário.
  • Alerta de equipe: análise caiu em revisão manual; notifique o analista de plantão via Slack, Teams ou ticket.
  • Notificação ao vendedor: aviso imediato quando a análise da carteira é aprovada, rejeitada ou precisa de reenvio de documentos.

Como assinar eventos

A assinatura é por tabela + tipo de gatilho, não por evento semântico. Você define quais entidades quer monitorar e qual mudança dispara a notificação. O payload pode usar um template customizado pra entregar JSON limpo, com nomes e estrutura que façam sentido pro seu sistema.

Gatilhos disponíveis
CódigoQuando disparaUso típico na Riskora
TANRegistro criadoAnálise nova, avaliado novo
TACRegistro alteradoMudança de status da análise, atualização de score do avaliado
TADRegistro removidoAuditoria de exclusão (raro em entidades de avaliação)
DACODocumento finalizadoReservado pra fluxos transacionais
DAVODocumento anuladoReservado pra fluxos transacionais
DACLDocumento encerradoReservado pra fluxos transacionais

Pra avaliações, os gatilhos relevantes são TAN e TAC em Z_Eval_Analysis e Z_Evaluee. O gatilho dispara em qualquer alteração da tabela; filtros por valor (ex: só quando z_EvalStatus = AP) ficam no seu lado, lendo o payload.

Exemplo · Notificação de finalização de análise

Cenário: você quer ser notificado sempre que uma análise muda de estado, com payload contendo só os campos do seu interesse.

Configuração da inscrição
CampoValor
TabelaZ_Eval_Analysis
GatilhoTAC
URL de destinohttps://erp.cliente.com/webhooks/riskora
Assinatura HMACHabilitada (padrão recomendado)
Template de payload (opcional)

Cada @ColumnName@ é substituído pelo valor do registro alterado. Sem template, o plugin envia o registro inteiro com todas as colunas da tabela.

json template
{
  "analysis_value": "@Value@",
  "reference_no": "@z_ReferenceNo@",
  "evaluee_id": @Z_Evaluee_ID@,
  "status": "@z_EvalStatus@",
  "final_score": @z_FinalScore@,
  "tier": "@z_TierValue@",
  "approved_limit": @z_ApprovedLimit@,
  "calculated_limit": @z_CalculatedLimit@,
  "risk_level": "@z_RiskLevel@",
  "ai_recommendation": "@z_AIRecommendation@"
}
O que chega no seu endpoint
POST request
POST /webhooks/riskora HTTP/1.1
Host: erp.cliente.com
Content-Type: application/json
webhook-id: msg_01hxyza1b2c3d4e5f6g7h8j9k0
webhook-timestamp: 1712587330
webhook-signature: v1,a591a6d40bf42040eb...

{
  "analysis_value": "RK-PJ_AVANCADA_IC943",
  "reference_no": "PED-2026-1234",
  "evaluee_id": 1000042,
  "status": "AP",
  "final_score": 782,
  "tier": "B",
  "approved_limit": 45000,
  "calculated_limit": 50000,
  "risk_level": "L",
  "ai_recommendation": "APROVAR"
}

No seu lado, filtre por status em ["AP", "RJ", "CA", "EX"] pra reagir só nas finalizações. Outras transições intermediárias (ex: DR → IP, IP → MR) chegam pelo mesmo gatilho.

Segurança · HMAC-SHA256

Toda requisição com assinatura habilitada vai assinada. Seu endpoint deve validar a assinatura antes de processar — sem isso, qualquer um que descobrir a URL pode forjar eventos.

Headers enviados
HeaderFormatoExemplo
webhook-idmsg_<uuid>msg_01hxyza1b2c3d4e5f6g7h8j9k0
webhook-timestampunix epoch (segundos)1712587330
webhook-signaturev1,<base64> (espaço-separado em rotação)v1,a591a6d40bf42040eb...

O secret é gerado no painel com prefixo whsec_. Pra validar, decodifique o base64 do que vem depois do prefixo e use como chave HMAC.

Validação · Node.js
javascript
import crypto from 'crypto';

// Secret recebido no setup, sem o prefixo whsec_
const SECRET_BASE64 = process.env.RISKORA_WEBHOOK_SECRET;
const secretKey = Buffer.from(SECRET_BASE64, 'base64');

export async function handleWebhook(req) {
  // 1. Lê o RAW body antes de qualquer parse
  const rawBody = await req.text();

  // 2. Verifica janela de 5 minutos (anti-replay)
  const timestamp = req.headers.get('webhook-timestamp');
  const age = Math.floor(Date.now() / 1000) - Number(timestamp);
  if (Math.abs(age) > 300) {
    return new Response('Timestamp expirado', { status: 400 });
  }

  // 3. Reconstrói o conteúdo assinado
  const msgId = req.headers.get('webhook-id');
  const signed = `${msgId}.${timestamp}.${rawBody}`;

  // 4. Calcula a assinatura esperada
  const expected = crypto
    .createHmac('sha256', secretKey)
    .update(signed)
    .digest('base64');

  // 5. Compara em tempo constante (suporta rotação de secret)
  const received = req.headers.get('webhook-signature') ?? '';
  const ok = received.split(' ').some(sig => {
    const value = sig.startsWith('v1,') ? sig.slice(3) : sig;
    try {
      return crypto.timingSafeEqual(
        Buffer.from(value, 'base64'),
        Buffer.from(expected, 'base64')
      );
    } catch { return false; }
  });
  if (!ok) return new Response('Assinatura inválida', { status: 401 });

  // 6. OK: processar
  const payload = JSON.parse(rawBody);
  // ... lógica do seu sistema
  return new Response('ok', { status: 200 });
}

Retry e idempotência

Entrega at-least-once. Sucesso é qualquer resposta HTTP 2xx; falha (timeout ou 5xx) reagenda nova tentativa. Após o teto de tentativas, a inscrição pode ser auto-pausada e a entrega marcada como abandonada.

TentativaDelayJanela acumulada
1imediato0s
2+5s5s
3+5min5min 5s
4+30min35min 5s
5+2h2h 35min
6+5h7h 35min
7+10h17h 35min
8+14h1d 7h 35min
9+20h2d 3h 35min
10+24h3d 3h 35min
desistemarca delivery_failed

Cada tentativa aplica jitter de ±15%. O teto e o timeout HTTP são configuráveis via SysConfig; o default é razoável pra grande maioria dos casos.

Idempotência é responsabilidade do consumidor: o mesmo evento pode chegar mais de uma vez (retry após timeout do seu lado, por exemplo). Sempre persista o webhook-id processado e ignore duplicatas.

Inbound · seu sistema → Riskora

Quando usar

Quando seu sistema é a fonte de um evento que precisa refletir na Riskora — uma compra fechada, um cliente que mudou de status, um pagamento confirmado. Ao invés de fazer várias chamadas REST sequenciais, você posta um JSON num endpoint e a Riskora dispara o processo certo.

  • Atualização de histórico do avaliado: seu ERP fecha um pedido; envia o evento e a Riskora atualiza z_LastPurchaseDate, z_TotalPurchases12m, z_AverageTicket.
  • Notificação de pagamento: sistema de cobrança confirma quitação; a Riskora reflete em z_PaymentBehavior.
  • Disparo de análise via evento: CRM detecta lead qualificado; chama o webhook e a Riskora cria a análise correspondente.

Como funciona

Cada caso de uso de inbound é uma combinação endpoint + processo:

  1. 1.Você define com a equipe Riskora o caso de uso: qual payload o seu sistema vai enviar e que ação isso dispara na plataforma.
  2. 2.A Riskora cria o processo que recebe o payload (nativo ou via Groovy/Java) e configura o endpoint /api/v1/webhooks/{key} com seu próprio secret.
  3. 3.Você recebe a URL do endpoint, o secret pra assinar e (opcional) a lista de IPs/CIDR que será aceita.
  4. 4.Seu sistema posta JSON assinado; a Riskora valida assinatura, detecta duplicata pelo webhook-id, e roda o processo.

Verificação de assinatura é altamente recomendada e fica habilitada por padrão. Sem assinatura, qualquer requisição ao endpoint é processada — só faz sentido em ambiente fechado com lista de IPs muito restrita.

Exemplo · ERP atualizando histórico de compra

Cenário: cada vez que seu ERP fecha um pedido, você quer que a Riskora atualize o histórico do avaliado pra a próxima análise já considerar o dado novo.

Endpoint configurado
url
POST https://app.riskora.ai/api/v1/webhooks/erp-pedido-fechado
Payload acordado
json
{
  "evaluee_document": "13823508000131",
  "purchase_date": "2026-05-08",
  "purchase_amount": 18500.00,
  "payment_status": "PAID",
  "external_order_id": "PED-2026-1234"
}
Envio assinado · curl
bash
SECRET_BASE64="<parte depois do whsec_>"
BODY='{"evaluee_document":"13823508000131","purchase_date":"2026-05-08","purchase_amount":18500.00,"payment_status":"PAID","external_order_id":"PED-2026-1234"}'
MSG_ID="msg_$(uuidgen)"
TIMESTAMP=$(date +%s)

SIGNATURE=$(printf '%s.%s.%s' "$MSG_ID" "$TIMESTAMP" "$BODY" \
  | openssl dgst -sha256 -hmac "$(printf '%s' "$SECRET_BASE64" | base64 -d)" -binary \
  | base64)

curl -X POST https://app.riskora.ai/api/v1/webhooks/erp-pedido-fechado \
  -H "Content-Type: application/json" \
  -H "webhook-id: $MSG_ID" \
  -H "webhook-timestamp: $TIMESTAMP" \
  -H "webhook-signature: v1,$SIGNATURE" \
  -d "$BODY"
Respostas possíveis
StatusBodySignificado
200{"status":"ok"}Processo executou com sucesso
200{"status":"duplicate"}Mesmo webhook-id já processado; idempotente
400erroHeader obrigatório ausente ou timestamp expirado
401erroAssinatura inválida
403erroIP de origem não autorizado
404erroEndpoint key inexistente

webhook-id é obrigatório quando a verificação de assinatura está habilitada. Use UUID/ULID — repostar com o mesmo ID retorna duplicate sem re-rodar o processo.

Limites e considerações

  • Tamanho do payload: hoje limitado a 4000 caracteres por chamada inbound. Pra volumes maiores, fragmentar ou usar a API REST diretamente.
  • Conteúdo: apenas application/json é suportado. Binários não são aceitos.
  • Idempotência: o controle pelo webhook-id só funciona se a verificação de assinatura estiver habilitada. Forte recomendação de manter habilitada.
  • IP allowlist: opcional, mas recomendada se o seu sistema sai de IPs conhecidos. Aceita CIDR (ex: 200.10.0.0/24).

Quero integrar. E agora?

  1. 1.Entre em contato pelo formulário informando se precisa de outbound, inbound ou ambos.
  2. 2.Pra outbound: você descreve as entidades e gatilhos que quer assinar (e, se quiser, o template de payload). A Riskora configura a inscrição e devolve URL de destino + secret pra você usar do seu lado.
  3. 3.Pra inbound: você descreve o caso de uso (qual evento dispara qual ação na Riskora, formato do payload). A Riskora configura o processo, o endpoint e devolve URL + secret + IPs autorizados.
  4. 4.Validação em ambiente de homologação com eventos sintéticos antes da virada pra produção.
Falar com a equipe

Ainda com dúvidas?

A equipe técnica pode revisar o caso de uso e recomendar a melhor estratégia (API, webhook outbound, inbound ou combinação).