# Idempotency

Using the API

Retry any POST safely with an Idempotency-Key: the same key and body never repeat the work, and a replay shows the current state.

A request whose answer never arrives may or may not have run. To make a `POST` safe to send again, give it an `idempotency-key` header and retry with the same key: the work is done once, however many attempts it takes. Reads need no key: retry them with `max_age` set to the seconds since the first attempt, and the retry is served free from the cache.

## How it works

- Every `POST` accepts the header. Use a new random value for each new request (a UUID is ideal), up to 255 printable ASCII characters, and reuse it only to retry that same request.
- Keys belong to your account and to one route, and are kept 1 day (15 minutes for an answer that shows a secret). After that, a retry doesn't run again: it answers [`idempotency_key_reused`](https://socialtap.dev/docs/errors/index.md#idempotency_key_reused) with `details.reason` `answer_expired`. The request ran, so check what it did before you send it again under a new key.
- The first request with a key runs normally. Once it has succeeded, a retry with the same key and the same body doesn't run again: it answers with the first request's status and the resource's **current** state (a job created then is shown as it is now), with the header `idempotent-replayed: true`. Routes that show a secret once (a new key or webhook endpoint, a rotated secret) answer exactly what they answered the first time. A key's previous secret, after a rotation, never gets such an answer back: [`idempotency_key_reused`](https://socialtap.dev/docs/errors/index.md#idempotency_key_reused).
- The body is compared after parsing, so key order and whitespace don't matter.

| Situation | Answer |
| --- | --- |
| The same key with another body, or on another route | [`idempotency_key_reused`](https://socialtap.dev/docs/errors/index.md#idempotency_key_reused) (422): send a new key |
| The same key while its first request is still running | [`idempotency_key_in_progress`](https://socialtap.dev/docs/errors/index.md#idempotency_key_in_progress) (409): retry after the `retry-after` seconds (after 2 minutes a retry resumes it) |
| A key whose first request was refused or failed | Nothing is kept: retry with the same key once the request is fixed |
| A key whose first request could not confirm what it did ([`internal`](https://socialtap.dev/docs/errors/index.md#internal) says so) | Retry it: you get what it created, never a second one |

With the TypeScript SDK, every `POST` carries a key, reused for its automatic retries. Over plain HTTP, send a new key with every `POST` and reuse it, with the same body, whenever you retry that request.

---

[HTML version](https://socialtap.dev/docs/idempotency/) · [Docs index for AI agents](https://socialtap.dev/llms.txt) · [All docs in one file](https://socialtap.dev/llms-full.txt)
