Fenicia models an order's lifecycle as a finite state machine: from a given state, only a specific set of destination states are valid. This article documents the complete machine (23 states) and all the endpoints that operate it.
Which endpoint should I use?
Use accept, reject, and cancel for the merchant's common actions — they're optimized for their use case and validate specific business rules (for example, the cancellation reason catalog). Use the generic transition endpoint when you need to move the order to any valid state in the machine that doesn't have a dedicated action.
23 states. Each row indicates the states you can transition to from the current state; any other destination is rejected with orders:invalid_transition.
When you retrieve an order, its _links object includes only the actions valid for its current state. The possible actions are: accept, reject, cancel, prepare, fulfill, returns. If an action doesn't appear in _links, it isn't valid for the order's current state.
The handler doesn't read any field from the request body — send {} or simply omit the body. If the order belongs to a channel that requires confirming the acceptance in the marketplace before accepting locally (today: Walmart), the acceptance is propagated automatically; you don't need to send anything for that.
Required permission:orders:update
curl -X POST https://api.fenicia.io/orders/65f3a1b2c4d5e6f7a8b9c0d1/accept \ -H "Authorization: Bearer fkapi_your_api_key"
reject uses the same catalog of 12 canonical reasons as cancel (see the table in the "Cancel an order" section below) and the same rule: note is required when reason is other. Unlike cancel (which accepts extra fields without rejecting them), reject's validator is strict: sending any field other than reason, motive, note, or requestedBy is rejected.
Sets the order's status without going through a named action. Useful when integrating a flow that already knows the exact destination state.
Directly sets an order's status. Requires orders:update permission.
orderIdstringrequired
Order ID.
statusstringrequired
Target status.
{ "status": "preparing"}
204No body
(no content)
Required permission:orders:update
204 No Content — no body
Unlike accept/reject/cancel/transition, this endpoint responds with 204 No Content: it doesn't validate the transition against the state machine (don't confuse it with transition, which does validate) and it doesn't return the updated order. If you need the resulting order, do a GET /orders/{orderId} afterward.
This endpoint's transport schema only requires toStatus. reason isn't required unless the specific transition demands it (for example, transitioning to cancelled or rejected from certain states) — in that case, omitting it returns validation:invalid_input.
The response does NOT carry _links, and the order is nested under order
Unlike accept/reject/cancel (which return { data: { ...order, _links } }), this endpoint returns { data: { order, previousStatus, newStatus, hooks } } — the complete order lives under the order key, without _links, alongside the previous/new status and the list of hooks that fired (e.g. inventory adjustments).
orderIds must have at least one element — an empty array rejects the entire call with validation:invalid_input; there's no partial result in that case. With at least one element, each order is processed individually: one can fail (invalid transition, not found) without aborting the rest — check results[] for the per-order detail.
This endpoint saves you from having to reimplement the state machine table in your client: it returns directly the set of valid states for the queried order. It's documented in detail in Get an order, along with the rest of the resource's HATEOAS links.