ARCNM

Building blocks

Idempotency

How to retry safely. Idempotency-Key header, 24h dedup window, large-upload behavior.

Send an Idempotency-Key header on every mutating request and ARCNM dedupes safe retries — a dropped connection or client retry never bills the same calculation twice.

POST /api/v1/parts/calculations/quote
Idempotency-Key: 9c5f0a40-5a8b-4d18-9f4e-c4e1f6d8b6e9

The first request with a given key succeeds normally. A subsequent request with the same key and body within the window replays the original response — without re-running the work, without re-charging.


How it works (requests up to 1 MB)

  1. Client generates a UUIDv4 idempotency key per logical operation.
  2. The server fingerprints (method, path, caller, org, body) and looks it up in a short-lived cache.
  3. Cache hit, completed, same body: we replay the original status code, headers, and body, and add Idempotent-Replayed: true.
  4. Cache hit, in-flight: we return 409 (idempotency_in_flight) so you don't double-create while the original is still processing.
  5. Same key, different body: we return 409 (idempotency_conflict) — the server refuses to overwrite a different operation with the same key. Pick a new key.
  6. Cache miss: we execute, store the response, and write the cache entry with a 24h TTL.

What's in the fingerprint

  • method + path
  • caller — your API key (or user) identity
  • org — your X-Org-Slug / tenant context
  • body — exact bytes, including whitespace

Large uploads (CAD / multipart > 1 MB)

Bodies larger than 1 MB — i.e. CAD uploads to /upload-and-quote — are too big to fingerprint or cache, so they use a lock-only mode:

  • The first request claims a short lock and executes.
  • A concurrent or fast-retry request with the same key gets 409 (idempotency_in_flight) — it does not receive a cached body.
  • On a 4xx the lock is released so you can fix and resend.
  • On success or 5xx the lock is held for a short window (≈60 s); a retry inside that window still gets 409, not a replay.

In other words: for big uploads, idempotency protects you from double-execution, but you won't get the original response replayed — poll GET /parts/calculations/{id} to find the result instead.


Which verbs honour it

Idempotency-Key is honoured on POST, PUT, PATCH, and DELETE whenever the header is present. GET / HEAD ignore it (reads don't mutate). A mutation without a key still works — we just can't dedupe. Send one anyway.


Key format

  • Any string up to a few hundred bytes; UUIDv4 is conventional.
  • Must be globally unique per logical operation. If you generate one key per "shipment of CAD files to ARCNM", every retry of that shipment reuses the same key.
  • Treat it as opaque.

A naming convention that works well with upstream ids:

<system>-<verb>-<external_id>
e.g.  erp-quote-rfq-2026-05-9012

Concurrency

A second request with the same key arriving while the first is still in flight gets:

{
  "error": {
    "code": "idempotency_in_flight",
    "message": "Request with this Idempotency-Key is currently being processed."
  }
}

Wait briefly and retry. Once the first request completes, a same-body retry of a small request replays the original response (with Idempotent-Replayed: true); a large-upload retry returns 409 until the lock expires.


Example

curl -X POST https://api.arcnm.io/api/v1/parts/calculations/quote \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: erp-quote-rfq-2026-05-9012" \
  -d '{ "part_revision_id":"…", "costing_environment_id":"…", "lot_size":50 }'

See also

  • Errorsidempotency_in_flight, idempotency_conflict.
  • Rate limits — pair idempotency with retries.
  • Webhooks — the event id is the dedup key for delivery-side consumers.