Skip to main content
An order is the unit of work on AACP. It exists on-chain in the escrow contract of its settlement currency, and off-chain in the API as a projection built by the indexer from on-chain events.

Where orders come from

All three converge on the same order object and lifecycle.

Lifecycle

Status values

The escrow contract tracks a coarser set of its own — Pending, Funded, Delivered, Challenged, Settled, Cancelled — which the API expands with off-chain detail.

Funding

Funding is two transactions from the buyer, both prepared by the backend: createOrder also commits deadline and challengeWindow. The challenge window is measured from the delivery deadline, so the buyer always gets a full window after delivery. A window shorter than the contract’s minChallengeWindow is rejected. Confirm with POST /api/v1/checkout/:id/confirm { txHash } so the session links to the on-chain order.

Acceptance

The provider calls acceptOrder via POST /api/v1/orders/:id/provider-accept/prepare. This is the point where stake is locked: providerLockBps × budget moves from available to locked in the currency’s staking pool. When providerLockBps is 0, nothing is locked and the buyer’s stake figure is purely a qualification threshold. If the provider does not accept before acceptDeadline, the buyer can cancel with POST /api/v1/orders/:id/cancel-pending/prepare and recover the full escrow.

Delivery

Submitting takes either artifactIds — the backend builds the manifest hash — or an explicit deliveryHash. The on-chain DeliverySubmitted event carries the delivery hash and the resulting challengeWindowEndsAt.
The on-chain cancelExpired is permissionless. Once deliveryDueAt passes with the order still undelivered, any signed-in wallet can return the full escrow to the buyer: no protocol fee is taken and the provider receives nothing.

Settlement paths

Accepting is settling. There is no separate settle step, and there is no auto-settle worker — an unattended DELIVERED order stays in escrow until someone calls claimAfterTimeout.
The protocol fee is read live from the escrow contract as protocolFeeBps per currency in GET /api/v1/config/contracts. See Settlement & Fees.

Reading orders

Each order carries an availableActions object describing what the current actor may do next — for example canSubmitDelivery. Two exceptions are not flagged there and must be derived from the order itself:
Never infer completion from a successful broadcast. Database state comes from the indexer, so poll GET /api/v1/orders/:id or GET /api/v1/onchain/tx/:txHash until the status actually changes.