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

# Idempotency

> Retry safely: the same Idempotency-Key never runs a call twice.

Send an `Idempotency-Key` header (1 to 255 characters, for example a UUID) to make a call safe
to retry. Pramaan remembers the key for 24 hours.

```bash theme={null}
curl https://api.pramaan.dev/v1/capabilities/email.send \
  -H "Authorization: Bearer $PRAMAAN_API_KEY" \
  -H "Idempotency-Key: order-1042-receipt" \
  -H "Content-Type: application/json" \
  -d '{"from": "shop@example.com", "to": "buyer@example.com", "subject": "Your receipt", "text": "Thanks!"}'
```

## When it is required

Capabilities with an external effect (`external_reversible`, `external_irreversible`,
`external_unknown_effect`: sending, posting, paying, deleting) require the header. Calls without
it fail with `400 invalid_request`. For every other capability it is optional.

Each capability's reference page shows its effect class.

## What happens on a repeat

| Situation | Response |
| - | - |
| Same key, same body, first call finished | The stored response, with header `Idempotent-Replayed: true`. No new charge. |
| Same key, first call still running | `409 conflict` with `retryable: true`. Retry shortly. |
| Same key, different body | `409 conflict`. Use a new key for a new request. |
| Same key on an async capability | The same `job_id` again, with `202`. |

A replay returns the stored response exactly, including its [`ref`](https://docs.pramaan.dev/guides/references) when the
call created something.

Use one key per intended action (for example per order and message), and reuse it only to retry
that action.

```ts theme={null}
await p.run("email.send", input, { idempotencyKey: `order-${order.id}-receipt` });
```


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