Skip to content

Idempotency

Preview Networks drop responses, CI runners retry, Terraform re-applies. An idempotency key makes those retries safe: send the same key with the same request and managed.dev returns the original result — the job or resource you already created — instead of creating a second one.

Send an Idempotency-Key header on any POST that creates a resource or kicks off a job. The value is a unique string you choose — a UUID is the natural choice:

A creating POST, made retry-safe
POST /v1/sites/site_01J7…/environments/env_01J8…/components HTTP/1.1
Host: api.managed.dev
Authorization: Bearer mfk_live_…
Forge-Version: 2026-06-23
Idempotency-Key: 6f1c2e9a-4b7d-4f0a-9c11-2a8e5d3b1f04
Content-Type: application/json
{ "kind": "plugin", "slug": "wordpress-seo", "version": "latest", "activate": true }

The platform stores the key and the result it produced for 24 hours. Inside that window, a replay returns the original response verbatim. After it expires, the same key is a fresh request again.

This is the rule that makes retries safe: a replay echoes the original outcome — it does not re-run the work.

  • First request with key 6f1c… → the plugin-install job is created and returned (202 Accepted).
  • Any retry with the same key 6f1c… within 24h → the same job_01J9… is returned, with its current status. The install is not started a second time.
  • This holds even if the original job has since failed. You get the original, failed job back — not a fresh attempt. To genuinely retry the operation, issue a new request with a new key.

Automated callers retry aggressively, and a retry that double-creates is a real hazard: two preview environments, a plugin installed twice, a duplicated deployment.

  • CI pipelines retry on transient network failures. Generate one key per logical step so a retried step reconciles against the first attempt instead of stacking a second.
  • The official Terraform provider sends an idempotency key per planned action, so an interrupted apply resumes cleanly — the re-apply finds the original job rather than provisioning a duplicate.
Situation Retry safely?
Any request, with the same Idempotency-Key, within 24h Yes — you get the original result back.
A GET (or any read) Yes — reads have no side effects, key or not.
A POST without a key No — there’s nothing to deduplicate against; you may create twice.
The same key after 24h No — the record has expired; it’s treated as new.
The same key with a changed body No — that’s a conflict, not a retry. Use a new key.

The takeaway: put an Idempotency-Key on every creating POST, even the ones you don’t expect to retry. It costs nothing on the happy path and turns an ambiguous network failure into a safe, deterministic replay.

Create a preview environment — safe to retry
curl -X POST https://api.managed.dev/v1/sites/site_01J7…/environments \
-H "Authorization: Bearer mfk_live_…" \
-H "Forge-Version: 2026-06-23" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "branch": "feature/checkout", "type": "preview" }'

The first call returns 202 Accepted with a job; any replay inside 24h returns that same job. Tail it to completion as described in async jobs.