Idempotency
Send an Idempotency-Key header on a request that changes something, and a retry after a network failure cannot do it twice. No public endpoint takes a POST yet; this is how every one will behave.
How it works
- The first request with a key runs, and its status, headers and body are kept for 24 hours under your API key and that idempotency key.
- A retry with the same key and the same body returns the stored response with
Idempotent-Replayed: true. Nothing runs twice. - A retry with the same key and a different body gets
409with codeIDEMPOTENCY_KEY_REUSED. - Only successful (
2xx) responses are kept. A failed request can be retried with the same key.
Pattern
Make one key per operation, before the first attempt, and reuse it for every retry of that operation.
Node
import { randomUUID } from 'node:crypto'
async function postOnce(url: string, body: unknown): Promise<unknown> {
const key = randomUUID()
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TENDRAL_API_KEY}`,
'Idempotency-Key': key,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})
if (res.ok) return res.json()
if (res.status < 500 && res.status !== 429) throw new Error(await res.text())
await new Promise((r) => setTimeout(r, 2 ** attempt * 1000))
}
throw new Error('Gave up after 5 tries')
}