Guide
Idempotency
How retries stay safe on the ORN API: safe reads by design, ledger-level guarantees that exist today, and the Idempotency-Key mechanism for write operations.
Why idempotency matters
Networks fail in the middle of requests. A timeout on a write operation leaves the caller with no answer and one dangerous question: did it happen? Retrying blindly can repeat the effect; not retrying can leave an operation half-done. The ORN API answers this with three layers: reads are safe by design, the money-touching paths are idempotent at the ledger, and write operations accept an Idempotency-Key header that binds a logical operation to exactly one execution.
- Read operations are safe — they observe records and change nothing, so a retry is always harmless.
- Wallet funding is idempotent per payment reference — a retried payment funds the wallet exactly once.
- Webhook capture is idempotent per provider transaction id — a duplicate delivery returns success without a second side effect.
- Write operations carry an idempotency behaviour statement in the API Operations reference — check it for the operation you are calling.
The Idempotency-Key header
Send an Idempotency-Key header with a write call and the platform claims that key for your credential and that operation before any side effect runs. The raw request body is hashed (SHA-256) and bound to the key, so the key is bound to one logical operation — not just any call you happen to send.
curl -X POST "https://www.orangeridesnetwork.org/api/v1/journeys/create_journey" \
-H "Authorization: Bearer orn_test_YOUR_KEY" \
-H "Idempotency-Key: 6d1f0e2a-9c41-4f8e-b7d2-2c8f1a5e3b90" \
-H "content-type: application/json" \
-d '{ "…": "the journey payload" }'Reuse this exact key — and the same body — for every retry of the same logical create.
| Rule | Behaviour |
|---|---|
| Key length | 1–255 characters. Empty or longer keys are rejected with INVALID_REQUEST. |
| Key scope | One key per credential and operation — the same string under a different operation is a different key. |
| Body binding | The SHA-256 hash of the raw request body is stored with the key. |
| Retention | Keys are kept for 24 hours, after which they expire and become claimable again. |
What happens on each call
| Situation | What the API does |
|---|---|
| First use of the key | The request executes once; the response is stored under the key. |
| Retry — same key, same body, first call completed | The stored response is replayed with its original status. The operation does not run a second time. |
| Same key, different body | 409 CONFLICT — the key is bound to the request it first carried. |
| Same key while a request with it is still processing | 409 CONFLICT — wait for the first attempt to resolve, then retry if needed. |
| First attempt failed | The key is reclaimable once, so the retry executes cleanly instead of replaying a failure. |
| Key older than 24 hours | The record has expired; the key is claimable as new. |
Replays return the original response exactly — success or failure that was recorded on completion. Errors are covered in Errors; every response carries x-request-id so retries correlate with support.
Using keys well
- Generate one unique key per logical operation — a UUID is the natural choice.
- Reuse the same key on every retry of that operation, with the same request body.
- Never reuse a key across different payloads — a different body is a 409 CONFLICT by design.
- Treat the key as disposable infrastructure, not as business data — it carries no meaning beyond "this logical operation, this credential, this operation path".
- For the money paths you do not need to do anything: funding and webhook capture are idempotent at the ledger regardless of headers.
Related reading: Webhooks & Events for at-least-once delivery and endpoint deduplication on the event id, and the Idempotency field on every operation in API Operations for the behaviour of the operation you are calling.
Enforcement status
The Idempotency-Key mechanism is enforced for every write operation on /api/v1 in the shared execution layer — not per route. A write call with an Idempotency-Key is claimed before any side effect or charge; a completed key replays its stored response without re-executing or re-billing; a different payload under the same key is a deterministic 409; a failed attempt releases the key for a clean retry. This behaviour is covered by automated enforcement tests and by live runtime verification of the running system.