Skip to content

Idempotency ​

Summary: every request that creates or changes something carries an Idempotency-Key header. Send the same key with the same body again and you get the first response back, so a retry after a timeout can never create a second order. Use a new key for each new action.

Which endpoints need a key ​

Needs Idempotency-KeyTakes no key
POST /clinics, PATCH /clinics, PUT /clinics/banking, POST /clinics/banking/authorize, PATCH /clinics/identityEvery GET
POST /orders, PATCH /orders/{id}, POST /orders/{id}/cancelPOST /orders/check (it changes nothing)
POST /tickets, POST /tickets/{id}/messages, POST /tickets/{id}/resolvePOST /uploads, POST /support-sessions

A request to an endpoint that needs a key and has none is refused with 400 idempotency_key_required.

How it works ​

  • The key is any string from 1 to 128 characters after trimming spaces. A UUID per action is the simplest choice.
  • The body is fingerprinted. We hash the exact bytes of the request body. A repeat with the same key and identical bytes replays the stored response, status code included. The same key with different bytes is refused with 409 idempotency_key_reused, because that is a bug in the caller, not a retry. Re-serializing JSON with a different key order or spacing counts as different bytes, so keep the original body for retries.
  • Only successes are stored. A 201 or 200 is remembered and replayed. A refusal (400, 409, 422) is not stored, so after you fix the problem you can resend under the same key and it runs again.
  • Stored responses last 7 days. After that, a repeat no longer replays the stored response. On order create the key is also recorded on the order itself, so a key that created an order can never be used for a different order: that is refused with 409 idempotency_key_reused however old the order is.
  • Keys are scoped to your account, the endpoint and the environment, so a sandbox key and a production key never collide. Edit, cancel, reply and resolve are also scoped to the order or ticket in the path, so one key used on two different orders cannot replay the wrong order's answer.

Order create: two places, one key ​

POST /orders carries the key twice: the Idempotency-Key header and the body's idempotency_key. They must be the same string (surrounding spaces are ignored in the comparison). If they differ, the request is refused with 400 idempotency_key_mismatch and nothing is created, so you can correct it and resend under the same header.

Separately, your partner_order_id must be unique among your live orders. If you lose a create response and retry with a new key, the retry is refused with 409 partner_order_id_duplicate, which carries the existing axiomOrderId. Retrying with the original key returns the original 201 instead, which is why you should keep the key with the order on your side.

Retrying safely ​

You gotDo this
A timeout or network errorRetry with the same key and the same body.
5xx, 429 or 503Retry with the same key after a pause. Honour Retry-After when it is present.
409 order_in_flight or 409 idempotency_key_in_flightAnother request with this key is still running. Retry shortly with the same key. If order_in_flight keeps coming back, the key belongs to an earlier order with this partner_order_id that is failed or cancelled: read that order first (GET /orders/{partnerOrderId}) and follow the failed-order guidance; never resubmit one whose failure.code is pharmacy_outcome_unknown. Only then resubmit, under a new key.
409 idempotency_key_reusedYour code reused a key for a different body. Use a new key for the new action.
400 or 422Fix the request. Resend with the same key (refusals are not stored) or a new one.
200 or 201Done. Store the response.

A good pattern: create the key when the user starts the action, save it with your pending record, and use that saved key for every attempt until you get a final answer.

Errors ​

StatusCodeMeaning
400idempotency_key_requiredThe endpoint needs an Idempotency-Key header.
400idempotency_key_invalidThe key is empty after trimming, or longer than 128 characters.
400idempotency_key_mismatchOrder create only: header and body keys differ.
409idempotency_key_reusedThe key was used before with a different body.
409idempotency_key_in_flightA concurrent request with this key has not finished. Retry shortly. (The order and clinic endpoints add retryable: true; the ticket endpoints do not, so branch on the code.)