Skip to Content
Developer APIAPI GuidesIdempotency & Concurrency

Idempotency & Concurrency


Idempotency

Create-style endpoints accept an optional Idempotency-Key header. If you retry a request with the same key and the original request succeeded, the server returns the original response without executing the operation again.

curl -X POST https://api.eunifyer.com/api/v1/partner/orgs \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: unique-request-id-abc123" \ -d '{ "name": "Acme Corp", "plan_id": "…" }'

A replayed response includes X-Idempotency-Replayed: true.

Rules

  • Generate a fresh Idempotency-Key for each logical operation — do not reuse keys.
  • Keys are scoped to your organization and cached for 24 hours.
  • If you send the same key with a different body, the server returns 409 Conflict.
  • If the original request was still in-flight when you retry, you may receive a 503 — back off and retry.
  • If the original request failed with a 4xx, the error is not cached — you can retry with the same key and corrected body.

Generating keys

const idempotencyKey = crypto.randomUUID();
import uuid idempotency_key = str(uuid.uuid4())

Which endpoints support idempotency

EndpointIdempotency supported
POST /partner/orgsYes
POST /partner/orgs/{id}/usersYes
POST /partner/orgs/{id}/teamsYes
POST /developer/service-principalsYes
POST /developer/service-principals/{id}/tokensYes
POST /drive/uploadYes
POST /webhooks/subscriptionsYes

Optimistic concurrency (ETag / If-Match)

Mutable resources that are edited concurrently carry an ETag response header. Use If-Match on write requests to prevent overwriting another client’s changes.

Reading the ETag

curl -I https://api.eunifyer.com/api/v1/sites/my-site-id/pages/my-page-id \ -H "Authorization: Bearer $TOKEN" # Response headers include: # ETag: "abc123def456"

Writing with If-Match

curl -X PATCH https://api.eunifyer.com/api/v1/sites/my-site-id/pages/my-page-id \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "If-Match: \"abc123def456\"" \ -d '{ "content": "# Updated content\n\nNew paragraph." }'

If the resource was modified by someone else since you read it, the server returns:

{ "type": "https://problems.eunifyer.com/precondition_failed", "title": "Precondition Failed", "status": 412, "detail": "Resource was modified since your last read. Fetch the current version and retry.", "code": "precondition_failed" }

Re-fetch the resource, merge your changes, and retry with the new ETag.

Which resources support ETag

ResourceETag support
Sites pages (GET/PATCH /sites/{id}/pages/{id})Yes
CardDAV contactsYes

Example — safe page update

import httpx client = httpx.Client( base_url="https://api.eunifyer.com/api/v1", headers={"Authorization": f"Bearer {token}"}, ) # 1. Read current version resp = client.get(f"/sites/{site_id}/pages/{page_id}") resp.raise_for_status() etag = resp.headers["etag"] page = resp.json() # 2. Make changes locally page["content"] = "# Updated\n\nNew content here." # 3. Write with If-Match update = client.patch( f"/sites/{site_id}/pages/{page_id}", json={"content": page["content"]}, headers={"If-Match": etag}, ) if update.status_code == 412: # Conflict — re-fetch and retry ... update.raise_for_status()

Summary

ConcernMechanismHeader
Safe retries on createIdempotencyIdempotency-Key (request)
Detect replayed responseIdempotencyX-Idempotency-Replayed: true (response)
Prevent lost updates on editsOptimistic concurrencyETag (response) + If-Match (request)
Stale If-Match412 errorRe-fetch + retry