Importable sales order columns reference
This page is the complete lookup for every column the Import Sales Orders spreadsheet importer reads, plus the exact validation each one is subject to. It's the reference companion to the task guide Import sales orders — read that first if you want the step-by-step Upload → Map → Validate → Import flow; come here to look up a specific column, its accepted values, or an edge case.
Everything below is read straight from the importer, so it's authoritative for what the Import Sales Orders window accepts. For what each field means once it lands on the order, see the Fields reference.
Before you begin
- Importing requires the Import sales orders permission (
sales_orders.import). Without it the Import button is hidden. See the Permissions reference. - Products, sales channels, currencies, warehouses, and nominal codes referenced by your file must already exist — the importer resolves them by name (or code) and errors on anything it can't find. It never creates them for you.
- Customers are the exception. A row can auto-create a new customer when the email or name doesn't match an existing one (see Customer columns).
- The download template (Download Template on step 1) is seeded with your own channels, customers, products, and reference values, and carries a Field Guide sheet mirroring the tables below.
How rows become orders
The importer uses one row per line item. Header columns (order number, customer, channel, currency, addresses, and the order-level totals) are repeated on every row that belongs to the same order, and the importer collapses them into one multi-line order.
| Aspect | Behavior |
|---|---|
| Accepted file types | .csv, .tsv, .xlsx, .xls, or pasted CSV/TSV text. |
| Delimiter & header row | Auto-detected; you confirm the First row is a header checkbox before mapping. |
| Column mapping | Each file column is bound to a target field via a Maps To dropdown. Required fields are flagged; unwanted columns can be set to Skip this column. |
| Grouping | Rows are grouped into one order by id, or by (sales_order_number + customer), so repeated header values on each line collapse into a single order. |
| Order-level values | order_discount_amount, order_discount_rate, shipping_amount, addresses, and all header fields are read from the first row of each order group. Custom fields are read from the first row too. |
| Row cap | Up to 50,000 rows per run. |
Header & upsert columns
These describe the whole order and are read from the first row of each order group.
| Column | Required | Type / format | Accepted values | Notes |
|---|---|---|---|---|
id | No | Integer | An existing sales order ID | The upsert key. When present, the row updates that exact order. Blank creates a new order (or matches on number + channel — see Upsert rules). An ID that doesn't exist is Blocked. |
sales_order_number | No | Text (≤255) | Any | Blank auto-generates a number. When id is blank, this combines with sales_channel_name as the upsert match key. |
order_date | Yes (create) | Date YYYY-MM-DD | A parseable date | Interpreted in your account timezone. Optional on an update (the existing order keeps its date). |
sales_channel_name | Yes (create) | Text | An existing channel name | Every order must belong to a sales channel. Resolved by name (case-insensitive). Optional on an update. |
sub_sales_channel_name | No | Text | An existing sub-channel name | Resolved by name. |
store_name | No | Text | An existing store name | Defaults to your sales-order default store when blank. |
currency_code | No | Text | An existing ISO currency code | Defaults to the channel's or your account's default currency when blank. |
customer_po_number | No | Text | Any | The customer's own PO reference. |
requested_shipping_method | No | Text | Free text, or a shipping-method name | Stored as free text; also matched to a system shipping method when the value resolves to one. |
ship_by_date | No | Date YYYY-MM-DD | A parseable date | Latest date the order should ship by. |
deliver_by_date | No | Date YYYY-MM-DD | A parseable date | Latest date the order should be delivered by. |
hold_until_date | No | Date YYYY-MM-DD | A parseable date | Earliest date the order may ship — held until then (for example, preorders). |
tags | No | Text | Comma-separated (tag1, tag2) | Tags are auto-created if missing. On an update a blank cell preserves the existing tags. |
Customer columns
The customer is resolved in this order: customer_id → customer_email → customer_name. Only customer_email can auto-create a customer; the other two must match an existing record.
| Column | Required | Type / format | Accepted values | Notes |
|---|---|---|---|---|
customer_id | No | Integer | An existing customer ID | Exact match, checked first. An ID that doesn't exist is a row error. |
customer_email | Preferred | Text | Any email | Matches an existing customer by email; if none matches, a new customer is created from the row. This is the recommended key. |
customer_name | No | Text | Any | Fallback used only when customer_id and customer_email are blank. Errors if the name is ambiguous (more than one customer shares it) or not found (it can't auto-create without an email). |
customer_company | No | Text | Any | Only used when auto-creating a new customer. Ignored for a matched/existing customer. |
customer_phone | No | Text | Any | Only used when auto-creating a new customer. Ignored for a matched/existing customer. |
On a new order at least one of customer_id, customer_email, or customer_name is required. On an update where the row's customer matches (or omits) the order's current customer, the existing customer is kept and no change is made.
Order-level total columns
Read from the first row of each order group only. If you put a non-zero value on a later line of a multi-line order, it's ignored and the preview warns you.
| Column | Required | Type / format | Accepted values | Notes |
|---|---|---|---|---|
order_discount_amount | No | Number ≥ 0 | Amount in the order currency | An order-level discount as a fixed amount, allocated across the lines. |
order_discount_rate | No | Number 0–100 | Percentage | An order-level discount as a percentage. If both order_discount_amount and order_discount_rate are given, the rate wins and the amount is discarded with a warning. |
shipping_amount | No | Number ≥ 0 | Amount in the order currency | Adds a "Shipping" revenue charge to the order. |
Re-importing the same order wipes the discount and shipping records the previous import created and re-applies them from the new values — so correcting a sheet and re-importing doesn't stack duplicate charges. Discounts and shipping added manually or by a channel sync are left untouched.
Address columns
Only these five fields are read for each of shipping and billing. On an update, a blank cell preserves the existing address rather than wiping it; supply at least one non-blank field to overwrite.
| Column | Required | Type / format | Notes |
|---|---|---|---|
shipping_address | No | Text | Street address line. |
shipping_city | No | Text | |
shipping_province | No | Text | State / province / region. |
shipping_zip | No | Text | ZIP / postal code. |
shipping_country | No | Text | Country name or ISO code. |
billing_address | No | Text | Street address line. |
billing_city | No | Text | |
billing_province | No | Text | State / province / region. |
billing_zip | No | Text | ZIP / postal code. |
billing_country | No | Text | Country name or ISO code. |
Line-item columns
One set per row. Every row with a sku becomes a line on its order.
| Column | Required | Type / format | Accepted values | Notes |
|---|---|---|---|---|
sku | Yes (create) | Text | An existing product SKU | Must resolve to a standard or kit product. Bundles and subscription products are rejected. An unmatched SKU is a line error. |
description | No | Text (≤255) | Any | Defaults to the product's name when blank. |
quantity | Yes | Number > 0 | A positive number | |
unit_price | Yes | Number ≥ 0 | Price per unit, in the order currency | |
discount | No | Number ≥ 0 | Amount per unit | Stored as a fixed line discount of discount × quantity — it's per-unit, not a percentage and not a line total. |
tax_rate | No | Number | Percentage (for example, 8.875) | Defaults to 0 when blank. |
warehouse_name | No | Text | An existing warehouse name | Blank lets the system route the line by inventory. |
nominal_code | No | Text | An existing nominal code | The accounting code for the line; matched by code. |
Custom-field columns
For every custom field you've defined on sales orders, the template offers a custom_<slug> column (for example custom_gift_message). Mapping one sets that custom field's value on the order.
| Behavior | Detail |
|---|---|
| Column name | custom_<slug>, one per sales-order custom field. The Field Guide sheet lists the slug, type, and valid values for each. |
| Sets a value | A non-blank cell writes that value to the custom field. |
| Clears a value (update) | A mapped but blank cell clears the field on the order. |
| Leaves a value untouched | A custom-field column you don't map is left exactly as it was — a partial-import sheet never wipes custom fields it doesn't include. |
| Which row | Read from the first row of each order group, like the other header fields. |
Mapping custom_<slug> columns now writes the values through as described above. (An earlier version silently dropped these columns; that has been fixed.)
How the importer decides create vs update
For each order group the importer picks a target in this order:
- By
id— if a row has anid, that exact order is the target. - By (
sales_order_number+sales_channel_name) — ifidis blank and the number-plus-channel pair matches an existing order, that order is updated. Otherwise a new order is created.
An update with line rows replaces every line
When an update row includes line items, all lines on the matched order are replaced with the rows in your import — not merged. For a header-only change (tags, PO number, dates, sub-channel, shipping method, custom fields), leave the sku/quantity/unit_price columns out of the file entirely so the existing lines are left untouched.
States that block an update
An order in one of these states is marked Blocked in the preview and never sent:
| State | What's blocked | Workaround |
|---|---|---|
| Archived | Any import update. | Unarchive it first, or drop the row. |
| Canceled | Any import update. | Drop the row. |
id not found | The referenced order doesn't exist. | Remove the id to create a new order instead. |
| Closed | Any field except tags, sub_sales_channel_name, customer_po_number, and requested_shipping_method. | Restrict the row to those four fields, or reopen the order. |
If two rows in the same file both target the same existing order, both are Blocked with a collision error — consolidate them into one group.
Validation rules at a glance
| Field kind | Rule | Blank cell |
|---|---|---|
Text lookups (sales_channel_name, sub_sales_channel_name, store_name, currency_code, warehouse_name, nominal_code) | Must resolve to an existing record by name/code (case-insensitive); an unknown value is an error. | Left unset (defaults apply where noted). |
sku | Must resolve to an existing standard or kit product. | A row with no SKU is treated as a non-line (header-only) row. |
quantity | Must be a positive number. | Error on a line row. |
unit_price | Must be a non-negative number. | Error on a line row. |
order_discount_rate | Numeric, 0–100. | Ignored. |
order_discount_amount, shipping_amount, discount | Numeric, non-negative. | Ignored. |
Dates (order_date, ship_by_date, deliver_by_date, hold_until_date) | Must be a parseable date; interpreted in your account timezone. | Left unset (except order_date, required on create). |
tags / addresses / custom fields | — | Blank preserves the existing value on an update. |
Next steps
- Import sales orders — the full task flow, including update mode, blocked rows, and the OCR/PDF path.
- Export sales order columns reference — the Summary and Line-item columns the Export button produces.
- Bulk actions on the sales orders list — where the Import and Export buttons live.
- Fields reference — what each order-header and line field means on the order itself.
- Add notes, tags, and custom fields — set up the custom fields these
custom_<slug>columns write to.