Static Ads Lab
Reference

Idempotency

Use Idempotency-Key on POST and PATCH to prevent duplicate work on retries.

The Static Ads Lab API supports idempotency for POST and PATCH requests via the Idempotency-Key header. Use it whenever you'd otherwise risk double-charging your wallet on retries.

How it works

  • Send Idempotency-Key: <unique-string> on a POST or PATCH.
  • The first request with that key (per API key) executes normally.
  • Subsequent requests with the same key replay the cached response — no new work, no duplicate wallet charge.
  • Cached responses include the header Idempotent-Replayed: true so you can tell the difference.
  • Keys are scoped per API key. Different keys with the same Idempotency-Key value don't collide.
  • Cache TTL is 24 hours by default (IDEMPOTENCY_TTL_SECONDS). After that, the key is forgotten and a new request will execute.

A UUID v4 is the simplest choice:

import { randomUUID } from "node:crypto";

const idempotencyKey = randomUUID();

await fetch("https://api.staticadslab.com/v1/image-ads", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.SAL_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": idempotencyKey,
  },
  body: JSON.stringify({
    reference_ad_url: "https://cdn.example.com/reference-ad.png",
    brand_id: "brand_...",
    product_id: "prod_...",
    audience_id: "aud_...",
  }),
});

For deterministic flows, derive the key from a stable business identifier:

const idempotencyKey = `generate-ad:${userId}:${campaignId}:${variantIndex}`;

What you should idempotize

  • POST /v1/image-ads — every flat ad costs $1.00, every editable ad costs $4.00. Always idempotize.
  • POST /v1/design-templates — costs $0.25 each. Idempotize.
  • PATCH /v1/image-ads/:id — re-runs the render. Idempotize if you might retry.
  • POST /v1/{resource}/:id/duplicate — costs nothing, but a retry without a key leaves you with two copies to clean up. Idempotize if your client retries on network errors.

You don't need to idempotize read operations or operations on resources that have no side effects (e.g. updating a brand name).

Concurrent requests with the same key

If two requests with the same Idempotency-Key land at the same time:

  • One acquires a 30-second lock and executes.
  • The other returns 409 IDEMPOTENCY_CONFLICT with a message asking you to retry shortly.

Add a brief retry-on-409 to your client.

Pitfalls

  • Reusing a key for a different request body. The cached response is returned regardless of body. Use a fresh key when the request changes.
  • Using a non-unique key per logical operation. A literal "my-key" reused across all requests will replay the first response forever (until TTL).
  • Treating idempotency as a deduplication mechanism for read endpoints — the API only honors it on POST and PATCH.