Orders API
The Orders API covers the complete lifecycle of an order: listing and searching it, creating it, retrieving it, updating it, transitioning it between states, preparing and shipping it, managing returns and attachments, recovering abandoned carts, and auditing/exporting its history.
This article is the entry point to the domain. Read it before any other article in this section: it defines the response envelope, which governs the shape of absolutely every response in this API.
Base URL and authentication
https://api.fenicia.ioThere is no version prefix (/v1) in the URL. All endpoints in this domain hang off the /orders base path.
Every request requires an API key sent as a Bearer token:
Authorization: Bearer fkapi_your_api_keyTip
Store your API key in an environment variable (FENICIA_API_KEY) and never include it directly in source code.
The response envelope (read this carefully)
Every response from the Orders API follows one of these three shapes. There are no exceptions within this domain except the one explicitly documented in Exception: abandoned carts below.
Success — single resource
{
"data": {
"_id": "65f3a1b2c4d5e6f7a8b9c0d1",
"externalId": "FEN-10042",
"orderStatus": "accepted",
"total": 1986.26,
"_links": {
"prepare": "/orders/65f3a1b2c4d5e6f7a8b9c0d1/prepare",
"cancel": "/orders/65f3a1b2c4d5e6f7a8b9c0d1/cancel"
}
}
}The meta field is optional in single-resource responses (it can carry additional links outside the resource, though _links typically lives inside data, as in the example above).
Success — paginated list
{
"data": [
{ "_id": "65f3a1b2c4d5e6f7a8b9c0d1", "externalId": "FEN-10042", "orderStatus": "accepted" },
{ "_id": "65f3a1b2c4d5e6f7a8b9c0d2", "externalId": "FEN-10043", "orderStatus": "pending" }
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 143,
"totalPages": 8,
"hasMore": true
}
}
}meta.pagination is required on every list response. meta.links is optional and, when present, carries navigation links for the collection itself — don't confuse it with the _links object on each individual resource.
Error
{
"error": {
"code": "orders:not_found",
"message": "Order not found",
"details": {
"field": "orderId",
"value": "65f3a1b2c4d5e6f7a8b9c0d1"
}
}
}The error always comes wrapped in an error object — code/message never appear as top-level properties. code always follows the namespace:snake_case format (e.g. orders:not_found, returns:already_approved). The complete catalog of codes, grouped by namespace, is in the Error Catalog.
The resource is never wrapped under its domain name
You will never see {"order": {...}} or {"orders": [...]}. It is always data, whether singular or plural.
HATEOAS links (_links)
Order and return resources include an _links object inside data with the actions valid for the resource's current state. The possible actions are: accept, reject, cancel, prepare, fulfill, returns. A well-built client doesn't need to hardcode which transition is valid in which state — it simply checks whether the link is present in the response.
Pagination
List endpoints accept page and limit as query params and return meta.pagination with page, limit, total, totalPages, and hasMore. The exact defaults and limits for each endpoint are documented in its own article (see List orders).
Common list filters
Most list endpoints (GET /orders, /orders/search, the count endpoints, /orders/export) share the same filter normalizer. The most commonly used:
| Filter | Description |
|---|---|
orderStatus (alias status) | Individual order status. |
statusGroup | Visual status group — see below. |
channelIds (alias channelId) | One or more channel IDs. |
salesChannel / salesChannels (alias origin / origins) | Sales channel type. |
location | Order's origin location/warehouse. |
startDate / endDate | Date range (ISO). |
paymentStatus | Payment status. |
customerId | Filters by customer. |
q | Free-text search embedded in the list. |
tags, deliveryStatus, hasShipment, fulfillmentMode, deliveryCarrier | Additional shipping/tagging filters. |
metafields | JSON with key-value metadata pairs to filter by. |
extend | Expands additional relations in the response. |
The exhaustive list, with types and examples, lives in List orders.
State machine (summary)
An order moves through a directed state graph — not a simple linear flow. The terminal states (with no outgoing transitions) are cancelled, rejected, and returned; the rest have one or more valid transitions depending on the channel, the fulfillment mode, and whether the order ships in one or multiple parts.
To visually group orders (for example on a board), the API exposes a reduced set of status groups, distinct from the individual states in the transition state machine:
| Group | Use |
|---|---|
pending | Orders not yet accepted. |
preparing | Accepted, in picking/packing. |
completed | Delivered or successfully closed. |
cancelled | Cancelled or rejected. |
problematic | With some delivery exception or incident. |
all | No group filter applied. |
Don't hardcode the transition graph in your application: use _links on each response to know which action is valid at any given moment, and consult State Transitions for the full state machine, including the cancellation reason taxonomy.
Exception: abandoned carts
Different envelope in this one group of endpoints
GET /orders/abandoned-carts and its list variants do not use the standard {data, meta} envelope above. They return a double-nested data object, with pagination inside the same inner object:
{
"data": {
"data": [
{ "id": "cart_8f2a1", "status": "abandoned", "totalValue": 1245.00 }
],
"pagination": {
"page": 1,
"limit": 20,
"total": 34,
"totalPages": 2,
"hasMore": true
}
}
}This is a real API inconsistency (not a documentation error): build for it explicitly in your client if you're going to consume this group of endpoints. The rest of the domain uses the standard envelope documented above.
Additionally, the legacy path /abandoned-carts/* (without the /orders prefix) still works but is deprecated as of 2026-06-01. The canonical, recommended route is /orders/abandoned-carts/*. Full detail in Abandoned Carts.
Quick example
curl https://api.fenicia.io/orders?limit=5 \
-H "Authorization: Bearer $FENICIA_API_KEY"Section map
| Article | Content |
|---|---|
| List orders | Paginated listing with all available filters. |
| Search orders | Free-text search. |
| Get an order | Full detail of an order by ID. |
| Create an order | Manual order creation. |
| Update an order | Modification of editable fields. |
| State transitions | Full state machine: accept, reject, cancel, transition. |
| Fulfillment | Picking, shipping labels, carriers, and tracking. |
| Delivery | Delivery confirmation and evidence. |
| Returns and refunds | Full returns lifecycle. |
| Attachments | File attachments via presigned S3 URLs. |
| Abandoned carts | Abandoned cart recovery. |
| History and export | Auditing and CSV export. |
| Error catalog | All error codes in the domain. |