# Idempotency

A network error can hide whether a write ran. Send an `Idempotency-Key`
header with every write, and you can retry it safely.

```http
POST /api/companies/{company_id}/invoices/{invoice_id}/issue HTTP/1.1
Authorization: Bearer osk_live_...
Content-Type: application/json
Idempotency-Key: 5f0c9a1e-6f0b-4c1e-9a52-2b8f0d5b7e41

{}
```

- **Use a new random key for each new change**, for example a UUID. Use the
  same key only to retry the same request.
- The command operations and the file upload accept the header. The
  [API reference](/docs/api) lists it among the parameters of each operation
  that takes it.

## What a repeat gets

| The repeat                                                         | The answer                                                                                |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| The same key and the same body, after the first request finished   | The first response again, with the header `Idempotent-Replayed: true`. Nothing runs twice |
| The same key and the same body, while the first request still runs | 409 `idempotency_in_progress`. Wait and retry                                             |
| The same key with a different body                                 | 409 `idempotency_conflict`. Use a new key for a new request                               |

- The API keeps a key for **24 hours**, for each credential and company.
- Only a success is kept. After an error (a status of 400 or more), you may
  retry with the same key.
- When the first request died before it finished, the key is free again
  after five minutes, and a retry with the same body runs it. The books
  themselves also remember the key, so a command never runs twice.

## Without the header

A write without an `Idempotency-Key` runs every time you send it. A retry
after a timeout can then record the same invoice twice.
