Skip to content

Shopify GraphQL migration

Linnworks is upgrading Shopify integrations from Shopify's REST API to its GraphQL API. After an integration is upgraded, new orders arrive with a differently shaped order XML. This page explains what changed, what XmlExtractor 1.1.0 handles for you, and what to check in your own configurations.

Linnworks' guide: Shopify integration upgrade to GraphQL in Linnworks. Section 7 covers the order XML. Linnworks' detailed companion to that section, Shopify OrderXML Data Changes, lists every field rename; ask Linnworks support for a copy. The tables below include everything it describes.

What changed in the XML

Change Before, REST After, GraphQL
Node names PascalCase, for example LineItems camelCase, for example lineItems
Renamed nodes FinancialStatus = paid displayFinancialStatus = PAID
IDs 6380782551076 gid://shopify/Order/6380782551076
Prices Price Blank. The amount is in originalUnitPriceSet > shopMoney > amount
Line items A flat list lineItems with one nodes element per line
Shipping lines A flat list shippingLines > nodes with code and title
Custom attributes NoteAttributes > Property on the order and Properties > Property on line items, as Name/Value pairs customAttributes on the order and on each line item, as key/value pairs. The Property wrapper is gone
Other renamed nodes Currency, PresentmentCurrency, OrderNumber, BuyerAcceptsMarketing, BrowserIp, OrderStatusUrl, PaymentGatewayNames > string currencyCode, presentmentCurrencyCode, number, customerAcceptsMarketing, clientIp, statusPageUrl, paymentGatewayNames
Removed nodes Number, the internal sequence number; ProductExists Gone. Number now matches number, the customer-facing order number, through the case fallback
SKU and vendor LineItems > LineItem > Sku and Vendor Blank at line level. The SKU is under lineItems > nodes > variant > sku or variant > inventoryItem > sku, the vendor under product > vendor
Money ShopMoney listed first presentmentMoney listed first, and currencyCode blank inside each money set; the currency is stated once at order level
Status values Lower case: paid, open Upper case: PAID, OPEN
Dates 2026-01-22T08:44:12+00:00 2026-01-22T08:44:12Z
Delivery method FulfillmentOrders > FulfillmentOrder > DeliveryMethod > MethodType = shipping fulfillmentOrders > nodes > deliveryMethod > methodType = SHIPPING. MethodType alone still resolves; the value is upper case
Gift card flag LineItems > LineItem > GiftCard lineItems > nodes > isGiftCard
Transactions Transactions > Transaction > Gateway transactions > gateway; the Transaction wrapper is gone
Browser IP ClientDetails > BrowserIp clientIp
Staff user UserId No equivalent seen. staffMember exists but is empty in the samples
Risk block Risks > Data > Order > Risk > Assessments > Assessment > Fact > Description risk > assessments > facts > description, each with a sentiment
Blank nodes Rare Common. GraphQL only returns what Linnworks asks for, so many nodes are empty.
Fulfillment orders Not present fulfillmentOrders, listed before the order's own nodes, with its own id, a location > id, and a partial lineItems

Only orders downloaded after the upgrade use the new shape. Orders already in Linnworks keep the old one, so both exist side by side for a while.

Linnworks also changes the order reference to {ShopifyOrderId}-{FulfillmentOrderId}. XmlExtractor receives Linnworks order IDs from the Rules Engine and never reads the reference, so that change doesn't affect it.

What XmlExtractor 1.1.0 does for you

  • NoteAttribute. reads both shapes. It looks for a name/value pair first and a key/value pair when there is none. A configuration such as NoteAttribute.Gift wrap keeps working on old and new orders without a change.
  • Case no longer breaks a path. Exact case still wins when it exists. When it doesn't, the first node that matches ignoring case is used, so LineItems>Sku finds lineItems > nodes > sku.
  • Empty copies are skipped. When a match has an empty value, or the rest of the path finds nothing under it, the next match is tried. The partial lineItems under fulfillmentOrders no longer hides the real one.
  • The macro records the format. Each order in the new shape is marked in the macro's log, which support can read, so we can tell you which of your orders arrive in the new shape.
  • Empty nodes can't break an order. The new XML contains many empty nodes such as <name />. Version 1.0.0 could fail the whole order on them. Version 1.1.0 ignores them.

