Configurando webhooks

Toda confirmação de mudança de estado vem via webhook. Aqui você aprende a registrar sua URL, filtrar eventos, obter o secret de assinatura e validar o primeiro evento. A configuração detalhada de segurança vive em Webhooks · Configuração e segurança.

POST /webhook · GET /webhook · PATCH /webhook/{id}

Os endpoints de webhook ficam no serviço webhook-sender-manager (host próprio, ex.: https://webhook-sender-manager-production.iorq.com.br) e exigem o header Fund-Id além do Authorization.

1. Por que webhooks

O ciclo de uma operação envolve múltiplos atores fora do controle do integrador: validação de elegibilidade, geração de termo na administradora, coleta de assinaturas, desembolso bancário. Em vez de você ficar pollando estado, a IORQ te avisa quando algo muda.

  • Latência baixa — eventos são entregues em segundos após a mudança
  • Reentrega garantida — se sua URL falha, a IORQ retenta (ver Idempotência e reentrega)
  • Um tipo de mensagem — hoje a IORQ envia o message_type LOAN_UPDATE; o que mudou vem no data.status do payload

2. Pré-requisitos

  • Endpoint HTTPS público com certificado válido (TLS 1.2+). HTTP e self-signed são rejeitados.
  • Capacidade de responder rápido — após o timeout a IORQ considera falha e retenta.
  • Token Bearer JWT válido + header Fund-Id para chamar POST /webhook (ver Autenticação).
📘

Recomendação

Antes de processar o evento, enfileire-o (SQS, RabbitMQ, etc.) e responda 200 ao webhook. Processamento síncrono dentro do handler é frágil — uma lentidão downstream estoura o timeout de 10s.

3. Registrar uma URL de webhook

3.1 POST /webhook

POST /webhook · application/json

Campos do payload

CampoTipoDescrição
message_typestringTipo de mensagem assinada. Hoje: LOAN_UPDATE
webhook_urlstring (HTTPS)URL pública que receberá os eventos. Obrigatoriamente https:// — URLs http:// são rejeitadas
headersobjectOpcional. Headers custom ({ "Chave": "Valor" }) que a IORQ reenviará em cada entrega — camada adicional de autenticação

O fundo é definido pelo header Fund-Id da requisição, não por um campo no corpo.

Exemplo:

curl -X POST 'https://webhook-sender-manager-production.iorq.com.br/webhook' \
  -H 'Authorization: Bearer eyJhbGciOi...' \
  -H 'Fund-Id: 374485cf-f6df-467c-b91d-9f14082c6f36' \
  -H 'Content-Type: application/json' \
  -d '{
    "message_type": "LOAN_UPDATE",
    "webhook_url": "https://api.meudominio.com/iorq-webhooks",
    "headers": { "X-My-Auth": "meu-token" }
  }'

Resposta:

{
  "webhook_id": "...",
  "fund_id": "374485cf-f6df-467c-b91d-9f14082c6f36",
  "user_id": "...",
  "message_type": "LOAN_UPDATE",
  "webhook_url": "https://api.meudominio.com/iorq-webhooks",
  "status": "ACTIVE",
  "headers": { "X-My-Auth": "meu-token" },
  "max_attempts": 7,
  "created_at": "2026-05-13T12:00:00Z",
  "updated_at": "2026-05-13T12:00:00Z",
  "signing_secret": "whsec_K8nP3qR7sT2vW9xY1zA4bC6dE0fG5hJ"
}
🚧

Guarde o signing_secret imediatamente

Ele aparece apenas nesta respostaGET, PATCH e listagem não o retornam. É com ele que você valida a assinatura X-IORQ-Signature de cada entrega. Ver Configuração e segurança.

4. Formato dos eventos recebidos

Cada evento é enviado como POST JSON para a webhook_url, assinado com HMAC-SHA256:

Headers

HeaderDescrição
Content-TypeSempre application/json
X-IORQ-Signaturet=<unix_ts>,v1=<hmac_sha256_hex> — digest sobre "{ts}.{corpo}" com o signing_secret
X-IORQ-TimestampUNIX timestamp do envio (o mesmo t da assinatura)
(custom)Os headers que você registrou em headers, reenviados como cadastrados

Body

{
  "event": "update",
  "data": {
    "entity_id": "OP-001",
    "status": "approved",
    "reason": null,
    "nosso_numero": null,
    "installment_code": null,
    "entity_type": "ccb"
  }
}

O discriminador do que mudou é data.status. Veja o Catálogo de eventos para todos os valores possíveis.

5. Validar a configuração

Use o Fund-Id e o webhook_id retornado para conferir o registro:

curl 'https://webhook-sender-manager-production.iorq.com.br/webhook' \
  -H 'Authorization: Bearer eyJhbGciOi...' \
  -H 'Fund-Id: 374485cf-f6df-467c-b91d-9f14082c6f36'

Para autenticar as entregas no seu endpoint, valide a assinatura HMAC com o signing_secret (comparação em tempo constante):

import hmac, hashlib, time

def verify(payload_bytes, signature_header, secret, tolerance=300):
    parts = dict(p.split("=", 1) for p in signature_header.split(","))
    ts, sig = parts["t"], parts["v1"]
    if abs(time.time() - int(ts)) > tolerance:
        return False
    signed = f"{ts}.{payload_bytes.decode()}"
    expected = hmac.new(secret.encode(), signed.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

Implementação em Node.js e detalhes de replay em Configuração e segurança.

6. Gerenciar webhooks existentes

OperaçãoEndpoint
Listar webhooks do fundoGET /webhook (header Fund-Id)
Detalhe de um webhookGET /webhook/{webhook_id}
Atualizar URL / headers / statusPATCH /webhook/{webhook_id}
Pausar entregaPATCH /webhook/{webhook_id} com {"status":"INACTIVE"}
ReativarPATCH /webhook/{webhook_id} com {"status":"ACTIVE"}
Listar eventos de um webhookGET /events/webhook/{webhook_id}
Reenviar (replay) um eventoPOST /events/{event_id}/replay
Histórico de entregas de um eventoGET /attempts/event/{event_id}

7. Próximos passos