SurfacedBySurfacedBy Docs
DocumentationReference

Idempotency

How the required Idempotency-Key header makes write requests safe to retry.

Ask an AI:Open in ChatGPTOpen in Claude

Every write request to the Data API (POST and DELETE) must carry an Idempotency-Key header. If a network error leaves you unsure whether a write went through, resend it with the same key and body: you get the original response back instead of a second write.

curl -X POST https://api.surfacedby.com/api/v1/ext/domains \
  -H "X-API-Key: sk_live_..." \
  -H "Idempotency-Key: 9f8e2b1a-0c4d-4a7e-8b3f-5d1e2a3c6d7f" \
  -H "Content-Type: application/json" \
  -d '{"domain": "yourbrand.com"}'

Generate a fresh UUID for each logical operation. A write without the header is rejected with 400 idempotency_required. GET requests ignore the header.

Scope

A key is scoped to the API key that sent it, the request path, and the HTTP method. The same idempotency key can be used by different API keys, or on a different path or method, without conflict. Within that scope, SurfacedBy compares a hash of the exact request body bytes, so resend the body byte for byte.

Replay

When a request with the same key and the same body has already succeeded, SurfacedBy returns the stored response: the original status code, body, and headers, plus X-Idempotent-Replay: true. Stored responses are kept for at least 24 hours, after which the key can be used for a new operation.

Only successful responses are stored. A request that fails, for example with a validation error, a limit, or a permission error, releases its key: resending with the same key, with the same body or a corrected one, is processed as a new request.

Conflicts

  • 409 idempotency_in_progress - the original request with this key is still running. The response carries Retry-After: 5; retry after that, and you get the stored response once the original succeeds, or a fresh attempt if it failed. A key whose original request never finished becomes usable again within about an hour.
  • 409 idempotency_conflict - the key was already used on this path with a different body, and that request succeeded or is still running. Use a new key.

See Errors for the full error catalogue.

On this page