> For the complete documentation index, see [llms.txt](https://docs.kick.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kick.co/api/idempotency.md).

# Idempotency

Retry a write safely by sending an Idempotency-Key, so a request you never got an answer to never lands twice.

A retried write is only safe if the API can tell it apart from a second, deliberate one. Send an `Idempotency-Key` header and Kick makes that call for you: the first request runs, and once it has finished, a repeat of it inside the next 24 hours gets that same response back instead of writing again.

The header is optional and accepted on every mutating endpoint, meaning `POST`, `PUT`, `PATCH`, and `DELETE`. Read endpoints ignore it.

### Send a key

Generate one key per operation you want to happen exactly once, before the first attempt, and reuse that key on every retry of it. Any string of 1 to 255 characters works, and surrounding whitespace is trimmed before the key is stored.

```bash
curl -i -X POST https://use.kick.co/api/platform/v1/workspaces \
  -H "Authorization: Bearer kick_org_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9f8b0c2e-4d17-4a3e-9a26-1c7f5b0de842" \
  -d '{"name": "Northwind Coffee"}'
```

Keys are scoped to the organization holding the token, so they only have to be unique inside your own integration. Nothing another partner sends can collide with yours.

***

### What a replay returns

A repeat of a request whose original already finished is answered from storage rather than executed again. The status code and body are the ones the first attempt produced, and one extra header marks the response as a replay:

```
HTTP/1.1 201 Created
Idempotent-Replayed: true
X-Trace-Id: 6a59086000000000169b1fa77832f239
```

Read `Idempotent-Replayed: true` as "the work already happened", not as an error. Its absence is just as informative: that attempt is the one that did the writing.

A stored response lives for 24 hours from the first attempt. After that the key is forgotten, and sending it again runs the request as a fresh one, so keep the retries of a single operation inside that window.

{% hint style="info" %}
The header is only set on replays, so it is the one signal that tells a resumed job whether it created something or found it already created.
{% endhint %}

***

### When a retry is not a replay

| Status | Why                                                            | What to do                                                                                                               |
| ------ | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `400`  | The key is empty after trimming, or longer than 255 characters | Fix the key. This is checked before the request runs, so nothing was written                                             |
| `409`  | A request carrying this key is still being processed           | The original is in flight. Wait briefly and resend the same key; once the original finishes, the answer becomes a replay |
| `422`  | The key was already used with a different request              | Two different operations are sharing a key. Send the second one under a key of its own                                   |

Kick compares the method, path, query string, and body of the retry against the original, so anything that changes the request changes what the key stands for, including a field you did not mean to vary. Build the payload once and resend the same bytes.

A rejected request usually frees its key: the claim is dropped and the key is available for a corrected retry. Since a corrected retry is a different request anyway, generate a new key whenever you change the payload rather than reusing the old one.

***

### Retrying safely

* Generate the key before the first attempt, not inside the retry loop. A request that times out before you see an answer has to retry under the original key, and that only works if the key already exists.
* Retry the identical request. A retry that differs in any way is a new operation and needs a new key.
* On `429`, wait the number of seconds in `Retry-After` and resend the same key. Rate limiting is applied before the request is claimed, so a throttled attempt never burns a key.

***

### Next steps

→ [Errors](/api/readme.md#errors)

→ [Rate limits](/api/readme.md#rate-limits)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kick.co/api/idempotency.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
