Dispatching to a carrier, labels and returns are not in API version
2026-10.
The order
- State:
statusis the pipeline status, built in (pending,confirmed,scheduled,canceled, …) or one the merchant named: treat it as an open string. The flagsdispatched,delivered,returned,archivedandwaitingsay the rest. A returned order keeps its status (usuallypending): readreturned. - Money:
total,shippingPrice, and each line’sunitPriceandtotalPriceare decimal strings incurrency. - Buyer:
provinceCode(the wilaya, 1 to 58) andtownOns(the commune) always;name,phone,phone2,email,address,address2, and the order’snoteanddeliveryNote, only withread_customer_contact. - Delivery:
method(homeorstopdesk),speed, the delivery agent, the tracking number andcarrierStatus, the carrier’s own wording. - Lines:
items[]; a pack’s component lines carrypackParentItemId. - Where it came from:
source(shopify:<domain>,app:<handle>for an order an app created,nullfor the storefront and the dashboard),landingPageId,utm { source, medium, campaign, content }. - Other:
exchangeOfOrderId,cancellation { reasonId, reasonLabel, source }, and the timesscheduledFor,confirmedAt,dispatchedAt,deliveredAt,returnedAt,canceledAt,createdAt,updatedAt.
waiting: true and masked whatever your scopes (phones **********, notes
null) until it unlocks, which sends orders/updated with waiting. You may
read, edit, cancel, schedule and comment on it; confirming it is 403
ORDER_LIMIT_REACHED.
Which orders you can reach
GET /orders lists every order of the business your token may read: every
stage, archived ones included, newest first. Not listed: abandoned checkouts
still waiting for the merchant (they are abandoned_checkouts/created, and
become orders when recovered) and the collected-goods rows Tassyir keeps
for an exchange. Orders of stores outside your installation’s are left out.
Every route that names an order reads it that way first: any other id is
404 NOT_FOUND, before anything is written. With an online token whose
person may see only the orders assigned to them, you reach only those.
List and sync
Filters only narrow, and the cursor is bound to them. The list stays ordered
by creation, so to sync walk every page and keep the largest
updatedAt
you saw, then start the next sync from it:
orders/* webhooks tell you what changed
(Webhooks).
Create an order
Anything else is refused, on purpose: an order is created
pending (confirm
it with the route below), priced from the catalogue and the business’s
delivery prices, never from your numbers, and carries no carrier, tracking,
payment or attribution of your choosing.
What happens is what happens to an order a merchant types in the dashboard:
- The duplicate rule. A second order for the same phone and the same
items, within 24 hours and not yet dispatched, is folded into the first:
200 with that order, nothing created. If you cannot read that order,
409
ORDER_DUPLICATE. - An abandoned checkout becomes the order. When the buyer (same phone) left a checkout sharing a product, the order takes the checkout’s id.
- The business’s distribution assigns it to a team member, once.
- The plan’s allowance admits it: past it, the order is created
waiting, and your answer is masked. - Its
sourceisapp:<your handle>, andorders/createdis sent once. - The storefront’s anti-spam checks do not apply: your app is an authenticated member of the business, not a buyer’s browser.
Idempotency-Key, a retry replays the stored answer
and its status.
Edit, confirm, cancel, schedule
PATCHchangesbuyer(only the keys you send),delivery(method,speed),noteanddeliveryNote(nullclears one). Not the status, the store or the items. A new commune, method or speed re-prices the delivery. A dispatched, delivered or returned order is 409ORDER_NOT_EDITABLE. It sendsorders/updated.confirm(no body) checks the buyer’s details for a carrier: a missing phone, wilaya or commune is a 400 namingmissingFields. An empty address is filled from the commune. Sendsorders/confirmed. Refusals: 403ORDER_LIMIT_REACHED(a waiting order), 409ORDER_STATUS_CONFLICT(its status does not allow it, already confirmed included).canceltakes an optionalreasonId(fromGET /cancel-reasons) andnote(up to 500). An archived or unknown reason is 400CANCEL_REASON_INVALID; a reason that requires a note, without one, 400CANCEL_NOTE_REQUIRED. Sendsorders/cancelled.scheduletakesscheduledFor, in the future: the status becomesscheduled. An order already scheduled is 409ORDER_STATUS_CONFLICT. Sendsorders/updated.
fields trims it).
Comments
GET /orders/{id}/comments lists the team’s notes on the order, newest
first; POST adds one from your app ({ "body": "…" }, 1 to 1,000
characters).
byThisApp marks your own comments; who else wrote one is not said. The team
often types phone numbers into comments, so another author’s body follows
the notes rule: present only with read_customer_contact, and null while
the order is waiting. Your own comments always carry their body. Comments
send no webhook.
Attribution
Every write is recorded in the activity log under your app’s name, whatever the token kind. An app’s write never counts as a team member working the order, and earns no commission.Errors these routes add
See Errors for the codes every route shares.