# Idempotency

> Send an Idempotency-Key so that a retried POST never starts, or charges for, a second job.

Networks fail. A `POST` whose response you did not receive may or may not have started a job —
and a job costs credits. Send an `Idempotency-Key` and a retry becomes safe.

```http
Idempotency-Key: <a UUID you generate once per operation>
```

## Rules

| Rule | Behaviour |
|---|---|
| **scope** | a key is remembered per user and per operation (how long: `GET /v1/meta` `limits.idempotency_key.ttl_seconds`; `null` = as long as its job) (e.g. submitting `image.glam`) |
| **same key, same body** | no new job; you get the original handle again (same `job_id`), with the SAME `X-Refabric-Credits` / `X-Refabric-Credit-Type` the first answer carried. Nothing new is held |
| **same key, different body** | `409 conflict`, `code: idempotency_key_reused`; nothing runs |
| **same key while the first request is still being processed** | `409 conflict`, `code: request_in_progress`, `retryable: true`; retry shortly with the same key |
| **after the retention** | the key is forgotten; reusing it starts a new job |
| **format** | an opaque string; use a UUID v4 |

Idempotency is per **user**: two API keys of the same user share the same key space.

Applies to `POST /v1/tasks/{name}`. `GET`, `PUT …/cancel` and `DELETE` are naturally idempotent
and ignore the header. `POST /v1/files` ignores it too: registering a url is idempotent on the url
itself (the same url answers the same file); a byte upload retried answers a new `file`.

## Recommended use

Generate the key **once per logical operation** and keep it with the operation (for example in
your own job table), not once per HTTP attempt.

```python
import uuid, requests

op_key = str(uuid.uuid4())            # store with your own record
for attempt in range(5):
    try:
        r = session.post(f"{API}/tasks/image.glam", json=body,
                         headers={"Idempotency-Key": op_key}, timeout=60)
        break
    except requests.ConnectionError:
        continue                       # same key → at most one job
```

```bash
curl -s -X POST "$REFABRIC_API/tasks/image.glam" \
  -H "Authorization: Key $REFABRIC_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" -d @body.json
```
