niiko/developers

The contract

Three outcomes, not two

A two-outcome contract forces the third to disguise itself as another, and the disguised one is always the one that takes longest to understand. Branch once on status.

Last updated

statusHTTPmeaning
done200Done. Carries the output and the idempotencyKey.
pending_approval202Waits for a human signature and may complete hours later. A webhook tells you when it resolves. Do not retry.
refused4xxNot done. reason is one of a closed list, and detail carries what helps: for stale, a message saying what to do.

The shape of a reply

{ "status": "done", "output": { … }, "idempotencyKey": "…" }
{ "status": "pending_approval", "proposalId": "…", "idempotencyKey": "…" }
{ "status": "refused", "reason": "stale", "detail": { "why": "client_ambiguous", "message": "…" }, "idempotencyKey": "…" }

Reads: two outcomes

A read changes nothing, so it never waits for a signature: done (200) with the output, or refused (4xx) with a named reason. It carries no idempotencyKey either.

{ "status": "done", "output": { … } }
{ "status": "refused", "reason": "role_forbidden", "detail": { "message": "…" } }