01API
Idempotency
A network call can time out after Rollmark did the work. If you send it again, a second order must not appear. Every POST, PATCH, PUT and DELETE takes an Idempotency-Key header: any 1 to 255 printable characters, a UUID is fine.
The rules
- The first request with a key is run, and its answer is kept for 24 hours.
- The same request again (same method, same path, same body) within 24 hours gets the same answer, with
Idempotent-Replay: true. Nothing runs again and nothing is recorded twice. - The same key for a different request (another method, path or body) is
409 idempotency_conflict. A key means one intended action: use a new key for a new action. - Only a success is kept. A refusal (a
4xx) or a failure (5xx) undoes the call and keeps nothing, so a request that was wrong, or arrived before the thing it names existed, can be sent again unchanged once that is fixed. - The key is the store's, not the API key's: if you rotate a key mid-retry, the replay still works.
- The record and the change are written in the same database transaction, so a crash cannot leave one without the other.
- Two requests with the same key at the same moment: the second waits for the first and then gets its answer.
Where it is required
POST /orders/{id}/ship and POST /inventory/batch require the header (400 idempotency_required without it). The first counts as a Rollmark Transfers shipment; the second changes up to 500 items. Everywhere else it is optional and strongly advised.
What to use as the key
Something that names the action in your system, so a retry after a crash uses the same one: your shipment id for a ship, your order id for a create, a run id for a nightly inventory batch. A random UUID per attempt does not protect you from your own crash and restart.
Orders also protect themselves
POST /orders is idempotent on its intake_ref (the store's own id for the order) even without the header: the same body again is 200 with Idempotent-Replay: true, a changed body is 409 intake_conflict. Hand-managed stock is idempotent by external_id: the same id is always the same item.