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)
- Client generates a UUIDv4 idempotency key per logical operation.
- The server fingerprints
(method, path, caller, org, body)and looks it up in a short-lived cache. - Cache hit, completed, same body: we replay the original status
code, headers, and body, and add
Idempotent-Replayed: true. - Cache hit, in-flight: we return
409(idempotency_in_flight) so you don't double-create while the original is still processing. - 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. - Cache miss: we execute, store the response, and write the cache entry with a 24h TTL.
What's in the fingerprint
method+pathcaller— your API key (or user) identityorg— yourX-Org-Slug/ tenant contextbody— 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
4xxthe lock is released so you can fix and resend. - On success or
5xxthe lock is held for a short window (≈60 s); a retry inside that window still gets409, 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
- Errors —
idempotency_in_flight,idempotency_conflict. - Rate limits — pair idempotency with retries.
- Webhooks — the event
idis the dedup key for delivery-side consumers.