Skip to content

Idempotency

When a request times out or the connection drops, you cannot tell whether it arrived. Send an Idempotency-Key header with every POST, and you can simply send the same request again: if the first one got through, the retry gets its answer instead of doing the work a second time.

Terminal window
curl https://api.accountcloud.io/v1/address/validate \
-H "Authorization: Bearer $ACCOUNTCLOUD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2e0a-4b7d-4e59-9a51-0c3f8f2d7b14" \
-d '{"address": {"country": "NL", "street": "Hoofdstraat", "house_number": "12", "postal_code": "1234ab", "city": "Amsterdam"}}'

Only to POST:

  • POST /v1/documents (send a document)
  • POST /v1/documents/{id}/feedback
  • POST /v1/ubl/validate
  • POST /v1/address/validate and POST /v1/address/format

On GET and DELETE the header is ignored: repeating those is safe as it is.

  • Any string of 1 to 255 visible ASCII characters, without spaces. Anything else gets 400 invalid_idempotency_key. A UUID works well, and so does your own id for the piece of work, such as inbox-48213.
  • Per account and environment. All live keys of your account share one set of idempotency keys, and all test keys another. A test request never replays a live answer.
  • Kept for 24 hours from the first request with it. After that the key is forgotten, and a request with it runs as a new one.
Situation Answer
The first request with a key Runs as usual. A 2xx answer is stored with the key.
The same key and the same request again, after a 2xx The stored status and body, with Idempotency-Replayed: true. Nothing runs again, and nothing is charged.
The same key with a different request 409 idempotency_key_reused. Nothing runs.
The same key while the first request is still running 409 idempotency_key_in_use, with Retry-After: 1.
The same key after an answer that was not a 2xx Runs again. Only successful answers are stored, so a retry after a refusal or an error gets a fresh try.

A retry counts as the same request when it has the same method, the same path and the same body.

  • The order of the fields in a JSON object does not matter; the order of the items in a list does.
  • With multipart, the form fields count, and each file by its SHA-256: a different file under the same key is a different request.
  • Headers are not compared. If you change a header that matters, such as AccountCloud-Entity, use a new key.

A different request under a used key gets:

{
"type": "https://docs.accountcloud.io/errors/idempotency_key_reused",
"title": "Idempotency key reused",
"status": 409,
"detail": "This Idempotency-Key was already used for a different request.",
"code": "idempotency_key_reused",
"request_id": "req_01m6j19ysmj9hd5hkknyrejfkn"
}
HTTP/1.1 200 OK
Content-Type: application/json
Idempotency-Replayed: true
AccountCloud-Charged: 0.0000
  • The status and the body are those of the first answer.
  • Other headers of the first answer are not repeated, such as the Location of a 202 from POST /v1/documents. Take the id from the body.
  • It is free: AccountCloud-Charged is 0.0000, whatever the first request cost.
  • It still passes the gateway: the key, its scopes and the rate limits are checked as for any request, and a replay counts towards your rate limits.

While the first request with a key has not answered yet, a second one with the same key gets 409 idempotency_key_in_use and Retry-After: 1. Wait a second and send it again: once the first one has finished, you get its answer.

If the first request never finishes, for example because a server stopped halfway, the key is released after 60 seconds, and the next request with it runs again.

  1. Make the key once per piece of work, before the first attempt, and store it with the work. A retry after a crash on your side then still uses the same key.
  2. Retry after a network error or a timeout, after a 5xx, and after a 429 or 503 once the Retry-After has passed. Use a growing pause between attempts.
  3. Wait and retry after 409 idempotency_key_in_use.
  4. Do not retry any other 4xx unchanged: it gets the same answer. A 409 idempotency_key_reused means the key was used for something else, which is a bug on your side.

POST /v1/documents also recognises a file it has seen before, without any key: the same file again returns the earlier document, with duplicate_of, and is not charged again. That works beyond the 24 hours, until the content of the earlier document is deleted. See duplicates and retries.