Skip to main content
An app works orders the way a team member does: it reads them, creates orders from its own channel, fixes the buyer’s details, confirms, cancels with a reason, schedules a call back and leaves comments. Every write runs the same checks as the dashboard button that does the same thing, and the dashboard shows your app’s name on it (“Review Requests confirmed order #1042”). Dispatching to a carrier, labels and returns are not in API version 2026-10.

The order

  • State: status is the pipeline status, built in (pending, confirmed, scheduled, canceled, …) or one the merchant named: treat it as an open string. The flags dispatched, delivered, returned, archived and waiting say the rest. A returned order keeps its status (usually pending): read returned.
  • Money: total, shippingPrice, and each line’s unitPrice and totalPrice are decimal strings in currency.
  • Buyer: provinceCode (the wilaya, 1 to 58) and townOns (the commune) always; name, phone, phone2, email, address, address2, and the order’s note and deliveryNote, only with read_customer_contact.
  • Delivery: method (home or stopdesk), speed, the delivery agent, the tracking number and carrierStatus, the carrier’s own wording.
  • Lines: items[]; a pack’s component lines carry packParentItemId.
  • Where it came from: source (shopify:<domain>, app:<handle> for an order an app created, null for the storefront and the dashboard), landingPageId, utm { source, medium, campaign, content }.
  • Other: exchangeOfOrderId, cancellation { reasonId, reasonLabel, source }, and the times scheduledFor, confirmedAt, dispatchedAt, deliveredAt, returnedAt, canceledAt, createdAt, updatedAt.
Waiting orders. An order past the plan’s order allowance is created 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:
Between syncs, the 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 source is app:<your handle>, and orders/created is 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.
Answers: 201 for a new order (or a recovered checkout), 200 for an existing one. With an Idempotency-Key, a retry replays the stored answer and its status.

Edit, confirm, cancel, schedule

  • PATCH changes buyer (only the keys you send), delivery (method, speed), note and deliveryNote (null clears 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 409 ORDER_NOT_EDITABLE. It sends orders/updated.
  • confirm (no body) checks the buyer’s details for a carrier: a missing phone, wilaya or commune is a 400 naming missingFields. An empty address is filled from the commune. Sends orders/confirmed. Refusals: 403 ORDER_LIMIT_REACHED (a waiting order), 409 ORDER_STATUS_CONFLICT (its status does not allow it, already confirmed included).
  • cancel takes an optional reasonId (from GET /cancel-reasons) and note (up to 500). An archived or unknown reason is 400 CANCEL_REASON_INVALID; a reason that requires a note, without one, 400 CANCEL_NOTE_REQUIRED. Sends orders/cancelled.
  • schedule takes scheduledFor, in the future: the status becomes scheduled. An order already scheduled is 409 ORDER_STATUS_CONFLICT. Sends orders/updated.
Every answer is the order, read again (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.