What to check in your configurations

  1. Renamed nodes. FinancialStatus is now displayFinancialStatus, and its values are upper-case, PAID rather than paid. Update the path and any Rules Engine condition that compares the value.
  2. Blank line-item names. lineItems > nodes > name is empty in the new shape. Use title, so LineItems>Name becomes lineItems>nodes>title or, with the case fallback, LineItems>Title.
  3. Prices. Plain price nodes are blank. Use the money objects, for example totalPriceSet>shopMoney>amount or lineItems>nodes>originalUnitPriceSet>shopMoney>amount.
  4. Shadowed nodes. id now returns a location id and name returns the billing name, because fulfillmentOrders and billingAddress come first. Use >>id and >>name: a leading >> prefers the shallowest match, which is the order's own node. The same applies to tags: customer > tags comes before the order's own tags, so use >>tags for the order's tags. See path-syntax.md.
  5. Custom attributes. Order-level NoteAttributes and line-item Properties both become customAttributes with key/value pairs. NoteAttribute.<name> reads both shapes, so a configuration such as NoteAttribute.Gift message needs no change. A raw path such as NoteAttributes>Property>Value does: switch it to NoteAttribute.<name>. When an order-level and a line-level attribute share a key, the order-level one is returned, because it comes first in the document.
  6. Lines from sibling orders. With the Split Orders by Shopify Fulfillments setting on, each Linnworks order carries the full Shopify order data, so lineItems>nodes>sku may return a line that belongs to another fulfillment. Check the remainingQuantity values under fulfillmentOrders if that matters to you.
  7. SKU and vendor. Both are blank at line level in the new shape. Paths such as LineItems>Sku and lineItems>nodes>sku still resolve, because XmlExtractor skips the empty node and finds the SKU under variant, and LineItems>Vendor finds product > vendor the same way. To be explicit, use lineItems>nodes>variant>sku.
  8. Money sets. Each money set lists presentmentMoney before shopMoney. A path that stops at amount, such as totalPriceSet>amount, returns the presentment amount. Name the side you want: totalPriceSet>shopMoney>amount.
  9. Number. The internal sequence number is gone. A configuration that extracted Number now receives the customer-facing order number, because Number matches number ignoring case. If you used OrderNumber, switch to number.
  10. Customer tags. Linnworks renders customer > tags empty in the new shape, so Customer>Tags finds nothing on GraphQL orders. If you rely on it, ask Linnworks to include customer tags in the order XML.
  11. Verify on a real order. Open the order's XML in Linnworks and check the node names against your paths, or set Troubleshoot to true for one order and ask support to confirm the path. See Troubleshooting.

How to tell which shape an order has

  • Support can see Order XML format: Shopify GraphQL in the macro's log for each order in the new shape.
  • In the order's XML view in Linnworks, the new shape has displayFinancialStatus and a fulfillmentOrders block. Don't rely on gid:// ids alone: Shopify REST payloads also carry them in admin_graphql_api_id fields.
  • Linnworks' FAQ: if your Shopify integration settings show Split Orders by Shopify Fulfillments and Use Presentment Currency, the integration is on GraphQL.

Path examples, old and new

The REST names below match Linnworks' notice and a live rendering of a REST-format order: Id, Name, FinancialStatus, LineItems, ShippingLines, NoteAttributes. Take the exact old names from your own configuration.

You want REST path GraphQL path Works on both
A checkout or line-item custom field NoteAttribute.Gift wrap NoteAttribute.Gift wrap Yes
The first line's SKU LineItems>Sku lineItems>nodes>variant>sku Yes. The line-level sku is blank in the new shape and skipped, so the old path reaches the variant's SKU
The currency Currency currencyCode No. List both
The order number OrderNumber number No. List both
The payment gateway PaymentGatewayNames>string paymentGatewayNames No. List both
Marketing consent BuyerAcceptsMarketing customerAcceptsMarketing No. List both
The order total TotalPrice totalPriceSet>shopMoney>amount No. List both
The first line's product name LineItems>Name lineItems>nodes>title No. name is blank in the new shape. List both
Payment status FinancialStatus displayFinancialStatus No. List both: FinancialStatus, displayFinancialStatus
The order name Name >>name No. List both
The Shopify order id Id >>id No. List both
The shipping service code ShippingLines>Code shippingLines>nodes>code Yes, thanks to the case fallback
A line price Price lineItems>nodes>originalUnitPriceSet>shopMoney>amount No. List both
The order's tags Tags >>tags Use >>tags on both. On the new shape a plain Tags can return the customer's tags instead, because customer > tags comes first in the document
The customer's tags Customer>Tags Not available Linnworks renders customer > tags empty in the new shape, on every order seen since the switch. Raise it with Linnworks if you need it

Listing both paths in one configuration is safe. The one that doesn't exist on an order logs Did not find value and nothing is written for it.