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

# Idempotency

> Retry POST requests safely with the Idempotency-Key header.

A network error can leave you unsure whether ZeroGen received a request. To
retry a `POST` safely, send an `Idempotency-Key` header with it. ZeroGen runs
the request once for each key and answers a retry with the original outcome, so
a retried create never starts a second generation.

Every `POST` endpoint accepts the header. Without it, each request runs on its
own.

```bash theme={null}
curl https://api.zerogen.com/v1/generations \
  -H "Authorization: Bearer $ZEROGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f0e8b52-1c4d-4f7a-9b2e-6d5c4a3b2f10" \
  -d '{"model": "openai/gpt-image-2/generate", "prompt": "A lighthouse at dawn"}'
```

## Choose a key

A key is 1 to 255 printable ASCII characters. Generate a new random value, such
as a UUID, for each new request, and reuse it only to retry that request.

ZeroGen keeps a key's record for 24 hours. After that, the key can be used for a
new request.

## What a retry returns

ZeroGen fingerprints each request by its method, path, and JSON body. The order
of keys in the body doesn't matter. A retry with the same key and the same
request returns the original outcome, with an `Idempotent-Replayed: true`
header:

* **Creating a generation.** The retry returns the generation's current state,
  not a stored copy, so it can show progress since the first response. If the
  create was refused with a `4xx` error, the retry returns that error.
* **Every other `POST`.** The retry returns the original response.

A replay never starts new work.

## Errors a retry can run again

ZeroGen doesn't store an outcome that a retry could change: a `5xx` error, a
`429`, or any error whose `retryable` is `true`. A retry with the same key runs
the request again. For a create, the retry resumes the generation that the
first attempt reserved instead of starting another, so you can retry a create
until you get a stored outcome.

## Conflicts

| Status | Code | Cause |
| - | - | - |
| `409` | `idempotency_conflict` | The key was already used for a different request: another endpoint, or a different body. Send a new key for a new request. |
| `409` | `idempotency_in_progress` | A request with this key is still running. Retry it shortly. This error is retryable. |
| `400` | `invalid_request` | The key isn't 1 to 255 printable ASCII characters. |

Each error's `param` is `Idempotency-Key`.

## Who shares a key

A key's record belongs to the key's owner, the organization, and the key mode:

* **Your other API keys.** All of your keys of one mode in an organization
  share records, so a retry still matches after you rotate a key. A create that
  hasn't started running yet is the exception: retry it with the API key that
  sent it, or send a new `Idempotency-Key`. A retry from another key returns
  `409 idempotency_conflict`.
* **Live and test keys.** A test key's request never replays into, or blocks, a
  live request with the same key, or the reverse.
* **Other people and organizations.** The same key from another member, or in
  another organization, is a separate record.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.