Fulfill an order with a tracking number

Read the open fulfillment orders of an order, then create a fulfillment with carrier, tracking number and URL using fulfillmentCreate.

API
Admin GraphQL API
Operations
order.fulfillmentOrders, fulfillmentCreate
Access scopes
write_merchant_managed_fulfillment_orders, write_assigned_fulfillment_orders or write_third_party_fulfillment_orders
Replaces (REST)
POST /admin/api/fulfillments.json
API version
2026-10
Last checked

In short

To mark items as shipped, read the order’s fulfillmentOrders with status OPEN, then call fulfillmentCreate with lineItemsByFulfillmentOrder (fulfillment order ID plus line item IDs and quantities) and trackingInfo (company, number, url). Set notifyCustomer to send the shipping email. Leave out the line items to fulfill everything in that fulfillment order.

How to use it

  1. Send OpenFulfillmentOrders with the order ID. Each fulfillment order is one location’s share of the order.
  2. Pick the fulfillment order line items you’re shipping and their quantities (up to remainingQuantity).
  3. Send ShipWithTracking with the carrier name, tracking number and tracking URL.
  4. Repeat per parcel; a partial fulfillment leaves the rest of the fulfillment order open.

Code

fulfillment-orders.graphql
query OpenFulfillmentOrders($orderId: ID!) {
  order(id: $orderId) {
    id
    name
    fulfillmentOrders(first: 10, query: "status:OPEN") {
      nodes {
        id
        status
        assignedLocation {
          name
        }
        lineItems(first: 50) {
          nodes {
            id
            sku
            remainingQuantity
          }
        }
      }
    }
  }
}
fulfillment-orders.variables.json
{
  "orderId": "gid://shopify/Order/1234567890"
}
fulfillment-orders.response.json
{
  "data": {
    "order": {
      "id": "gid://shopify/Order/1234567890",
      "name": "#1001",
      "fulfillmentOrders": {
        "nodes": [
          {
            "id": "gid://shopify/FulfillmentOrder/1111111111",
            "status": "OPEN",
            "assignedLocation": {"name": "Main warehouse"},
            "lineItems": {
              "nodes": [
                {"id": "gid://shopify/FulfillmentOrderLineItem/2222222221", "sku": "LS-M", "remainingQuantity": 2},
                {"id": "gid://shopify/FulfillmentOrderLineItem/2222222222", "sku": "WS-01", "remainingQuantity": 1}
              ]
            }
          }
        ]
      }
    }
  }
}
fulfillment-create.graphql
mutation ShipWithTracking($fulfillment: FulfillmentInput!) {
  fulfillmentCreate(fulfillment: $fulfillment) {
    fulfillment {
      id
      status
      trackingInfo(first: 5) {
        company
        number
        url
      }
    }
    userErrors {
      field
      message
    }
  }
}
fulfillment-create.variables.json
{
  "fulfillment": {
    "notifyCustomer": true,
    "trackingInfo": {
      "company": "DHL Express",
      "number": "1234567890",
      "url": "https://www.dhl.com/track?tracking-id=1234567890"
    },
    "lineItemsByFulfillmentOrder": [
      {
        "fulfillmentOrderId": "gid://shopify/FulfillmentOrder/1111111111",
        "fulfillmentOrderLineItems": [
          {"id": "gid://shopify/FulfillmentOrderLineItem/2222222221", "quantity": 2}
        ]
      }
    ]
  }
}
fulfillment-create.response.json
{
  "data": {
    "fulfillmentCreate": {
      "fulfillment": {
        "id": "gid://shopify/Fulfillment/1234567890",
        "status": "SUCCESS",
        "trackingInfo": [
          {
            "company": "DHL Express",
            "number": "1234567890",
            "url": "https://www.dhl.com/track?tracking-id=1234567890"
          }
        ]
      },
      "userErrors": []
    }
  }
}

Written by Lintel. MIT license: free to use in your own store and in client work.

Limits and edge cases

  • Fulfillments are created against fulfillment orders, not order line items. Use the FulfillmentOrderLineItem IDs, not LineItem IDs.
  • Which scope you need depends on who fulfills: the merchant’s own locations, a fulfillment service app, or a third party.
  • trackingInfo also takes numbers and urls lists for shipments with several parcels.
  • Send company exactly as written in Shopify’s list of supported tracking companies so Shopify builds the tracking link; always send url for carriers not on the list.

Questions

How do I add a tracking number to a Shopify order with GraphQL?
Create the fulfillment with fulfillmentCreate and trackingInfo. To change tracking on an existing fulfillment, use fulfillmentTrackingInfoUpdate.
What is a fulfillment order?
The part of an order that one location or fulfillment service ships. An order with items in two warehouses has two fulfillment orders.
Does fulfillmentCreate email the customer?
Only when notifyCustomer is true. The shipping confirmation email then includes the tracking link.
  • Validated against the Admin or Storefront API schema for version 2026-10 on the date shown. Check the version in your request URL.
  • IDs and store addresses in the examples are placeholders. Replace them with your own.
  • Admin API calls need an access token from your app. Never put an Admin API token in a storefront or theme.
  • MIT license. Use the code in your own store or in client work.

Need this built, tested and maintained for your store? See API integrations.

Have something to build? Let’s talk it through.

Taking a limited number of projects at a time. Every brief is read by an engineer, not a salesperson.

Gencer KarakayaShopify Engineer

An engineer reads your brief, and we reply by email.