When to send one
- Send an Idempotency-Key on every POST, PUT, PATCH and DELETE. Reads need none: a GET changes nothing.
- Use a fresh value per logical operation, such as a UUID v4 you generate before the first attempt.
- Reuse that same value on every retry of that one operation. A retry after a network timeout, where you never saw a response, is answered with 409 idempotency_in_progress rather than a replay. See below.
- The key is at most 200 characters.
curl -X POST https://api.klasstack.com/v1/mcp \
-H "Authorization: Bearer ks_test_sk_your_key_here" \
-H "Idempotency-Key: 2f8b0f1e-6c1b-4a3f-9d2e-7a5c1b0e4d33" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'How a replay behaves
- The same key with the same body returns the first response again. The write happens once.
- The stored response is the real first response, including its status and its request id, so a replay is safe to treat exactly like the original.
- Keys are scoped to your school and your app. Two apps, or two schools, can use the same key string without colliding.
- The same key with a different body is refused with 422 idempotency_key_reused. That is a bug in the caller, not a replay, and failing loudly beats writing something unintended.
- A retry sent while the first attempt is still in flight, or whose first attempt never recorded an outcome, is answered with 409 idempotency_in_progress. It is not replayed, because the first attempt may already have committed the write and running it again is the double write this header exists to prevent.
- That 409 is permanent for that key. It does not clear with time, so retrying the same key in a loop will never succeed.
- After a 409, read the resource back to find out whether the first attempt landed. If it did, you are done. If it did not, send the operation again under a new key.