> ## Documentation Index
> Fetch the complete documentation index at: https://docs.swippee.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Idempotency

> Safely retry billable requests without creating duplicates or double-charging.

Network blips, timeouts, and double-taps happen. To make retries safe, send an
**`Idempotency-Key`** header on the billable, resource-creating `POST` endpoints.
If the same key arrives again, Swippee replays the original response instead of
doing the work twice — so a retry can't create a duplicate report or charge your
quota twice.

```bash theme={null}
curl -X POST https://api.swippee.com/v1/parse \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -F "file=@statement.pdf"
```

Use any unique, hard-to-guess value (a UUID v4 is ideal). Generate it **once per
logical operation** and reuse it across that operation's retries — not per HTTP
attempt.

## Where it applies

| Endpoint                | Why                                                  |
| ----------------------- | ---------------------------------------------------- |
| `POST /v1/parse`        | Each call creates a report and consumes parse quota. |
| `POST /v1/verify/issue` | Each call mints a new verification token.            |

Other write endpoints (e.g. `POST /v1/decisions`) are already idempotent by a
natural key, so a key is optional there. `GET` requests never need one.

## Behaviour

* **First request** — processed normally; the response is cached against your key.
* **Retry (same key, same params)** — the original response is replayed verbatim,
  with an `Idempotent-Replayed: true` header. No new report, no extra charge.
* **Still in flight** — if a retry arrives while the first is still processing,
  you get `409 IDEMPOTENCY_IN_PROGRESS`. Wait a moment and retry the same key.
* **Key reused with different params** — `422 IDEMPOTENCY_KEY_REUSED`. A given key
  is bound to its first request body; use a fresh key for a new request.
* **Server error (5xx)** — the key is released so your retry can reprocess. Only
  deterministic responses (success and client errors) are cached.

## Scope & lifetime

* Keys are scoped to **your organization** and **environment** (`live` vs `test`
  keys never collide).
* Cached responses expire after **24 hours** — retries beyond that window are
  treated as new requests.
* Keys must be **8–255 characters**.
