> For the complete documentation index, see [llms.txt](https://docs.giro.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.giro.tech/desenvolvedores/api-gtfgts/webhooks/retry-e-garantias.md).

# Retry e Garantias de Entrega

A entrega de webhooks do GTFgts é **at-least-once** (pelo menos uma vez), com **retry automático e back-off exponencial**. Esta página descreve a semântica de sucesso/falha por status HTTP, o ciclo de retentativas e as garantias de entrega.

***

## Critérios de sucesso e falha

O desfecho de cada entrega é decidido pelo **status HTTP** que o seu endpoint retorna:

| Resposta HTTP                                          | Comportamento                                                                                                                            |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **2xx**                                                | Entrega confirmada. Qualquer `2xx` (200, 201, 202, 204…) vale como sucesso; **o corpo da resposta é ignorado**. Sem retry.               |
| **4xx**, exceto `408` e `429`                          | Falha permanente — o cliente rejeitou a chamada. **Sem retry**. Causas comuns: header de auth errado (401/403), endpoint removido (410). |
| **3xx / 5xx / `408` / `429` / timeout / erro de rede** | Falha retentável — entrega reagendada com **back-off exponencial**.                                                                      |

{% hint style="warning" %}
Respostas **4xx** (ex.: 400, 401, 403, 404, 410) **cancelam a entrega imediatamente**, sem retry — com duas exceções, `408` e `429`, que são retentadas. Se o seu endpoint está sobrecarregado, responda `429` ou `503`, nunca `400`. Garanta que seu endpoint retorne `2xx` quando a notificação for recebida com sucesso. Erros de validação/auth no seu lado **descartam** o evento.
{% endhint %}

***

## Retry com back-off exponencial

Em caso de falha retentável, a entrega é **retentada com back-off exponencial**: até **4 reentregas**, cerca de **1, 5, 30 e 120 minutos** depois de cada falha — **5 chamadas no total**, contando a primeira. Os horários são aproximados: as reentregas saem em ciclos da plataforma, não no segundo exato.

| Chamada | Quando                      |
| ------- | --------------------------- |
| 1ª      | Assim que o evento é gerado |
| 2ª      | \~1 min após a 1ª falhar    |
| 3ª      | \~5 min após a 2ª falhar    |
| 4ª      | \~30 min após a 3ª falhar   |
| 5ª      | \~120 min após a 4ª falhar  |

***

## Esgotamento de retentativas

Se a 5ª chamada também falhar, a entrega é cancelada e a falha é tratada operacionalmente pela plataforma. O desfecho da operação continua disponível por polling em `GET /api/v1/fgts/operations/{requestId}` — use-o para reconciliar eventos que não chegaram.

```
[entrega] → 2xx ............................. entrega confirmada (sem retry)
          → 4xx (exceto 408/429) ............ falha permanente (sem retry)
          → 3xx/5xx/408/429/timeout → [até 4 reentregas: +1, +5, +30, +120 min] → 2xx (entrega confirmada)
                                                                            → ... → entrega cancelada
```

***

## Garantias de entrega

A entrega é **at-least-once**: diante de falha de rede, timeout ou resposta não-`2xx`, o **mesmo evento pode ser reenviado** e, portanto, **chegar mais de uma vez** ao seu endpoint.

{% hint style="warning" %}
**Não assuma ordem de entrega cronológica estrita.** Em virtude das retentativas e do processamento assíncrono, eventos podem chegar **fora da ordem** em que ocorreram. Não baseie a lógica do seu consumidor na ordem de chegada — decida com base no `eventType` e no **estado atual do recurso** no seu sistema.
{% endhint %}

***

## Idempotência

{% hint style="success" %}
**Recomendado:** implemente idempotência no seu endpoint. Como a entrega é **at-least-once**, o mesmo evento pode ser enviado mais de uma vez. Use o par **(`data.requestId`, `eventType`)** como chave de idempotência para identificar e descartar reentregas. O `requestId` sozinho **não basta**: a mesma operação emite mais de um evento — `CANCEL_RESERVE_UNDER_REVIEW` e depois `CANCEL_RESERVE_FAILED`, por exemplo — e deduplicar só por ele descarta o desfecho final.
{% endhint %}

Exemplos de receptor com deduplicação por `requestId` em [Segurança e Exemplos](/desenvolvedores/api-gtfgts/webhooks/seguranca-e-exemplos.md). Conceito de idempotência ponta a ponta em [Idempotência](/desenvolvedores/api-gtfgts/guias/idempotencia.md).
