Skip to main content
A network error or a timeout doesn’t tell you whether a request reached sajn. If you retry a POST /api/v1/documents request without protection, you might create the document twice. An idempotency key makes the retry safe: sajn runs the request once, stores the response, and returns the stored response to every retry that uses the same key. To make a request idempotent, send an Idempotency-Key header with a unique value:
  • The header works on every method except GET, such as POST, PUT, PATCH, and DELETE. A GET request ignores it, because reading is already safe to repeat.
  • The key is any string of up to 255 characters. We recommend a UUID that you generate for each operation and store with it, so a retry after a crash reuses the same key. A longer key returns 400 VALIDATION_FAILED.
  • A stored response is kept for 24 hours. After that, the key is free, and a request with it runs again.

Send an idempotent request

The following samples create a contact with an idempotency key:
To retry, send the same request again with the same key. If the first attempt finished, the retry returns its stored status and body, with the following header:
A response without Idempotent-Replayed is from a request that ran.

What a key matches

A key belongs to a workspace, so two API keys or OAuth apps that act in the same workspace share one set of idempotency keys. Generate keys that are unique across all of them, such as UUIDs. sajn compares a retry with the original by its method, its path, and its JSON body. The query string and the other headers aren’t compared.

Which responses are stored

sajn stores the response that the request produced, so a retry gets the same answer even when it’s an error:
  • 2xx responses are stored and replayed.
  • 4xx responses from the request itself, such as 404 NOT_FOUND or 409 ALREADY_EXISTS, are stored and replayed. A retry with the same key and body fails the same way, so fix the request and send it with a new key.
  • 5xx and 429 responses aren’t stored. sajn releases the key, so a retry with the same key runs the request again.
Some errors happen before sajn starts the request, and aren’t stored either: authentication, permission, OAuth scope, rate-limit, and API version errors, and a 400 VALIDATION_FAILED for a body that doesn’t match the endpoint’s schema. You can correct the request and retry with the same key. Every request with a key counts against your rate limits, including a replay. When a retry replays a stored error, the requestId in its body identifies the original request, and the Sajn-Request-Id header identifies the retry. For more information, see Request IDs.

Errors

In API version 2026-09, a reused key returns the code INVALID_REQUEST, and a key in use returns ALREADY_EXISTS. For every other error code, see Errors. For a retry loop that honors Retry-After, see Retry with backoff.