Openi DeveloperDeveloper
Guia de integração

Webhooks de saída

Registrar endpoints, formato das entregas, assinatura HMAC e SLA.

Registrar um endpoint

POST /v1/webhooks

{
  "url": "https://app.cliente.com.br/integracoes/nexus",
  "secret": "um-segredo-forte-min-16-chars",
  "events": ["match.created"],
  "active": true,
  "maxAttempts": 5,
  "baseBackoffMs": 1000,
  "redactedFields": ["data.cpf", "data.cartao"]
}
  • url — endpoint HTTPS que receberá os eventos.
  • secret — segredo compartilhado usado para assinar o corpo (HMAC‑SHA‑256). Mínimo 16 caracteres recomendado.
  • events — lista de eventos a assinar. Default: ["match.created"] se omitido ou vazio. Eventos suportados:
    • match.created — novo match individual emitido após cada execução de rule set.
    • composite_match.created — novo match composto criado.
    • composite_match.completed — match composto fechou todos os lados esperados.
    • composite_match.extended — match composto recebeu mais um lado.
    • reconciliation_job.completed — job de conciliação finalizou.
    • test.ping — evento sintético usado por POST /v1/webhooks/{id}/test.
  • active (default true) — se false, o Nexus para de enviar (ainda registra webhook_deliveries).
  • maxAttempts (1..50, default 5) — tentativas totais antes de mover para dead_letter.
  • baseBackoffMs (100..60000, default 1000) — base do backoff exponencial entre tentativas.
  • redactedFields — JSONPaths (notação por pontos) que serão mascarados antes do envio (ex.: data.cpf).

Outras operações:

GET    /v1/webhooks
GET    /v1/webhooks/{id}
PATCH  /v1/webhooks/{id}
DELETE /v1/webhooks/{id}
POST   /v1/webhooks/{id}/test          # envia um evento test.ping
GET    /v1/webhook-deliveries          # auditoria das entregas

Formato das entregas

O Nexus envia POST <url> com:

Headers

Content-Type: application/json
X-Nexus-Event: match.created
X-Nexus-Id: <eventId UUID>
X-Nexus-Timestamp: 1746540330123        # epoch em ms (string)
X-Nexus-Signature: sha256=<hex>

Body (envelope)

{
  "specversion": "1.0",
  "schema_version": 1,
  "type": "match.created",
  "id": "<eventId UUID>",
  "time": "2026-05-06T14:05:30.123Z",
  "tenant_id": "<tenant uuid>",
  "source": "nexus",
  "data": {
    "tenantId": "<tenant uuid>",
    "matchId": "match-uuid",
    "score": 0.97,
    "decision": "MATCH",
    "timestamp": "2026-05-06T14:05:30.123Z",
    "ruleSet": { /* metadados do rule set */ },
    "left":  { /* dados do record left */ },
    "right": { /* dados do record right */ },
    "explanation": { /* features retornadas pelo JSONata */ }
  }
}

O envelope externo usa snake_case (campos do CloudEvents). Já o objeto data é específico de cada evento e usa camelCase (matchId, ruleSet, etc.).

Verificação da assinatura

X-Nexus-Signature é calculada como:

base = `${X-Nexus-Timestamp}.${X-Nexus-Id}.${rawBody}`
signature = "sha256=" + HMAC_SHA256(secret, base).hex()

Pseudocódigo de verificação (Node.js):

import crypto from "node:crypto";

function verify(req, secret) {
  const ts = req.header("X-Nexus-Timestamp");
  const id = req.header("X-Nexus-Id");
  const sig = req.header("X-Nexus-Signature");
  const rawBody = req.rawBody; // bytes do request, sem reserialização

  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(`${ts}.${id}.${rawBody}`)
    .digest("hex");

  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Assine sobre o corpo bruto exato que chegou. Reserializar JSON quebra a assinatura.

SLA de resposta e idempotência

  • Sucesso: o Nexus considera entregas com status 2xx como bem‑sucedidas.
  • Falha: outros códigos disparam retentativa exponencial (baseBackoffMs * 2^(tentativa-1)) até maxAttempts. Após esgotar, a entrega vai para dead_letter e gera alerta.
  • Classificação interna do erro (visível em GET /v1/webhook-deliveries):
    • 408 → timeout
    • 429 → throttled
    • 5xx → server (retentativa)
    • 4xx (exceto 408/429) → permanent.
  • Idempotência: sua aplicação deve tratar entregas como idempotentes. Use X-Nexus-Id como chave de deduplicação e responda 2xx mesmo em reentregas conhecidas.
  • Timeout sugerido: responda em ≤ 30s (default do sender).
  • Auditoria: GET /v1/webhook-deliveries lista cada tentativa com status HTTP, latência, classificação e timestamp.

Para payloads e semântica dos eventos composite_match.*, veja Matching composicional.

On this page