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

# Idempotency

> Safely retry POST requests without double-charging.

Any `POST` that creates a billable resource (generations, comparisons, uploads, webhooks) accepts an `Idempotency-Key` header. We store the response for 24 hours; the same key within the window replays the original response instead of creating a new resource.

## When to use it

* **Always** for retries on network errors.
* **Always** on POST endpoints that consume credits.
* Pair with exponential backoff for 502/500.

## How to generate keys

A UUID v4 per request is the standard. The key must be ≤ 200 characters and unique per logical operation.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.rimp.example/v1/videos \
    -H "Authorization: Bearer $RIMP_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{ "model": "veo-3-1-fast", "prompt": "...", "duration_s": 4 }'
  ```

  ```ts TypeScript theme={null}
  import { randomUUID } from 'node:crypto';

  await client.generations.createVideo(
    { model: 'veo-3-1-fast', prompt: '...', duration_s: 4 },
    { idempotencyKey: randomUUID() },
  );
  ```

  ```python Python theme={null}
  import uuid

  client.generations.create_video(
      model="veo-3-1-fast",
      prompt="...",
      duration_s=4,
      idempotency_key=str(uuid.uuid4()),
  )
  ```
</CodeGroup>

## Replay behavior

If the same key is reused within 24h with the **same body**, you get the original response back and an `Idempotent-Replayed: true` header:

```http theme={null}
HTTP/1.1 202 Accepted
Idempotent-Replayed: true
X-Request-Id: req_xyz

{ "id": "gen_abc123", "status": "queued", ... }
```

If the body is different but the key is the same, we return `409 idempotency_key_reuse`. This prevents accidentally booking a different generation under the same key.

## What's stored

We snapshot the response body and HTTP status. Headers other than `X-Request-Id` are NOT replayed (so `Set-Cookie` won't leak, for instance).

## Expiration

24 hours from creation. After that, the key is forgotten and a new POST with the same key creates a new generation.

## Anti-patterns

* ❌ Reusing the same UUID across logically different requests.
* ❌ Generating keys from `Date.now()` — collisions.
* ❌ Sending an Idempotency-Key on `GET` (silently ignored).
* ❌ Using the key as a "session" identifier — it's per-request.

## Combined with retry logic

```ts theme={null}
const idempotencyKey = randomUUID();

for (let attempt = 0; attempt < 4; attempt++) {
  try {
    return await client.generations.createVideo(
      { model: 'veo-3-1-fast', prompt: '...', duration_s: 4 },
      { idempotencyKey },
    );
  } catch (err) {
    if (err.status >= 500) {
      await sleep(2 ** attempt * 1000);
      continue;
    }
    throw err;
  }
}
```

The same `idempotencyKey` is used on every retry — so the 4th attempt that finally succeeds doesn't create a 5th generation.
