Idempotência e reentrega
1. Por que ocorre duplicação
Três cenários produzem duplicação legítima:
- Timeout do seu lado: a IORQ envia o evento, você processa, mas sua resposta
200demora > 10s para chegar. A IORQ assume falha e reenvia. Seu sistema processou duas vezes. - Erro
5xxcom efeito colateral: seu endpoint persistiu o evento mas explodiu antes de responder. A IORQ reenvia, sua persistência grava de novo. - Reenvio manual: você pediu o redelivery via
POST /webhook/event/{event_id}/redeliverpara reconciliar uma divergência.
2. Como deduplicar
Cada evento tem um event_id único (campo do body e header X-IORQ-Event-Id). Use-o como chave de deduplicação:
def handle_webhook(event):
if processed_events.exists(event["event_id"]):
return 200 # já processado, ack e ignora
with database.transaction():
process_event(event)
processed_events.insert(event["event_id"])
return 200Pontos de atenção:
- Tabela de IDs processados com índice único em
event_id— viola constraint = duplicação detectada. - Mesmo transaction-scope entre processar o evento e inserir o ID — sem isso, dá race.
- Retenção mínima de 30 dias — a IORQ pode reenviar dentro dessa janela.
3. Política de retentativa da IORQ
Quando a IORQ não recebe 2xx em até 10s, ela reenvia com backoff exponencial:
| Tentativa | Quando |
|---|---|
| 1 | Imediato (evento original) |
| 2 | + 30 segundos |
| 3 | + 2 minutos |
| 4 | + 10 minutos |
| 5 | + 1 hora |
| 6 | + 4 horas |
| 7 | + 12 horas |
| 8 | + 24 horas |
Após 8 tentativas (~42 horas de janela total), o evento entra em delivery_failed e fica disponível para retentativa manual via GET /webhook/{id}/deliveries.
Não dependa apenas dos webhooksSe seu endpoint fica fora por mais de 42h, eventos podem ser marcados como falha permanente. Implemente reconciliação periódica via
GET /loan/{originator_proposal_code}como salva-vidas.
4. Garantia de ordem
A IORQ garante ordem por originator_proposal_code: você não recebe loan_approved antes de loan_received para a mesma operação. Mas não há ordem global — eventos de operações diferentes podem chegar em qualquer ordem.
Se seu sistema precisa processar em ordem temporal (ex: aging diário), use o campo timestamp do evento, não a hora de recebimento.
5. Reentregas manuais
Você pode forçar a reentrega de um evento específico:
curl -X POST 'https://hs-api.iorq.com.br/webhook/event/evt_9c4a8b2d1e5f/redeliver' \
-H 'Authorization: Bearer YOUR_TOKEN'Ou listar entregas falhas em um intervalo:
curl 'https://hs-api.iorq.com.br/webhook/wh_2A8f1b3c4d5e/deliveries?status=failed&since=2026-05-12T00:00:00Z' \
-H 'Authorization: Bearer YOUR_TOKEN'Útil em casos de outage seu ou para reconciliar após mudança de schema interno.
6. Idempotência em requests da API
O mesmo princípio vale para chamadas de você para a IORQ. Todo endpoint mutador aceita uma chave:
| Endpoint | Chave |
|---|---|
POST /loan | originator_proposal_code |
POST /installment/settle | idempotency_key |
POST /installment/prepayment | idempotency_key |
POST /loan/repurchase | idempotency_key |
PATCH /loan/renegotiate | original_proposal_code |
Reenviar com a mesma chave e payload idêntico retorna o estado atual sem duplicar. Reenviar com a mesma chave e payload conflitante retorna 409.
7. Próximos passos
Updated about 6 hours ago