Create an order#
This guide walks through creating an order manually: creating the order with a customer and delivery details, optionally setting an expiration date, then adding products to it.
Overview#
- Create the order with
createOrder - (Optional) Set an expiration date with
setExpirationDateForOrder - Add products with
addItemsToOrder
Step 1 — Create the order#
createOrder sets up the order with a channel, customer, currency, and delivery details. The customer can be a contact, organisation, or project — pass only the fields that apply to your customer type.
Input: CreateOrderInput!
| Name | Type | Required | Description |
|---|---|---|---|
channel_id | String | Optional | ID of the storefront channel. Required when not authenticated with a storefront token. |
currency | Currency!▾ | Required | ISO 4217 currency code (e.g. EUR). |
country_code | String | Optional | ISO 3166-1 alpha-2 delivery country code — used for tax calculation. |
customer | CustomerInput▾ | Optional | The customer to attach — a contact, organisation, or project. |
billing | CreateOrderBillingInput▾ | Optional | Billing details. |
delivery | CreateOrderDeliveryInput▾ | Optional | Delivery details. |
phone_number_id | String | Optional | ID of a phone number to attach to the order. |
Returns: Order
| Name | Type | Required | Description |
|---|---|---|---|
id | ID! | Required | The ID |
number | String! | Required | Order number |
total | Money! | Required | Total value |
currency | Currency! | Required | Currency code |
Save the returned order.id — you'll need it in every subsequent step.
Create an order with a contact:
Variables:
Instead of referencing existing entities by ID, you can also create them inline:
customer.contact / customer.organisation accept full input objects, and
delivery.addresses[].address / billing.address accept an AddressInput.
Create an order with an organisation — optionally include a contact person:
Variables:
Create an order with an project — optionally include an organisation and contact person:
Variables:
Step 2 — (Optional) Set an expiration date#
If the order should expire after a certain period, set the expiration date immediately after creating the order. The value is a Unix timestamp in milliseconds.
Input: SetExpirationDateForOrderInput!
| Name | Type | Required | Description |
|---|---|---|---|
order_id | String! | Required | ID of the order from step 1. |
expires_at | Int64! | Required | Unix timestamp (milliseconds) when the order expires. |
Returns: Order
| Name | Type | Required | Description |
|---|---|---|---|
id | ID! | Required | The ID |
number | String! | Required | Order number |
total | Money! | Required | Total value |
currency | Currency! | Required | Currency code |
To expire the order at the end of a specific day, use the timestamp for 23:59:59 on that date.
For example, end of 2025-01-01 in UTC is 1735689599000.
Step 3 — Add items#
Add one or more products to the order by SKU. You can optionally override the price, add a discount, or attach a batch or serial number per item.
Input: AddItemsToOrderInput!
| Name | Type | Required | Description |
|---|---|---|---|
order_id | String! | Required | ID of the order from step 1. |
items | [OrderItemInput!]!▾ | Required | Products to add. |
Returns: Order
| Name | Type | Required | Description |
|---|---|---|---|
id | ID! | Required | The ID |
number | String! | Required | Order number |
total | Money! | Required | Total value |
currency | Currency! | Required | Currency code |
Basic — add products at catalogue price:
With a percentage discount:
With a custom price override:
price and original_price are in cents — 3999 means € 39,99. Only set original_price when
you also set price; it is shown as the crossed-out catalogue price on the order line.
Notes#
- Items are added per mutation call. If you are adding many products, you can send them all in a single
addItemsToOrdercall or batch them into multiple calls — either approach works. customer.contact_id,customer.organisation_id, andcustomer.project_idare mutually exclusive as the primary customer identifier; pick one based on your customer type. Acontact_idcan always be added alongside an organisation or project as the contact person.currencymust match the price list configured for the channel — mismatched currencies result in a validation error.- Timestamps (
expires_at,ordered_at,expected_at,ship_at) are Unix timestamps in milliseconds (Int64). - To look up addresses for a contact or organisation, query
contact(id: $id) { addresses { id } }ororganisation(id: $id) { addresses { id } }. - See Authentication for how to pass your API key.