# 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.

Page: https://lintelagency.com/resources/graphql/fulfillment-with-tracking

## 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.

## Facts

- **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:** 2 November 2026

## 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

```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

```json
{
  "orderId": "gid://shopify/Order/1234567890"
}
```

### fulfillment-orders.response.json

```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

```graphql
mutation ShipWithTracking($fulfillment: FulfillmentInput!) {
  fulfillmentCreate(fulfillment: $fulfillment) {
    fulfillment {
      id
      status
      trackingInfo(first: 5) {
        company
        number
        url
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### fulfillment-create.variables.json

```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

```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": []
    }
  }
}
```

## 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.

## Shopify documentation

- [fulfillmentCreate](https://shopify.dev/docs/api/admin-graphql/latest/mutations/fulfillmentCreate)
- [FulfillmentOrder object](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder)

## Related

- [Edit an order after it was placed](https://lintelagency.com/resources/graphql/order-editing)
- [Aras Kargo Shopify Integration: Rates vs Fulfillment](https://lintelagency.com/journal/how-to-make-aras-kargo-shopify-integration-current-guide)
- [Reliable Shopify webhooks: retries, idempotency, ordering](https://lintelagency.com/journal/reliable-shopify-webhooks)

License: MIT. Free to use in your own store and in client work.
