# Idempotency — Safely Retry with the Idempotency-Key Header

> Use the Idempotency-Key header to safely retry document uploads, batch processing, and bbox triggers without paying for or executing the same operation twice.

Network calls fail and time out. When that happens to a request that spends credits or creates a resource, retrying it naively can spend those credits twice. The `Idempotency-Key` header solves this: send the same key on a retry, and you get back the exact same response as the original call — without it running again.

## How it works

Add an `Idempotency-Key` header with any client-generated unique string (a UUID is a good choice) to a request that supports it:

```bash
curl -X POST https://imagetotable.ai/api/v1/batches/260716-4K9P/process \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f3e9a2c-9b41-4e6a-8c3d-2f1a5b6c7d8e" \
  -d '{"fields": [{"name": "invoice_number"}, {"name": "total_amount"}]}'
```

The key is stored per `(your account, key value, endpoint)` for **24 hours**. If the exact same request (same endpoint, same key) arrives again within that window, the original response — same status code, same body — is replayed, and the operation itself does not run a second time. That means a `process` call retried with the same key does not deduct credits twice, and a `documents` upload retried with the same key does not create a second document.

Requests without an `Idempotency-Key` header behave exactly as before — nothing is stored, nothing is replayed. The header is entirely opt-in.

## Which endpoints support it

Only endpoints that spend credits or create a resource accept `Idempotency-Key` — there's no benefit to it on a read-only `GET`, since repeating a read is always safe on its own:

- `POST /documents` (document creation)
- `POST /batches/{batch_name}/process` (starts processing, deducts credits)
- `POST /documents/{document_id}/bbox` (triggers the paid bbox annotation step)

## Reusing a key with different parameters

An `Idempotency-Key` is meant for retrying the *exact same* request, not as a general-purpose label. If you reuse a key you've already used, but this time with different request parameters — a different `batch_name`, a different request body — the API does not silently replay the old response (which would be wrong for a different request) and does not guess which one you meant. It returns a 400 `idempotency_key_reused` error instead. Generate a fresh key whenever the request is genuinely different, even if it targets the same kind of operation.

## Example: a replayed response

The second call below, made with the same key as a call that already succeeded, returns the identical body and status code as the first — it does not deduct credits again:

```json
{
  "batch_name": "260716-4K9P",
  "queued": 2,
  "quality": "fast",
  "webhook_registered": false
}
```

## What gets recorded

Only successful (2xx) responses are saved for replay. If the original call failed — a validation error, insufficient credits, anything non-2xx — nothing is recorded, and retrying with the same key simply attempts the operation fresh. This is deliberate: an error is exactly the situation where you want your retry to actually try again, not get the same failure played back until the key expires 24 hours later.

---

Source: https://imagetotable.ai/developers/guides/idempotency
