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#

  1. Create the order with createOrder
  2. (Optional) Set an expiration date with setExpirationDateForOrder
  3. 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!

NameTypeRequiredDescription
channel_id
String
OptionalID of the storefront channel. Required when not authenticated with a storefront token.
currency
Currency!
RequiredISO 4217 currency code (e.g. EUR).
country_code
String
OptionalISO 3166-1 alpha-2 delivery country code — used for tax calculation.
customer
CustomerInput
OptionalThe customer to attach — a contact, organisation, or project.
billing
CreateOrderBillingInput
OptionalBilling details.
delivery
CreateOrderDeliveryInput
OptionalDelivery details.
phone_number_id
String
OptionalID of a phone number to attach to the order.

Returns: Order

NameTypeRequiredDescription
id
ID!
RequiredThe ID
number
String!
RequiredOrder number
total
Money!
RequiredTotal value
currency
Currency!
RequiredCurrency code

Save the returned order.id — you'll need it in every subsequent step.

Create an order with a contact:

mutation CreateOrder($input: CreateOrderInput!) {
  createOrder(input: $input) {
    order {
      id
      processing
    }
  }
}

Variables:

{
  "input": {
    "channel_id": "3c7d1e5f-9a2b-4f8e-b6d0-1234abcd5678",
    "currency": "EUR",
    "country_code": "NL",
    "customer": {
      "contact_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
    },
    "delivery": {
      "addresses": [
        {
          "address_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
          "type": "ADDRESS"
        }
      ]
    }
  }
}
Tip:

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:

mutation CreateOrder($input: CreateOrderInput!) {
  createOrder(input: $input) {
    order {
      id
      processing
    }
  }
}

Variables:

{
  "input": {
    "channel_id": "3c7d1e5f-9a2b-4f8e-b6d0-1234abcd5678",
    "currency": "EUR",
    "country_code": "NL",
    "customer": {
      "organisation_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "contact_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "reference": "PO-2024-001"
    },
    "billing": {
      "address_id": "e5f6a7b8-c9d0-1234-ef01-345678901234"
    },
    "delivery": {
      "addresses": [
        {
          "address_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
          "type": "ADDRESS"
        }
      ]
    }
  }
}

Create an order with an project — optionally include an organisation and contact person:

mutation CreateOrder($input: CreateOrderInput!) {
  createOrder(input: $input) {
    order {
      id
      processing
    }
  }
}

Variables:

{
  "input": {
    "channel_id": "3c7d1e5f-9a2b-4f8e-b6d0-1234abcd5678",
    "currency": "EUR",
    "customer": {
      "project_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
      "organisation_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "contact_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
    },
    "delivery": {
      "addresses": []
    }
  }
}

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!

NameTypeRequiredDescription
order_id
String!
RequiredID of the order from step 1.
expires_at
Int64!
RequiredUnix timestamp (milliseconds) when the order expires.

Returns: Order

NameTypeRequiredDescription
id
ID!
RequiredThe ID
number
String!
RequiredOrder number
total
Money!
RequiredTotal value
currency
Currency!
RequiredCurrency code
mutation SetExpirationDateForOrder($input: SetExpirationDateForOrderInput!) {
  setExpirationDateForOrder(input: $input) {
    order {
      id
    }
  }
}
{
  "input": {
    "order_id": "72fca344-2a6f-4c3e-b4ca-029920b2522a",
    "expires_at": 1735689599000
  }
}
Tip:

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!

NameTypeRequiredDescription
order_id
String!
RequiredID of the order from step 1.
items
[OrderItemInput!]!
RequiredProducts to add.

Returns: Order

NameTypeRequiredDescription
id
ID!
RequiredThe ID
number
String!
RequiredOrder number
total
Money!
RequiredTotal value
currency
Currency!
RequiredCurrency code

Basic — add products at catalogue price:

mutation AddItemsToOrder($input: AddItemsToOrderInput!) {
  addItemsToOrder(input: $input) {
    order {
      id
    }
  }
}
{
  "input": {
    "order_id": "72fca344-2a6f-4c3e-b4ca-029920b2522a",
    "items": [
      { "sku": "BLK-HOODIE-M", "quantity": 1 },
      { "sku": "BLK-HOODIE-L", "quantity": 2 }
    ]
  }
}

With a percentage discount:

mutation AddItemsToOrder($input: AddItemsToOrderInput!) {
  addItemsToOrder(input: $input) {
    order {
      id
    }
  }
}
{
  "input": {
    "order_id": "72fca344-2a6f-4c3e-b4ca-029920b2522a",
    "items": [
      {
        "sku": "BLK-HOODIE-M",
        "quantity": 1,
        "adjustments": [
          {
            "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "description": "10% loyalty discount",
            "amount": 10,
            "is_percentage": true,
            "is_discount": true
          }
        ]
      }
    ]
  }
}

With a custom price override:

mutation AddItemsToOrder($input: AddItemsToOrderInput!) {
  addItemsToOrder(input: $input) {
    order {
      id
    }
  }
}
{
  "input": {
    "order_id": "72fca344-2a6f-4c3e-b4ca-029920b2522a",
    "items": [
      {
        "sku": "BLK-HOODIE-M",
        "quantity": 1,
        "price": 3999,
        "original_price": 4999
      }
    ]
  }
}
Tip:

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 addItemsToOrder call or batch them into multiple calls — either approach works.
  • customer.contact_id, customer.organisation_id, and customer.project_id are mutually exclusive as the primary customer identifier; pick one based on your customer type. A contact_id can always be added alongside an organisation or project as the contact person.
  • currency must 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 } } or organisation(id: $id) { addresses { id } }.
  • See Authentication for how to pass your API key.
Query Runnerhttps://afosto.app/graphql

No query loaded

Click play on any code block in the docs to load a query here.