Concepts
Idempotency and errors
Idempotency-Key semantics: replay, conflict. Problem responses: kind, status, code, message, evidence.
Every command carries an Idempotency-Key so a retry is safe. Every refusal is a problem — a small, typed shape you can read and route on.
Idempotency-Key
A canonical UUID, required on every command, never on a query. Send the same key with the same body again and the gateway returns the first acceptance byte-for-byte — a replay, not a second act, marked body.replay.transferRef. Send the same key with a different body and it is a conflict: 400 invalid-Input, “cannot change the request envelope.”
Caution
The key identifies the request, not the outcome. Rotate your API key mid-retry and the idempotency identity changes with it — the retry is a new operation. Keep the key stable across a retry.
Problem responses
Refusals are stated as plainly as capabilities. The shape is always the same:
{ "kind": "...", "status": 403,
"code": "forbidden-PermissionDenied",
"message": "...", "evidence": [] }Route on code, show the message. A gateway error nests under .problem; a refusal from this site's own gate is flat. Every response also echoes a request ref you can quote in a report.
See also
gateway 0.1.0 · sandbox
