Skip to main content
folk’s API supports idempotency, so you can safely retry a request that creates, updates or deletes data without running the operation twice. This is useful when a request times out or the connection drops before you receive the response: you cannot tell whether it went through, but you can retry it with the same key.

Sending an idempotency key

Add an Idempotency-Key header to any POST, PATCH, PUT or DELETE request. The key is a value you generate, unique to the operation you want to perform. We recommend a UUID v4.
Keys are 1 to 255 printable ASCII characters, other than space. The header is optional: requests without it behave as usual. It is ignored on GET requests, which never change data.

How retries are handled

The first request with a given key runs normally, and its response is saved, whatever its status code, including errors. Responses larger than 1 MiB are not saved, nor are responses that cannot be saved as JSON text, such as streamed or binary ones. A retry of such a request is rejected with IDEMPOTENCY_RESPONSE_NOT_STORED rather than run again: the operation already ran. Any later request with the same key and the same body returns the saved response, with the same status code and body, without running the operation again. A replay returns the saved response once your API key and workspace membership are checked again, but without checking your access to individual groups again, as the response belongs to an operation you were allowed to run. A replayed response carries an Idempotent-Replayed: true header. Its body is the original one, including the original requestId. Of the original headers, only Content-Type, Deprecation and Sunset are replayed. The others describe the retry: its X-Request-Id header identifies the retry, and its rate limit headers reflect your current usage. Keys are scoped to your user and workspace, and are kept for 24 hours after the request completes. Once a key has expired, a request with that key runs as a new request. While a request is still being processed, its key is held for up to 5 minutes. If its response could not be saved, for instance because of a server failure, the key is freed after that delay and a retry runs the operation again. A key is tied to the request it was first used with: its method, route and path parameters, query parameters, API version and body. The order of keys in the JSON body does not matter, and a request without a body is treated like one with an empty {} body. Reusing a key for a different request returns an IDEMPOTENCY_KEY_REUSED error instead of replaying the earlier response.
Responses to requests rejected before they run are not saved: authentication errors, rate limit errors, and validation errors for an unsupported API version or an invalid body, query or path parameter. You can fix the request and retry it with the same key.

Retrying safely

We recommend the following retry strategy:
  1. Generate a new key for every operation, and keep it with the request until you get a final response.
  2. On a timeout, a network error, a 409 or a 5xx error other than 500, retry the same request with the same key, using exponential backoff.
  3. On a 429, wait for the delay given by the Retry-After header, then retry with the same key. Rate-limited requests never run.
  4. A 500 returned once the operation has started is saved like any other response, so retrying with the same key returns it again. Check whether the operation took effect before sending it again with a new key.
  5. On IDEMPOTENCY_RESPONSE_NOT_STORED, the operation already ran: check its outcome, for instance by listing the records it created, before sending it again with a new key.
  6. To send the same payload again as a new operation, use a new key.

Errors

Invalid key

Status code: 400
Code: IDEMPOTENCY_KEY_INVALID
The Idempotency-Key header is empty, sent more than once, longer than 255 characters, or contains a space or a character outside printable ASCII.

Request in progress

Status code: 409
Code: IDEMPOTENCY_REQUEST_IN_PROGRESS
A request with the same key is still being processed. Retry once it has completed.

Key reused

Status code: 422
Code: IDEMPOTENCY_KEY_REUSED
The key was already used for a different request. Use a new key.

Response not stored

Status code: 422
Code: IDEMPOTENCY_RESPONSE_NOT_STORED
The request with this key already ran, but its response was not kept: it was larger than 1 MiB, or could not be saved as JSON text. Check the outcome of the operation before sending it again with a new key.

Idempotency unavailable

Status code: 503
Code: IDEMPOTENCY_UNAVAILABLE
folk could not claim the key, so the request was not processed rather than processed without protection. Retry with the same key.