Creating orders

Submit orders in bulk, and read the per-order result correctly.

Overview

An Order is a request to ship something to someone. It carries the addresses, the lines, and a blueprint_id that decides how the order gets fulfilled and shipped.

Two things about order.create differ from the other create mutations:

  • It takes a list of orders.
  • It returns OrderCreationResult, not Order — a per-order success flag. A partial failure is a successful response.

Before you create an order

An order cannot be created in isolation. You need:

PrerequisiteWhyWhere
ItemsOrder lines resolve by sku or item_idCreating items
A blueprintblueprint_id is required and drives fulfillment and shippingCreating blueprints

Creating orders

mutation CreateOrders($orders: [OrderInput!]!) {
    order {
        create(orders: $orders) {
            external_order_id
            success
            error_message
            order {
                id
                external_order_id
            }
        }
    }
}
{
    "orders": [
        {
            "external_order_id": "SO-10432",
            "blueprint_id": "3d7c6a15-9e28-4b70-8c31-5f0a2e94d6b1",
            "shipping_address": {
                "attention_first_name": "Dana",
                "attention_last_name": "Reyes",
                "street": ["1200 Market St", "Suite 400"],
                "city": "Philadelphia",
                "state_code": "PA",
                "postal_code": "19107",
                "country_code": "US",
                "residential": true
            },
            "billing_address": {
                "attention_first_name": "Dana",
                "attention_last_name": "Reyes",
                "street": ["1200 Market St", "Suite 400"],
                "city": "Philadelphia",
                "state_code": "PA",
                "postal_code": "19107",
                "country_code": "US"
            },
            "order_lines": [
                {
                    "quantity": 2,
                    "identifier": { "sku": "WIDGET-BLUE-01" },
                    "sell_price": "24.99"
                }
            ]
        }
    ]
}

Required fields

FieldTypeDescription
external_order_idString!Your order number. This is how results are keyed back.
blueprint_idID!Which blueprint fulfills and ships this order.
shipping_addressAddressInput!Where it goes.
billing_addressAddressInput!Who is billed.
order_lines[OrderLineInput!]!What is on the order. Must not be empty.

NOTE

AddressInput names its fields postal_code, state_code and country_code, and splits the recipient into attention_first_name / attention_last_name or company_name — not zip, state, country or name. Every field on it is optional at the type level; the carrier decides what is actually needed.

Order lines

Each line names a quantity and an identifier. The identifier is a OrderLineIdentifierInput — supply either sku or item_id:

{
    "quantity": 2,
    "identifier": { "sku": "WIDGET-BLUE-01" },
    "sell_price": "24.99",
    "discount": "2.00"
}

sku matches against item SKUs and item aliases, so a marketplace's own identifier resolves without translation on your side — see aliases.

Handling the result

order.create returns one result per submitted order. Some can succeed while others fail, and the HTTP status is still 200 with no errors key. Inspect each result individually.

{
    "data": {
        "order": {
            "create": [
                {
                    "external_order_id": "SO-10432",
                    "success": true,
                    "error_message": null,
                    "order": { "id": "a58f2d04-6b39-4c17-9e85-1d7b30f2a9c6" }
                },
                { "external_order_id": "SO-10433", "success": false, "error_message": "No item matching sku WIDGET-RED-99", "order": null }
            ]
        }
    }
}

Results are keyed by external_order_id, which is why that field is required — match on it rather than on array position.

WARNING

A 200 response does not mean every order was created. Check success on each element of the returned list.

Dates and holds

FieldEffect
first_ship_dateOrder will not ship before this date.
last_ship_dateOrder should ship by this date.
order_batch_idGroups orders for batch processing.

To hold an order after creation:

mutation HoldOrders($orders: [SetOrderHoldStatusInput!]!) {
    order {
        set_order_hold_status(orders: $orders) {
            id
            external_order_id
        }
    }
}

Updating orders

Three different shapes, depending on what you are changing:

OperationUse for
order.updatePer-order changes, each with its own values
order.bulk_updateOne set of changes applied to many order ids
order.update_order_ship_to_addressCorrecting a delivery address

Addresses have their own mutations because changing one re-triggers address validation.

Sub-resources

Parts of an order that are managed separately, each with create / update / delete:

Cancelling

mutation CancelOrders($orders: [ID!]!) {
    order {
        cancel_order(orders: $orders) {
            id
            external_order_id
        }
    }
}

International orders

Customs information comes from three separate places, and they are not alternatives — each covers something the others do not.

LayerCarriesSet on
Item customsPer-commodity data: hs_code, country_of_origin, USMCA origin criterionThe item, reusable across orders
Order customsThe whole declaration: parties, declared and insured value, commercial invoice, AES / ITAR / FICE, incotermsThe order, via customs
Customs blueprintDefaults for eight order-customs fieldsThe blueprint

Set customs on the order for anything crossing a border:

{
    "customs": {
        "export_reason": "SOLD",
        "incoterms": "DDP",
        "duties_prepaid": true,
        "taxes_prepaid": true,
        "usmca_applies": false
    }
}

OrderCustomsInput is much wider than that — exporter, importer and seller parties, override_total_declared_value, insured_value, commercial_invoice, and the export-control blocks. The blueprint does not cover those; they are order-level only.

What a customs blueprint actually does

A customs blueprint initializes eight fields on the order's customs information: comments, export_reason, duties_prepaid, taxes_prepaid, incoterms, usmca_applies, aes_exemption and itar_license_or_exemption_number.

Each is configured on the blueprint as a value plus an allow_overwrite flag, which defaults to false. So by default the blueprint only fills a field the order left unset — a value you send on the order wins. Setting allow_overwrite: true inverts that for that one field, and the blueprint's value replaces whatever the order supplied.

NOTE

A customs blueprint does not read item customs data. hs_code and country_of_origin come from each item's own customs record and are declared per commodity; the blueprint only supplies shipment-level defaults.

Finding orders again

Orders are searchable under the ORDER entity type:

query FindOrders($search: PaginatedSearchQuery) {
    searches {
        order {
            search(search: $search) {
                rows {
                    id
                    external_order_id
                }
                next_cursor
                has_next_page
            }
        }
    }
}

See Searching for filters, sorting and pagination.