Idempotency
Idempotency lets you retry a request (after a timeout or network blip) without it being processed twice. The Public API provides it in three forms, depending on the endpoint.
Usage reporting — idempotency key required
Usage reporting (the Meters endpoint) requires an
x-api-idempotency-key header on every submission. A missing key is rejected
with 400.
Code
- Reuse the same key when retrying the same submission — the duplicate
is acknowledged with
status: "duplicate"instead of being recorded twice. - Keys are valid for at least 30 days. Expired keys are cleaned up shortly after the window ends; once a key is cleaned up, reusing it is treated as a new submission.
- Keys can be up to 255 characters long.
- Use a fresh key for each new submission. A UUID is a good key.
- Keys are scoped per tenant, so two callers can never collide on the same key value.
Endpoints that require the key mark the header parameter as required in the API Reference.
Naturally idempotent endpoints
Some endpoints are idempotent by design through their identifiers rather than
a header — for example, customer provisioning upserts by
customer.customerNumber, so re-sending the same provision request resolves to
the same customer instead of creating a duplicate. The endpoint descriptions in
the API Reference call this out where it applies.
All other mutating endpoints — optional key
Every other mutating Public API endpoint (POST, PUT, PATCH, DELETE)
accepts x-api-idempotency-key as an optional header. Send a fresh key
with each new operation when you want retry protection, and reuse the same key
only when retrying that same operation:
Code
The first successful request runs normally. Retrying with the same key does
not repeat the operation — the replay response carries the original status
code, the header x-idempotent-replay: true, and a minimal body identifying
what was created:
Code
id is the created resource's id, or null when the operation didn't create
a single addressable resource (batch endpoints, action endpoints) — fetch the
full object with a GET if you need it. A replay of a 204 No Content
response returns 204 with the replay header and no body.
Failure states
| Situation | Response | What to do |
|---|---|---|
The original request failed with 4xx/5xx | The key is not burned | Retry with the same key — the operation runs again |
| A duplicate arrives while the original is still in progress | 409 with code IDEMPOTENT_REQUEST_IN_PROGRESS | Wait briefly, then retry with the same key |
| The key was already used on a different endpoint | 422 with code IDEMPOTENCY_KEY_REUSED | Use a fresh key — one key maps to one operation. This includes a usage-report key reused elsewhere |
| The key exceeds 255 characters | 400 with code IDEMPOTENCY_KEY_TOO_LONG | Shorten the key — a UUID is a good key |
Keys are tenant-scoped, retained for at least 30 days, and can be up to 255 characters long — the same window and cap as usage reporting.
Protocol endpoints (OAuth token and revocation, SCIM, MCP, and the portal SSO handoff and session endpoints) manage their own request semantics and don't accept the key. The API Reference shows the header parameter on every endpoint that does.