Create Sales Order
POST/api/sales-orders
Creates a sales order, optionally with an embedded customer, shipping/billing addresses, line items, line-level discounts, and financial lines (shipping, fees, etc.). Orders can be created as drafts and approved later, or opened immediately.
orders:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Authentication: Requires Bearer token.
Request body fields:
- order_status (string, required): One of
draft,reserved,open,closed. Line items are required unless the status isdraft. Whenclosed,fulfilled_atbecomes required. - order_date (date-time, required): Order placement date. If the value parses to today's date (a date-only value from a date picker), it is replaced with the exact current timestamp so the order reflects when it was actually placed. Back-dated or forward-dated values are kept as sent.
- currency_id (integer, required without currency_code): Currency record ID.
- currency_code (string, required without currency_id): ISO currency code, e.g.
USD. - sales_order_number (string, optional, max 255): Must be unique within the sales channel. Auto-generated from your order-number settings when omitted.
- customer_po_number (string, optional, max 255): The customer's own purchase-order reference.
- store_id (integer, optional) / store_name (string, optional): Store to attribute the order to.
- sales_channel_id (integer, optional): Sales channel the order belongs to; defaults to the local channel.
- shipping_method_id (integer, optional), requested_shipping_method (string, optional, max 255).
- customer_id (integer, optional): Existing customer ID. Alternatively send the
customerobject below. - sales_rep_id (integer, optional) / sales_rep_name (string, optional, max 255): Provide at most one; a new sales rep is created from the name if it doesn't exist.
- shipping_address_id / billing_address_id (integer, optional): Existing address IDs; each must belong to the order's customer.
- payment_status (string, optional):
unpaid,partially_paid,paid,refunded. - payment_date, ship_by_date, hold_until_date (do-not-ship-before release date), deliver_by_date, packing_slip_printed_at (dates, optional).
- fulfilled_at (date, required when order_status is
closed), tracking_number (string, optional, max 255; only accepted when order_status isclosed). - discount (number, optional, < 1,000,000): Order-level discount amount.
- is_tax_included (boolean, optional): Whether line amounts already include tax.
- tax_rate_id (number, optional).
- tags (array of strings, optional).
- memo_for_customer (string, optional, max 65,535).
- custom_field_values (array, optional): Custom field values keyed by custom field.
sales_order_lines (array; required unless order_status is draft). Duplicate lines are rejected — every line must be unique by product/SKU + sales_channel_line_id + description + quantity + amount + bundle_id; provide a sales_channel_line_id per line for channel-sourced orders. Each line:
- description (string, required, max 255)
- product_id (integer, optional) or sku (string, optional): Identifies the product; omit both for a non-product line.
- amount (number, required, < 100,000,000): Unit price.
- quantity (number, required, >= 0 and < 100,000)
- canceled_quantity (number, required when quantity is 0)
- externally_fulfilled_quantity (number, optional)
- tax_rate_id (number, optional)
- sales_channel_line_id (optional): The channel's own line identifier.
- nominal_code_id / nominal_code_name / nominal_code (optional): Ledger code by ID, name, or code.
- is_product (boolean, optional)
- warehouse_routing_method (string, optional):
dropship,warehouse,advanced, orunassigned. - warehouse_id (integer, optional; required when warehouse_routing_method is
warehouse) - bundle_id (integer, optional): Parent bundle product ID when the line is a bundle component.
- subscription_edition_id (integer, optional): Subscription edition to allocate from; edition allocation limits are enforced.
- line_discounts (array, optional): Each with name (string, required, max 255), type (required:
percentageorfixed_amount), rate (number 0-100, optional), amount (number >= 0, optional), scope (optional,line).
financial_lines (array, optional). Each line:
- financial_line_type_id (integer, optional), nominal_code_id (integer, optional), description (string, optional), quantity (number, optional, >= 0), amount (number, optional), tax_allocation (number, optional), allocate_to_products (boolean, optional), proration_strategy (string, optional:
revenue_based,cost_based,weight_based,volume_based,quantity_based,specific_line,manual), allocate_to_id (integer, optional: sales order line ID to allocate to), allocate_to_type (string, optional).
discount_lines (array, optional): Each with name (string, required, max 255), rate (number, optional), amount (number, optional).
tax_lines (array, optional): Each with name (string, required, max 255), rate (number, optional).
customer (object, optional): company, name, email, phone, fax, address1, address2, address3, city, province, province_code, zip, country, country_code (valid ISO country code), label — all optional strings (max 255).
shipping_address / billing_address (objects, optional): company, name, email, phone, fax, address1, address2, address3, city, province, province_code, zip, county, country_code (valid ISO country code), label — all optional strings (max 255).
Returns the complete created order, including lines, fulfillment state, totals, and addresses. Returns 400 when a line's warehouse routing cannot resolve a valid warehouse for the product.
Requires permission: sales_orders.create
Request
Responses
- 201
- 400
- 401
- 403
- 422
- 429
Created
Response Headers
Bad Request
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Unprocessable Entity
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.