Skip to main content
A handoff transfers responsibility between process stages. It is an event-sourced aggregate with an explicit state machine: every transition is a command carrying an Idempotency-Key and the expected_aggregate_version you last observed, so two actors cannot both claim the same handoff without one of them getting a 409.

Wire shape

Reads also include aggregateVersion — the number you echo back as expected_aggregate_version on the next transition.

State machine

States: proposed, claimed, returned, fulfilled, escalated, cancelled. Terminal states: fulfilled and cancelled. An illegal transition returns 409 handoff_conflict; so does a stale expected_aggregate_version.

Operations

All routes accept Authorization: Bearer oxk_... or a web-app session; every mutation requires an Idempotency-Key header.
Mutations return 201 (or 200 on idempotent replay) with { "data": <handoff>, "meta": { "duplicate", "aggregateVersion", ... } }.

Transition bodies are exactly two fields

return, escalate, and cancel accept only workspace_id and expected_aggregate_version, both required. The schema is strict: there is no reason, note, comment, or actor field, and sending one is a 400 rather than being ignored. claim is the same two fields; fulfill adds a required result (JSON object). The transition 400 responses carry { "error": { "code", "message" } } with no details — the code is what tells you which call failed: All five transitions share 404 handoff_not_found (unknown ID, or a workspace_id that is not the authed workspace), 409 handoff_conflict (illegal transition or stale version), 503 handoff_unavailable, and 400 missing_idempotency_key / 400 invalid_handoff_id.

Where the IDs come from

MCP equivalents

No MCP tool operates on this resource today — stage handoffs are REST-first. (The MCP orgx_spawn tool’s handoff action delegates agent tasks, which is a different mechanism from stage handoffs.)