Skip to content
GreenSnippets

Send requests with an idempotency key

Make POST requests safe to retry by sending a unique Idempotency-Key that the server can de-duplicate.

JavaScript
async function postWithIdempotency(url, body, { retries = 2, fetchImpl = fetch } = {}) {
  const key = crypto.randomUUID(); // one key for all attempts of this operation
  let lastError;
  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      const response = await fetchImpl(url, {
        method: "POST",
        headers: { "Content-Type": "application/json", "Idempotency-Key": key },
        body: JSON.stringify(body),
      });
      if (response.status < 500) return response;
      lastError = new Error(`Server error ${response.status}`);
    } catch (error) {
      lastError = error;
    }
  }
  throw lastError;
}

Example / expected output

Output
await postWithIdempotency("https://api.example.com/charges", { amount: 1000, currency: "usd" });

How it works

If a network error happens after the server processed a payment but before you got the response, a plain retry charges twice. Generate one key per logical operation and reuse the same key on every retry. Servers that support the header (Stripe, many internal APIs) return the original result for repeated keys.