# Idempotency

> Send an Idempotency-Key on POST requests so a retried request never runs, or bills, a check twice. Behavior, replays and conflicts.

Source: https://fileverity.com/en/docs/idempotency

A network failure can leave you not knowing whether a POST request arrived. If you simply send it again, a check could run and be billed twice. Send an `Idempotency-Key` header and the retry returns the first response instead.

## Using the header

**Idempotent request: cURL**

```bash
curl https://api.fileverity.com/v1/analyses \
  -H "Authorization: Bearer $FILEVERITY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0e5f6a64-52c2-4b36-9d0d-6f3d2f4c9a10" \
  -d '{"model": "fvimg-2", "file": "file_8Hk2pQ4vN9sL1xR7cW3mY6zB"}'
```

**Idempotent request: JavaScript**

```javascript
async function createAnalysis(body) {
  const key = crypto.randomUUID();
  let lastError;
  for (let attempt = 0; attempt < 3; attempt++) {
    try {
      return await fetch("https://api.fileverity.com/v1/analyses", {
        method: "POST",
        headers: { Authorization: "Bearer " + process.env.FILEVERITY_API_KEY, "Content-Type": "application/json", "Idempotency-Key": key },
        body: JSON.stringify(body),
      });
    } catch (error) {
      lastError = error;
    }
  }
  throw lastError;
}
```

**Idempotent request: Python**

```python
import uuid

def create_analysis(body):
    key = str(uuid.uuid4())
    last_error = None
    for attempt in range(3):
        try:
            return requests.post("https://api.fileverity.com/v1/analyses", headers={**headers, "Idempotency-Key": key}, json=body, timeout=90)
        except requests.ConnectionError as error:
            last_error = error
    raise last_error
```

- Send any unique string of 1 to 255 characters. A random UUID is a good choice. Use a new key for each distinct request, and reuse the same key only to retry the same request.
- It works on every POST endpoint: `/text/detections`, `/files`, `/analyses` and `/analyses/{id}/cancel`.
- Keys are scoped to your workspace, the mode (live or test) and the endpoint, and kept for 24 hours. The same key used with a live key and a test key does not collide.

## What you get back

| Situation | Result |
| --- | --- |
| First request with a key | Processed normally. Successful responses (status below 400) are saved. |
| Same key and same body within 24 hours | The saved response with the same status, plus the header `idempotent-replayed: true`. Nothing runs or bills again. |
| Same key, different body | `409` `idempotency_mismatch`. |
| Same key while the first request is still running | `409` `idempotency_in_progress`. Retry shortly. |
| Same key after an error response | The key is released. An error is not saved, so retrying runs the request again. |

A replayed response keeps the `x-request-id` of the new request, not of the original. Multipart uploads are compared by their form fields and file contents.

> **Note.** Idempotency removes duplicate work. It does not make a failed request succeed: after `service_unavailable` or `internal_error`, wait for the `retry-after` seconds if the response has that header, then retry with the same key.

See also [Errors](https://fileverity.com/en/docs/errors.md) and [Rate limits and headers](https://fileverity.com/en/docs/rate-limits.md).

