POST /api/chain/:slug/contracts/:id/transition
Drive a contract from current_state to a new state. Atomic — all of (compute, prove, ZSP wrap, contract row write, audit append, tally mint) succeed or none do.
Auth
Bearer with operator role or higher.
Request
{
"to": "funded",
"input": {
"amount": 1000,
"payer": { "balance": 5000 }
}
}
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | yes | Target state. Must match a transitions[].to whose from is the current state. |
input | object | optional | Scope for the operator + condition evaluator. |
Response — 200
{
"ok": true,
"new_state": "funded",
"previous_state": "pending",
"proof_digest": "7f…64hex",
"zeqond_number": 2287439213,
"tally": {
"tokenId": "uuid",
"remaining": 999
}
}
tally only present when the mint succeeded (mint failure is non-fatal — the transition still completes; the warning is logged).
Errors
| Status | Body | Cause |
|---|---|---|
400 | Missing 'to' state | to not in body |
400 | No transition: X → Y | definition doesn't allow that transition from the current state |
400 | condition_failed | condition evaluated false |
400 | compute_failed/verify_failed/zsp_failed | operator pipeline failed |
403 | forbidden | role < operator |
404 | contract_not_found | id mismatch |
Failed transitions are still recorded in contract_transitions with success: false.
Side effects
- Row inserted in
contract_transitions(success: true|false). - On success:
contracts.current_stateupdated. - On success: row appended to audit entangled state (
audit_log,transition_type: "contract", withproofDigestandzspEnvelope). - On success: tally token minted via
mintToken({...}).