Commerce
Export orders
Download Sela orders as CSV, Excel or JSON for any dates, or sync them automatically, to bring them into your POS, ERP or accounting system.
Last updated: 2026-10-05
Your business already runs a POS, an ERP or an accounting system. Sela takes orders from WhatsApp, Instagram, Messenger, Telegram, your website, your storefront and phone calls, and Export moves those orders into your own system without a custom integration.
Every export uses one order structure, sela.order.v1, described at the end of this page. The same structure is in the downloads, the REST API and the order webhooks, so you map it once.
| You want to | Use |
|---|---|
| Hand today's or this month's sales to your accountant | Excel workbook download |
| Import the orders into a POS, ERP or accounting system | Order items (CSV) download |
| Keep another system updated automatically | GET /api/v1/store-orders with updated_since, plus the order.created webhook |
Who can export#
Exporting needs the export reports permission. Owners, admins, branch admins, managers and finance members have it; agents, designers and viewers do not. A member without it sees the Export button, and the dialog explains who can export for them. It also works in a read-only workspace. See Team, roles and permissions.
Downloads are part of the Store area, so they cover every workspace with a Store. The REST API and webhooks need the Scale or Enterprise plan, see Plans and billing.
Download orders#
- Open Store, then Orders (the board or History) or Reports, and choose Export.
- Pick the dates: Today, Yesterday, This week, Last week, This month, Last month or Custom with a From and To date.
- Under Orders, pick Completed (delivered or picked up, the default and the right choice for accounting), Not cancelled (every order except rejected and cancelled ones) or All. Optionally narrow Source to Storefront, AI chat, Dashboard, Phone or API.
- Pick a Format (below) and choose Export.
Sela fetches the orders, shows how many it has so far, then downloads the file. You can Cancel at any time. Each export is recorded in the workspace's audit trail: who exported, the dates and filters, the format, how many orders, and whether phone numbers were full or masked. When it finishes you see the number of orders and the sales total, with Download again and Export something else. The dialog remembers your last choices on that browser.
How the dates work:
- Dates are business days in your workspace's time zone (set in your environment), not your computer's. An order placed at 1 a.m. belongs to that day.
- Weeks start on Saturday.
- One export covers up to 400 days and up to 50,000 orders. If a range holds more, Sela asks you to choose a shorter range and export it in parts.
- Orders are listed oldest first.
Formats#
| Format | File | What it holds |
|---|---|---|
| Orders (CSV) | sela-orders-<from>_<to>.csv | One row per order. For accounting and spreadsheets. |
| Order items (CSV) | sela-order-items-<from>_<to>.csv | One row per item, with the order's number, date, status, customer and total repeated on each row. The format POS and ERP imports expect. |
| Excel workbook | sela-orders-<from>_<to>.xlsx | Three sheets: Orders, Items and Daily summary. Headers in your dashboard language, Arabic sheets right to left, amounts as numbers, dates as real Excel dates in your workspace's time, filters on every header. |
| JSON | sela-orders-<from>_<to>.json | { "schema": "sela.order.v1", "exported_at", "range": { "from", "to" }, "timezone", "orders": [...] }, every order in full. For developers. |
CSV files are UTF-8 with a byte order mark and Windows line endings, so Excel shows Arabic correctly when you double-click them. Column headers are fixed English names that never change, so an import you set up once keeps working. Text that a spreadsheet would treat as a formula (starting with =, +, -, @) gets a leading apostrophe; phone numbers such as +9647701234567 and all amounts are left as they are.
The daily summary#
The Daily summary sheet has one row per business day and currency:
| Column | Meaning |
|---|---|
| Orders | Orders placed that day in the export |
| Completed | How many of them are completed |
| Cancelled | How many were rejected or cancelled |
| Item sales | The item subtotals of orders that count as sales |
| Delivery fees | Their delivery fees |
| Discounts | Their discounts |
| Net sales | Their order totals |
Rejected and cancelled orders are not sales, as on Store, Reports. A Total row per currency closes the sheet.
Phone numbers#
Customer phone numbers follow your phone privacy setting, exactly as the orders board shows them to you. Members who may export contacts (owners, admins and branch admins) always get full numbers. When numbers are masked for you, the dialog says so before you export. The REST API and webhooks always carry full numbers, since they belong to the workspace's own integrations.
Orders without items#
Staff can record an order as an agreed amount with no menu items, described in its notes, and orders made from an extracted invoice can look the same. In sela.order.v1 these have "amount_only": true and an empty lines list. So that line-based imports never drop them, the Order items CSV and the Items sheet give each one a single row:
| Column | Value |
|---|---|
sku | SELA-AMOUNT |
name / name_ar | Order amount / مبلغ الطلب |
quantity | 1 |
unit_price, line_total | The order's subtotal |
note | The order's notes |
Map SELA-AMOUNT to a general "sales" or "misc" item in your POS or accounting system.
Import into your POS or ERP#
- Export Order items (CSV) for a test day and import it into your system.
- Map the columns once:
number(ororder_id) is the order,skuidentifies the item,quantity,unit_priceandline_totalare the line, andorder_totalwithcurrencyis the bill. - Use
numberororder_idto skip orders you imported before, so exporting overlapping dates never creates duplicates. - Run it daily, or automate it with the REST API.
sku is Sela's item key: product:<id> for store products, dish:<key> for menu items, offer:<id> for offers, or empty for orders taken before items had keys. Give your items the same codes in your system, or keep a mapping table.
Orders CSV columns#
| Column | Meaning |
|---|---|
number | The order number customers see, such as ORD-7K3M |
business_date | YYYY-MM-DD, the business day the order was placed |
created_at | When it was placed, ISO 8601 with your workspace's UTC offset, such as 2026-10-05T14:03:22.123+03:00 |
created_time | HH:MM in your workspace's time |
status | submitted, accepted, preparing, ready, out_for_delivery, completed, rejected or cancelled |
source | storefront, ai_chat, dashboard, phone or api |
channel | The conversation's channel, such as whatsapp, instagram, messenger, telegram or web; empty when the order has no conversation |
branch | The delivery branch's name, when your delivery prices are per branch |
customer_name, customer_phone | The customer (see Phone numbers) |
customer_id | Sela's customer id, empty when none |
fulfillment_type | delivery or pickup |
area, address, landmark, maps_url | Delivery details |
items_count | Total quantity of items |
items_summary | The items as text, such as 2 × Shawarma - Large, Fries |
amount_only | true for an order without items |
subtotal, delivery_fee, discount, tax, total | Amounts in major units: whole dinars, dollars with cents. tax is always 0 today. |
currency | IQD or USD |
payment_method, payment_status | cash_on_delivery; unpaid or paid |
driver_name, delivery_status | The assigned driver and the delivery's status, when a driver was assigned |
invoice_number, invoice_status | The linked invoice, when there is one |
notes | The order's notes |
cancellation_reason | For rejected or cancelled orders with a reason: customer_request, out_of_stock, closed, out_of_zone, customer_unreachable, fake_order, no_driver or other |
accepted_at, ready_at, out_for_delivery_at, completed_at, cancelled_at, rejected_at | When the order last reached each step, same format as created_at |
taken_by | The team member who placed a staff order |
updated_at | When anything on the order last changed |
order_id | Sela's id for the order |
Order items CSV columns#
| Column | Meaning |
|---|---|
number, business_date, created_at, status, source, customer_name, customer_phone, area, payment_status | As in the orders file |
order_total, currency | The order's total |
line_no | The line's position in the order, from 1 |
sku | The item key (see above), or SELA-AMOUNT |
name, name_ar | The item, and its Arabic name when it has one |
variant, variant_ar | The size or type chosen |
modifiers | Options as text, such as Extras: Cheese; an offer lists what it includes |
quantity, unit_price, line_total | The line |
note | The customer's note on this item |
order_id | Sela's id for the order |
The sela.order.v1 structure#
The JSON download, GET /api/v1/store-orders and the order_v1 webhook field all carry this object. Fields are never renamed or removed in version 1; new fields can be added, so ignore ones you do not know. Amounts are numbers in major units, times are ISO 8601 strings with your workspace's UTC offset, and fields without a value are null.
| Field | Type | Meaning |
|---|---|---|
schema | string | Always sela.order.v1 |
id | string | Sela's order id |
number | string | The order number customers see |
created_at, updated_at | string | Placed, and last changed |
business_date | string | YYYY-MM-DD in your workspace's time zone |
timezone | string | Your workspace's time zone, such as Asia/Baghdad |
status | string | As in the CSV |
source | string | As in the CSV. New sources can be added. |
channel | string or null | As in the CSV |
branch | object or null | { "key", "name" }, the delivery branch |
customer | object | { "id", "name", "phone" } |
fulfillment | object | { "type", "area", "address", "landmark", "maps_url" }; type is delivery or pickup |
amount_only | boolean | true when the order has no item lines |
lines | array | The items, below; empty for amount-only orders |
totals | object | { "subtotal", "delivery_fee", "discount", "tax", "total", "currency" }; tax is 0 |
payment | object | { "method", "status" } |
delivery | object or null | { "driver_name", "status" } once a driver is assigned; status is assigned, out_for_delivery, delivered, not_delivered or cancelled |
invoice | object or null | { "number", "status" }; status is draft, approved_locked or void |
notes | string or null | The order's notes |
cancellation_reason | string or null | As in the CSV |
timeline | object | accepted_at, ready_at, out_for_delivery_at, completed_at, cancelled_at, rejected_at: when the order last reached each step, or null |
taken_by | string or null | The team member who placed a staff order |
Each entry of lines:
| Field | Type | Meaning |
|---|---|---|
line_no | number | Position from 1 |
sku | string or null | The item key |
name, name_ar | string, string or null | The item names |
variant, variant_ar | string or null | The size or type |
modifiers | array | { "group", "group_ar", "option", "option_ar", "price_delta" } for each option chosen |
modifiers_text | string | The options as one line; an offer lists its contents |
quantity, unit_price, line_total | number | The line |
note | string or null | The customer's note |
{
"schema": "sela.order.v1",
"id": "jh72...",
"number": "ORD-7K3M",
"created_at": "2026-10-05T14:03:22.123+03:00",
"updated_at": "2026-10-05T14:40:00.000+03:00",
"business_date": "2026-10-05",
"timezone": "Asia/Baghdad",
"status": "completed",
"source": "storefront",
"channel": null,
"branch": null,
"customer": { "id": "k57...", "name": "Ali", "phone": "9647701234567" },
"fulfillment": { "type": "delivery", "area": "Karrada", "address": "Street 14, House 3", "landmark": "Near the mosque", "maps_url": null },
"amount_only": false,
"lines": [
{
"line_no": 1,
"sku": "dish:shawarma",
"name": "Shawarma",
"name_ar": "شاورما",
"variant": "Large",
"variant_ar": "كبير",
"modifiers": [{ "group": "Extras", "group_ar": "إضافات", "option": "Cheese", "option_ar": "جبن", "price_delta": 500 }],
"modifiers_text": "Extras: Cheese",
"quantity": 2,
"unit_price": 4500,
"line_total": 9000,
"note": "No onion"
}
],
"totals": { "subtotal": 9000, "delivery_fee": 2000, "discount": 0, "tax": 0, "total": 11000, "currency": "IQD" },
"payment": { "method": "cash_on_delivery", "status": "paid" },
"delivery": { "driver_name": "Mustafa", "status": "delivered" },
"invoice": null,
"notes": null,
"cancellation_reason": null,
"timeline": {
"accepted_at": "2026-10-05T14:04:10.000+03:00",
"ready_at": "2026-10-05T14:20:00.000+03:00",
"out_for_delivery_at": "2026-10-05T14:22:00.000+03:00",
"completed_at": "2026-10-05T14:40:00.000+03:00",
"cancelled_at": null,
"rejected_at": null
},
"taken_by": null
}Keep your system in sync automatically#
For a system that should always have the latest orders, without anyone downloading files:
- Create an API key with
orders:readunder API Keys (Scale or Enterprise). - Once, pull everything:
GET /api/v1/store-orders?from=2026-01-01, followingnext_cursoruntilis_doneistrue. Keepmeta.next_updated_sincefrom the first page. - Then poll with
updated_sinceset to the saved value, follownext_cursorto the end, and save the last page'smeta.next_updated_sincefor the next poll. Every change to an order (a new status, payment, delivery, address, its invoice's status) moves itsupdated_at, so you receive it again with its new state. - Save orders by
id, overwriting what you have. Polls overlap by design (a couple of minutes), so the same order can come back; overwriting makes that harmless. - For instant notice of new orders, subscribe a webhook to
order.createdandorder.status_changed; both carryorder_v1.
Can't find what you need? Contact support.