# Idempotency and retries

Reuse a logical call identity without assuming its output can be replayed.

An idempotency key identifies one logical model operation. Reuse it when
retrying the same operation, and use a new key for a new operation.
Enlitt recognizes keys for **at least 30 days** after the call that claimed them.
Within that window, a repeated key does not begin a second billed operation.
Afterward, do not depend on whether a key is still recognized.

## Vercel adapter

```ts
import { enlitt, ENLITT_STANDARD_MODEL } from "@enlitt/sdk/vercel";
import { generateText } from "ai";

const idempotencyKey = "ticket-42-summary-attempt";
const result = await generateText({
  model: enlitt(ENLITT_STANDARD_MODEL),
  prompt: "Summarize ticket 42.",
  providerOptions: { enlitt: { idempotencyKey } }
});
```

The supplied key is a base of 16–200 visible ASCII characters. The Vercel
adapter appends the number of prompt items to distinguish underlying model
invocations in a tool loop. Retrying a step with the same base and prompt
item count derives the same identity. Each new step is billed as its own call.

The suffix is a count, not a content hash. Do not reuse the base for a different
prompt just because it has the same number of items. If you omit a key,
the adapter creates a fresh base for each invocation; your application's
separate attempts then have different identities.

## OpenAI and core calls

Pass `enlitt: { idempotencyKey }` in an OpenAI `responses.create()` body.
For `withPremiumCharge()`, pass `idempotencyKey` in its options. These use
the key directly because each invocation represents one model operation.

## Deduplication does not promise output replay

A repeated call can return `operation_in_progress`, a conflict, or
`idempotency_replay_unavailable`. Premium content stays in your application
and provider, so Enlitt cannot replay it. Persist results in your own system
when you need to recover output after a network interruption.

Generate or save the key before your retry loop. Generating a fresh key
inside every attempt defeats deduplication. Avoid concurrent calls with the
same key, and never change a call's pricing or inputs under an already-used identity.
