# Shopify

> Run your Shopify store from a workflow: create and update products, variants and stock levels, search orders and ship them with tracking, raise draft orders and turn them into sales, and keep your customer list up to date.

App · E-Commerce · 20 actions. Web page: https://docs.lodol.com/docs/integrations/shopify

## Actions

### Complete a draft order

Turn a draft order into a real order. Left pending, the order is created unpaid, which is the ordinary case for an invoice the customer still has to settle. Marked as already paid, Shopify records payment without taking any money - what a store does when the money arrived some other way. Returns the order it became.

**Inputs**

- Draft order (`draft_order_id`, text, required): The draft to complete, from a 'Create a draft order' step.
- Leave unpaid (`payment_pending`, true/false): On, the order is created awaiting payment. Off, it is recorded as paid without any money being taken. Default: `true`.

**Outputs**

- `draft_order` (object): The draft, now completed
- `order` (object): The order the draft became

**Example output**

```json
{
  "draft_order": {
    "createdAt": "2026-08-31T09:00:00Z",
    "currencyCode": "USD",
    "customer": {
      "displayName": "Avery Chen",
      "email": "avery@example.com",
      "id": "gid://shopify/Customer/7001234567890"
    },
    "email": "avery@example.com",
    "id": "gid://shopify/DraftOrder/9001234567890",
    "invoiceUrl": "https://example-store.myshopify.com/invoices/abc123",
    "legacyResourceId": "9001234567890",
    "lineItems": {
      "nodes": [
        {
          "id": "gid://shopify/DraftOrderLineItem/95001234567890",
          "originalUnitPriceSet": {
            "shopMoney": {
              "amount": "24.00",
              "currencyCode": "USD"
            }
          },
          "quantity": 2,
          "sku": "TEE-NVY-M",
          "title": "Everyday Cotton T-Shirt - Medium / Navy",
          "variant": {
            "id": "gid://shopify/ProductVariant/44001234567890",
            "title": "Medium / Navy"
          }
        }
      ]
    },
    "name": "#D14",
    "note2": null,
    "order": {
      "id": "gid://shopify/Order/5001234567891",
      "name": "#1043"
    },
    "status": "COMPLETED",
    "subtotalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "tags": [],
    "totalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "updatedAt": "2026-08-31T09:00:00Z"
  },
  "order": {
    "id": "gid://shopify/Order/5001234567891",
    "name": "#1043"
  }
}
```

### Create a customer

Add a customer to the store with their name, email, phone, note and tags. An email address or a phone number is needed - Shopify identifies a customer by one or the other. Returns the new customer with their id.

**Inputs**

- Email (`email`, text): The customer's email address. Required unless a phone number is given.
- First name (`first_name`, text): The customer's first name.
- Last name (`last_name`, text): The customer's last name.
- Phone (`phone`, text): The customer's phone number, in international format. Required unless an email address is given.
- Note (`note`, text): A staff note about the customer.
- Tags (`tags`, text): Tags for the customer, separated by commas.

**Outputs**

- `customer` (object): The new customer

**Example output**

```json
{
  "customer": {
    "amountSpent": {
      "amount": "0.00",
      "currencyCode": "USD"
    },
    "createdAt": "2026-01-19T11:20:00Z",
    "displayName": "Avery Chen",
    "email": "avery@example.com",
    "firstName": "Avery",
    "id": "gid://shopify/Customer/7001234567890",
    "lastName": "Chen",
    "legacyResourceId": "7001234567890",
    "note": null,
    "numberOfOrders": "0",
    "phone": null,
    "state": "ENABLED",
    "tags": [
      "newsletter"
    ],
    "updatedAt": "2026-08-30T14:02:11Z",
    "verifiedEmail": true
  }
}
```

### Create a draft order

Raise a draft order - an invoice or quote that is not a sale yet. Each line is either a catalogue variant and a quantity, or a title and a price for something not in the catalogue, so a workflow can bill for a service as easily as for a product. Returns the draft with the invoice link a customer can pay through.

**Inputs**

- Line items (`line_items`, list, required): What is being billed for. Each item needs either a 'variant_id' and 'quantity', or a 'title', 'price' and 'quantity' for a custom charge.
- Customer (`customer_id`, text): Who to bill, from a 'List customers' step. Leave empty for a draft with no customer attached.
- Email (`email`, text): Where the invoice goes, if it should differ from the customer's own address.
- Note (`note`, text): A staff note on the draft.
- Tags (`tags`, text): Tags for the draft, separated by commas.

**Outputs**

- `draft_order` (object): The draft that was created

**Example output**

```json
{
  "draft_order": {
    "createdAt": "2026-08-31T09:00:00Z",
    "currencyCode": "USD",
    "customer": {
      "displayName": "Avery Chen",
      "email": "avery@example.com",
      "id": "gid://shopify/Customer/7001234567890"
    },
    "email": "avery@example.com",
    "id": "gid://shopify/DraftOrder/9001234567890",
    "invoiceUrl": "https://example-store.myshopify.com/invoices/abc123",
    "legacyResourceId": "9001234567890",
    "lineItems": {
      "nodes": [
        {
          "id": "gid://shopify/DraftOrderLineItem/95001234567890",
          "originalUnitPriceSet": {
            "shopMoney": {
              "amount": "24.00",
              "currencyCode": "USD"
            }
          },
          "quantity": 2,
          "sku": "TEE-NVY-M",
          "title": "Everyday Cotton T-Shirt - Medium / Navy",
          "variant": {
            "id": "gid://shopify/ProductVariant/44001234567890",
            "title": "Medium / Navy"
          }
        }
      ]
    },
    "name": "#D14",
    "note2": null,
    "order": null,
    "status": "OPEN",
    "subtotalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "tags": [],
    "totalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "updatedAt": "2026-08-31T09:00:00Z"
  }
}
```

### Create a product

Add a product to the catalogue with a title, description, type, vendor and tags. It is created as a draft unless the status says otherwise, so a workflow can build it up before anyone can buy it. Returns the new product with its id.

**Inputs**

- Title (`title`, text, required): The product's name, as customers will see it.
- Description (`description_html`, text): The product description. HTML is kept, so headings and lists survive.
- Product type (`product_type`, text): The store's own category for it, such as 'Shirts'.
- Vendor (`vendor`, text): Who makes or supplies it.
- Tags (`tags`, text): Tags for the product, separated by commas.
- Status (`status`, text): Whether it goes live straight away. Defaults to Draft. One of: `ACTIVE` (Active - visible in the online store), `DRAFT` (Draft - not yet published), `ARCHIVED` (Archived - hidden and not for sale). Default: `DRAFT`.
- URL handle (`handle`, text): The slug in the storefront URL. Leave empty to let Shopify build one from the title.

**Outputs**

- `product` (object): The new product

**Example output**

```json
{
  "product": {
    "createdAt": "2026-03-04T10:15:00Z",
    "descriptionHtml": "<p>A soft, midweight cotton tee.</p>",
    "handle": "everyday-cotton-t-shirt",
    "id": "gid://shopify/Product/8001234567890",
    "legacyResourceId": "8001234567890",
    "onlineStoreUrl": "https://example-store.com/products/everyday-cotton-t-shirt",
    "priceRangeV2": {
      "maxVariantPrice": {
        "amount": "29.00",
        "currencyCode": "USD"
      },
      "minVariantPrice": {
        "amount": "24.00",
        "currencyCode": "USD"
      }
    },
    "productType": "Shirts",
    "publishedAt": "2026-03-05T08:00:00Z",
    "status": "DRAFT",
    "tags": [
      "cotton",
      "core range"
    ],
    "title": "Everyday Cotton T-Shirt",
    "totalInventory": 128,
    "updatedAt": "2026-08-28T09:41:00Z",
    "vendor": "Northbound Supply"
  }
}
```

### Delete a customer

Delete a customer record. This cannot be undone. Shopify refuses to delete a customer who has ever placed an order, since the order would then name somebody who does not exist - erasing that customer's personal details is a data request in the Shopify admin instead.

**Inputs**

- Customer (`customer_id`, text, required): The customer to delete, from a 'List customers' step.

**Outputs**

- `deleted_customer_id` (text): The id of the customer that was deleted

**Example output**

```json
{
  "deleted_customer_id": "gid://shopify/Customer/7001234567890"
}
```

### Delete a product

Delete a product and everything on it - its variants, its images and its inventory. This cannot be undone. A product that has ever been ordered is better archived than deleted, with 'Update a product' and the Archived status, because deleting it leaves past orders naming something that no longer exists.

**Inputs**

- Product (`product_id`, text, required): The product to act on. Paste the number from its admin URL (/products/8001234567890) or use the id from a 'List products' step.

**Outputs**

- `deleted_product_id` (text): The id of the product that was deleted

**Example output**

```json
{
  "deleted_product_id": "gid://shopify/Product/8001234567890"
}
```

### Fulfill an order

Mark an order shipped, with a tracking number and carrier if there is one, and email the customer unless told not to. Point it at an order to ship everything still outstanding, or at one fulfillment order to ship a single location's part of it.

**Inputs**

- Order (`order_id`, text): The order to ship. Everything still outstanding on it is fulfilled. Leave empty if naming a fulfillment order below instead.
- Fulfillment order (`fulfillment_order_id`, text): Ship only one part of an order. Leave empty unless the store ships an order from more than one location and only one of them is going out now; the id comes from the order in the Shopify admin.
- Tracking number (`tracking_number`, text): The carrier's tracking number for the parcel.
- Carrier (`tracking_company`, text): Who is carrying it, e.g. 'Canada Post' or 'UPS'. Shopify builds the tracking link from a name it recognises.
- Tracking link (`tracking_url`, text): A tracking URL, for a carrier Shopify does not recognise.
- Email the customer (`notify_customer`, true/false): Whether Shopify sends its shipping confirmation email. On by default. Default: `true`.

**Outputs**

- `fulfillment` (object): The shipment that was created

**Example output**

```json
{
  "fulfillment": {
    "createdAt": "2026-08-31T08:30:00Z",
    "id": "gid://shopify/Fulfillment/40123456789",
    "order": {
      "id": "gid://shopify/Order/5001234567890",
      "name": "#1042"
    },
    "status": "SUCCESS",
    "totalQuantity": 2,
    "trackingInfo": [
      {
        "company": "Canada Post",
        "number": "1Z999AA10123456784",
        "url": "https://www.canadapost-postescanada.ca/track-reperage/en#/details/1Z999AA10123456784"
      }
    ],
    "updatedAt": "2026-08-31T08:30:00Z"
  }
}
```

### Get a product

Read one product in full: its description, status, vendor, tags and price range, every one of its variants with their SKUs, prices and stock, the options that distinguish them, and the collections the product belongs to.

**Inputs**

- Product (`product_id`, text, required): The product to act on. Paste the number from its admin URL (/products/8001234567890) or use the id from a 'List products' step.

**Outputs**

- `product` (object): The product

**Example output**

```json
{
  "product": {
    "collections": {
      "nodes": [
        {
          "handle": "new-arrivals",
          "id": "gid://shopify/Collection/300123456789",
          "title": "New arrivals"
        }
      ]
    },
    "createdAt": "2026-03-04T10:15:00Z",
    "descriptionHtml": "<p>A soft, midweight cotton tee.</p>",
    "handle": "everyday-cotton-t-shirt",
    "id": "gid://shopify/Product/8001234567890",
    "legacyResourceId": "8001234567890",
    "onlineStoreUrl": "https://example-store.com/products/everyday-cotton-t-shirt",
    "priceRangeV2": {
      "maxVariantPrice": {
        "amount": "29.00",
        "currencyCode": "USD"
      },
      "minVariantPrice": {
        "amount": "24.00",
        "currencyCode": "USD"
      }
    },
    "productType": "Shirts",
    "publishedAt": "2026-03-05T08:00:00Z",
    "status": "ACTIVE",
    "tags": [
      "cotton",
      "core range"
    ],
    "title": "Everyday Cotton T-Shirt",
    "totalInventory": 128,
    "updatedAt": "2026-08-28T09:41:00Z",
    "variants": {
      "nodes": [
        {
          "availableForSale": true,
          "barcode": "0123456789012",
          "compareAtPrice": "32.00",
          "displayName": "Everyday Cotton T-Shirt - Medium / Navy",
          "id": "gid://shopify/ProductVariant/44001234567890",
          "inventoryItem": {
            "id": "gid://shopify/InventoryItem/45001234567890",
            "tracked": true
          },
          "inventoryQuantity": 42,
          "legacyResourceId": "44001234567890",
          "position": 2,
          "price": "24.00",
          "product": {
            "handle": "everyday-cotton-t-shirt",
            "id": "gid://shopify/Product/8001234567890",
            "status": "ACTIVE",
            "title": "Everyday Cotton T-Shirt"
          },
          "selectedOptions": [
            {
              "name": "Size",
              "value": "Medium"
            },
            {
              "name": "Colour",
              "value": "Navy"
            }
          ],
          "sku": "TEE-NVY-M",
          "taxable": true,
          "title": "Medium / Navy"
        }
      ]
    },
    "vendor": "Northbound Supply"
  }
}
```

### Get an order

Read one order in full: every line item with its quantity, SKU and price, the totals and what has been refunded, the customer and both addresses, the shipping method, and any shipments already made against it with their tracking.

**Inputs**

- Order (`order_id`, text, required): The order to act on. Paste the number from its admin URL (/orders/5001234567890) or use the id from a 'List orders' step. This is not the order number customers see ('#1001').

**Outputs**

- `order` (object): The order

**Example output**

```json
{
  "order": {
    "cancelledAt": null,
    "closedAt": null,
    "confirmed": true,
    "createdAt": "2026-08-30T14:02:11Z",
    "currencyCode": "USD",
    "customer": {
      "displayName": "Avery Chen",
      "email": "avery@example.com",
      "id": "gid://shopify/Customer/7001234567890",
      "phone": null
    },
    "displayFinancialStatus": "PAID",
    "displayFulfillmentStatus": "UNFULFILLED",
    "email": "avery@example.com",
    "fulfillments": [],
    "id": "gid://shopify/Order/5001234567890",
    "legacyResourceId": "5001234567890",
    "lineItems": {
      "nodes": [
        {
          "currentQuantity": 2,
          "discountedTotalSet": {
            "shopMoney": {
              "amount": "48.00",
              "currencyCode": "USD"
            }
          },
          "id": "gid://shopify/LineItem/130123456789",
          "originalTotalSet": {
            "shopMoney": {
              "amount": "48.00",
              "currencyCode": "USD"
            }
          },
          "quantity": 2,
          "sku": "TEE-NVY-M",
          "title": "Everyday Cotton T-Shirt",
          "variant": {
            "id": "gid://shopify/ProductVariant/44001234567890",
            "sku": "TEE-NVY-M",
            "title": "Medium / Navy"
          },
          "vendor": "Northbound Supply"
        }
      ]
    },
    "name": "#1042",
    "note": null,
    "phone": null,
    "processedAt": "2026-08-30T14:02:11Z",
    "shippingAddress": {
      "address1": "418 Bathurst St",
      "city": "Toronto",
      "country": "Canada",
      "countryCodeV2": "CA",
      "firstName": "Avery",
      "lastName": "Chen",
      "province": "Ontario",
      "provinceCode": "ON",
      "zip": "M5T 2S5"
    },
    "shippingLine": {
      "carrierIdentifier": null,
      "title": "Standard"
    },
    "subtotalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "tags": [
      "wholesale"
    ],
    "test": false,
    "totalPriceSet": {
      "shopMoney": {
        "amount": "54.60",
        "currencyCode": "USD"
      }
    },
    "totalRefundedSet": {
      "shopMoney": {
        "amount": "0.00",
        "currencyCode": "USD"
      }
    },
    "totalShippingPriceSet": {
      "shopMoney": {
        "amount": "6.60",
        "currencyCode": "USD"
      }
    },
    "totalTaxSet": {
      "shopMoney": {
        "amount": "0.00",
        "currencyCode": "USD"
      }
    },
    "updatedAt": "2026-08-30T14:05:40Z"
  }
}
```

### Get store details

Read the store itself: its name and domains, contact email, currency, timezone, weight unit, billing address and which Shopify plan it is on, plus every location it holds stock at. Takes no input, so it is the cheapest way for a workflow to prove the connection works before it changes anything.

**Inputs**: None.

**Outputs**

- `location_count` (number): How many locations it has
- `locations` (list): Where the store holds stock
- `shop` (object): The store

**Example output**

```json
{
  "location_count": 1,
  "locations": [
    {
      "address": {
        "formatted": [
          "12 Sterling Rd",
          "Toronto ON M6R 2B2"
        ]
      },
      "id": "gid://shopify/Location/70123456789",
      "isActive": true,
      "name": "Main warehouse",
      "shipsInventory": true
    }
  ],
  "shop": {
    "billingAddress": {
      "city": "Toronto",
      "country": "Canada",
      "countryCodeV2": "CA",
      "province": "Ontario",
      "zip": "M5T 2S5"
    },
    "contactEmail": "hello@example.com",
    "createdAt": "2025-11-02T16:44:00Z",
    "currencyCode": "USD",
    "email": "owner@example.com",
    "ianaTimezone": "America/Toronto",
    "id": "gid://shopify/Shop/60123456789",
    "myshopifyDomain": "example-store.myshopify.com",
    "name": "Northbound Supply",
    "plan": {
      "displayName": "Developer Preview",
      "partnerDevelopment": true,
      "shopifyPlus": false
    },
    "primaryDomain": {
      "host": "example-store.com",
      "sslEnabled": true,
      "url": "https://example-store.com"
    },
    "weightUnit": "KILOGRAMS"
  }
}
```

### List customers

Search the store's customers by name, email or tag, and by when they were created. Returns each with their contact details, tags, account state, how many orders they have placed, what they have spent and their default address.

**Inputs**

- Search (`search`, text): Words to look for in a customer's name, email, phone or address.
- Email (`email`, text): Only return the customer with this email address.
- Tag (`tag`, text): Only include customers carrying this tag.
- Created on or after (`created_after`, date): Only include customers created on or after this date.
- Created on or before (`created_before`, date): Only include customers created on or before this date.
- Sort by (`sort_key`, text): What to order the results by. One of: `CREATED_AT` (Date created), `UPDATED_AT` (Date last updated), `NAME`. Default: `CREATED_AT`.
- Sort direction (`sort_direction`, text): Which way to order the sort chosen above. One of: `desc` (Newest or highest first), `asc` (Oldest or lowest first). Default: `desc`.
- Number of customers (`limit`, number): How many customers to return, 1-250 (Shopify's maximum page size). Defaults to 25. From 1 to 250. Default: `25`.
- Continue from (`cursor`, text): The 'next_cursor' a previous run reported, to read the next page. Leave empty to start from the beginning.

**Outputs**

- `count` (number): How many were returned on this page
- `customers` (list): The customers that matched
- `has_more` (true/false): Whether a page follows
- `next_cursor` (text): Pass back as 'cursor' to read the next page

**Example output**

```json
{
  "count": 1,
  "customers": [
    {
      "amountSpent": {
        "amount": "163.80",
        "currencyCode": "USD"
      },
      "createdAt": "2026-01-19T11:20:00Z",
      "displayName": "Avery Chen",
      "email": "avery@example.com",
      "firstName": "Avery",
      "id": "gid://shopify/Customer/7001234567890",
      "lastName": "Chen",
      "legacyResourceId": "7001234567890",
      "note": null,
      "numberOfOrders": "3",
      "phone": null,
      "state": "ENABLED",
      "tags": [
        "newsletter"
      ],
      "updatedAt": "2026-08-30T14:02:11Z",
      "verifiedEmail": true
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

### List inventory at a location

Read what is in stock at one of the store's locations, item by item. Each line reports every quantity Shopify tracks - available, committed to an order, incoming, on hand and reserved - alongside the SKU, the variant and the product it belongs to, and the inventory item id needed to change it.

**Inputs**

- Location (`location_id`, text, required): Which of the store's locations to read or change stock at.
- Number of items (`limit`, number): How many items to return, 1-250 (Shopify's maximum page size). Defaults to 25. From 1 to 250. Default: `25`.
- Continue from (`cursor`, text): The 'next_cursor' a previous run reported, to read the next page. Leave empty to start from the beginning.

**Outputs**

- `count` (number): How many were returned on this page
- `has_more` (true/false): Whether a page follows
- `inventory_levels` (list): Stock lines at this location
- `location` (object): The location that was read
- `next_cursor` (text): Pass back as 'cursor' to read the next page

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "inventory_levels": [
    {
      "available": 42,
      "id": "gid://shopify/InventoryLevel/120987654321",
      "item": {
        "id": "gid://shopify/InventoryItem/45001234567890",
        "sku": "TEE-NVY-M",
        "tracked": true,
        "variant": {
          "id": "gid://shopify/ProductVariant/44001234567890",
          "product": {
            "handle": "everyday-cotton-t-shirt",
            "id": "gid://shopify/Product/8001234567890",
            "title": "Everyday Cotton T-Shirt"
          },
          "title": "Medium / Navy"
        }
      },
      "location": {
        "id": "gid://shopify/Location/70123456789",
        "name": "Main warehouse"
      },
      "quantities": [
        {
          "name": "available",
          "quantity": 42
        },
        {
          "name": "committed",
          "quantity": 3
        },
        {
          "name": "incoming",
          "quantity": 24
        },
        {
          "name": "on_hand",
          "quantity": 45
        },
        {
          "name": "reserved",
          "quantity": 0
        }
      ],
      "updatedAt": "2026-08-30T09:12:00Z"
    }
  ],
  "location": {
    "id": "gid://shopify/Location/70123456789",
    "name": "Main warehouse"
  },
  "next_cursor": null
}
```

### List orders

Search the store's orders. Filter by payment status, shipping status, customer email, and when they were placed or last changed. Returns each order with its number, totals, payment and fulfillment status, customer, and shipping and billing addresses. Filtering on 'created on or after' is how a scheduled workflow sees only what is new.

**Inputs**

- Search (`search`, text): Words to look for anywhere on the order - a customer name, an order number, a SKU.
- Payment status (`financial_statuses`, list): Only include orders in these payment states. Choosing several matches any of them. For a sales alert or report, choose Paid and Partially refunded so unpaid, voided and fully refunded orders are not counted. One or more of: `paid`, `pending`, `authorized`, `partially_paid` (Partially paid), `partially_refunded` (Partially refunded), `refunded`, `voided`, `expired`.
- Shipping status (`fulfillment_statuses`, list): Only include orders in these shipping states. 'Unfulfilled' is the queue of what still has to go out. One or more of: `unfulfilled`, `partial` (Partially fulfilled), `fulfilled`, `scheduled`, `on_hold` (On hold).
- Placed on or after (`created_after`, date): Only include orders placed on or after this date.
- Placed on or before (`created_before`, date): Only include orders placed on or before this date.
- Changed on or after (`updated_after`, date): Only include orders that changed on or after this date, which catches an old order that was just paid or shipped.
- Customer email (`customer_email`, text): Only include orders placed with this email address.
- Sort by (`sort_key`, text): What to order the results by. One of: `CREATED_AT` (Date created), `UPDATED_AT` (Date last updated), `PROCESSED_AT` (Date processed), `ORDER_NUMBER` (Order number), `TOTAL_PRICE` (Total price). Default: `CREATED_AT`.
- Sort direction (`sort_direction`, text): Which way to order the sort chosen above. One of: `desc` (Newest or highest first), `asc` (Oldest or lowest first). Default: `desc`.
- Number of orders (`limit`, number): How many orders to return, 1-250 (Shopify's maximum page size). Defaults to 25. From 1 to 250. Default: `25`.
- Continue from (`cursor`, text): The 'next_cursor' a previous run reported, to read the next page. Leave empty to start from the beginning.

**Outputs**

- `count` (number): How many were returned on this page
- `has_more` (true/false): Whether a page follows
- `next_cursor` (text): Pass back as 'cursor' to read the next page
- `orders` (list): The orders that matched

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "next_cursor": null,
  "orders": [
    {
      "cancelledAt": null,
      "closedAt": null,
      "confirmed": true,
      "createdAt": "2026-08-30T14:02:11Z",
      "currencyCode": "USD",
      "customer": {
        "displayName": "Avery Chen",
        "email": "avery@example.com",
        "id": "gid://shopify/Customer/7001234567890",
        "phone": null
      },
      "displayFinancialStatus": "PAID",
      "displayFulfillmentStatus": "UNFULFILLED",
      "email": "avery@example.com",
      "id": "gid://shopify/Order/5001234567890",
      "legacyResourceId": "5001234567890",
      "name": "#1042",
      "note": null,
      "phone": null,
      "processedAt": "2026-08-30T14:02:11Z",
      "shippingAddress": {
        "address1": "418 Bathurst St",
        "city": "Toronto",
        "country": "Canada",
        "countryCodeV2": "CA",
        "firstName": "Avery",
        "lastName": "Chen",
        "province": "Ontario",
        "provinceCode": "ON",
        "zip": "M5T 2S5"
      },
      "subtotalPriceSet": {
        "shopMoney": {
          "amount": "48.00",
          "currencyCode": "USD"
        }
      },
      "tags": [
        "wholesale"
      ],
      "test": false,
      "totalPriceSet": {
        "shopMoney": {
          "amount": "54.60",
          "currencyCode": "USD"
        }
      },
      "totalRefundedSet": {
        "shopMoney": {
          "amount": "0.00",
          "currencyCode": "USD"
        }
      },
      "totalShippingPriceSet": {
        "shopMoney": {
          "amount": "6.60",
          "currencyCode": "USD"
        }
      },
      "totalTaxSet": {
        "shopMoney": {
          "amount": "0.00",
          "currencyCode": "USD"
        }
      },
      "updatedAt": "2026-08-30T14:05:40Z"
    }
  ]
}
```

### List product variants

List variants across the store, or the variants of one product. A variant is what actually carries a price, a SKU and stock, so this is the step that finds the id a price change or a stock update needs - including the inventory item id 'Set inventory quantity' takes.

**Inputs**

- Product (`product_id`, text): Only list variants of this product. Leave empty to search across the whole catalogue.
- Search (`search`, text): Words to look for in the variant or product name.
- SKU (`sku`, text): Only return the variant with this exact SKU.
- Number of variants (`limit`, number): How many variants to return, 1-250 (Shopify's maximum page size). Defaults to 25. From 1 to 250. Default: `25`.
- Continue from (`cursor`, text): The 'next_cursor' a previous run reported, to read the next page. Leave empty to start from the beginning.

**Outputs**

- `count` (number): How many were returned on this page
- `has_more` (true/false): Whether a page follows
- `next_cursor` (text): Pass back as 'cursor' to read the next page
- `variants` (list): The variants that matched

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "next_cursor": null,
  "variants": [
    {
      "availableForSale": true,
      "barcode": "0123456789012",
      "compareAtPrice": "32.00",
      "displayName": "Everyday Cotton T-Shirt - Medium / Navy",
      "id": "gid://shopify/ProductVariant/44001234567890",
      "inventoryItem": {
        "id": "gid://shopify/InventoryItem/45001234567890",
        "tracked": true
      },
      "inventoryQuantity": 42,
      "legacyResourceId": "44001234567890",
      "position": 2,
      "price": "24.00",
      "product": {
        "handle": "everyday-cotton-t-shirt",
        "id": "gid://shopify/Product/8001234567890",
        "status": "ACTIVE",
        "title": "Everyday Cotton T-Shirt"
      },
      "selectedOptions": [
        {
          "name": "Size",
          "value": "Medium"
        },
        {
          "name": "Colour",
          "value": "Navy"
        }
      ],
      "sku": "TEE-NVY-M",
      "taxable": true,
      "title": "Medium / Navy"
    }
  ]
}
```

### List products

Search the store's products. Filter by words in the title or description, by status, product type, vendor or tag, and by when they were created. Returns each product with its id, handle, status, description, vendor, tags, total stock, price range and storefront link. With no filters at all this is the whole catalogue, newest change first.

**Inputs**

- Search (`search`, text): Words to look for in the product's title, description, vendor or tags. Leave empty to match everything.
- Status (`statuses`, list): Only include products in these states. Choosing several matches any of them; leave empty for all. One or more of: `ACTIVE` (Active - visible in the online store), `DRAFT` (Draft - not yet published), `ARCHIVED` (Archived - hidden and not for sale).
- Product type (`product_type`, text): Only include products of this type.
- Vendor (`vendor`, text): Only include products from this vendor or brand.
- Tag (`tag`, text): Only include products carrying this tag.
- Created on or after (`created_after`, date): Only include products created on or after this date. Leave empty for no lower bound.
- Created on or before (`created_before`, date): Only include products created on or before this date. Leave empty for no upper bound.
- Sort by (`sort_key`, text): What to order the results by. One of: `TITLE`, `CREATED_AT` (Date created), `UPDATED_AT` (Date last updated), `INVENTORY_TOTAL` (Total inventory), `PRODUCT_TYPE` (Product type), `VENDOR`. Default: `UPDATED_AT`.
- Sort direction (`sort_direction`, text): Which way to order the sort chosen above. One of: `desc` (Newest or highest first), `asc` (Oldest or lowest first). Default: `desc`.
- Number of products (`limit`, number): How many products to return, 1-250 (Shopify's maximum page size). Defaults to 25. From 1 to 250. Default: `25`.
- Continue from (`cursor`, text): The 'next_cursor' a previous run reported, to read the next page. Leave empty to start from the beginning.

**Outputs**

- `count` (number): How many were returned on this page
- `has_more` (true/false): Whether a page follows
- `next_cursor` (text): Pass back as 'cursor' to read the next page
- `products` (list): The products that matched

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "next_cursor": null,
  "products": [
    {
      "createdAt": "2026-03-04T10:15:00Z",
      "descriptionHtml": "<p>A soft, midweight cotton tee.</p>",
      "handle": "everyday-cotton-t-shirt",
      "id": "gid://shopify/Product/8001234567890",
      "legacyResourceId": "8001234567890",
      "onlineStoreUrl": "https://example-store.com/products/everyday-cotton-t-shirt",
      "priceRangeV2": {
        "maxVariantPrice": {
          "amount": "29.00",
          "currencyCode": "USD"
        },
        "minVariantPrice": {
          "amount": "24.00",
          "currencyCode": "USD"
        }
      },
      "productType": "Shirts",
      "publishedAt": "2026-03-05T08:00:00Z",
      "status": "ACTIVE",
      "tags": [
        "cotton",
        "core range"
      ],
      "title": "Everyday Cotton T-Shirt",
      "totalInventory": 128,
      "updatedAt": "2026-08-28T09:41:00Z",
      "vendor": "Northbound Supply"
    }
  ]
}
```

### Set inventory quantity

Set how many of one item are in stock at one location, to an exact number rather than by adding or subtracting. That is what a workflow syncing from a supplier feed or a spreadsheet wants: running it twice with the same number changes nothing the second time. Takes the inventory item id from 'List product variants' or 'List inventory at a location'.

**Inputs**

- Inventory item (`inventory_item_id`, text, required): The item to set stock for. This is the variant's 'inventoryItem.id', not the variant id - both list steps return it.
- Location (`location_id`, text, required): Which of the store's locations to read or change stock at.
- Quantity (`quantity`, number, required): How many there are now. This replaces the current count rather than adding to it. From 0 to 1000000.
- Which count (`quantity_name`, text): Which quantity to set. 'Available' is what can still be sold; 'On hand' is everything physically there. The other counts Shopify tracks are worked out from orders and transfers and cannot be set directly. One of: `available` (Available - on hand and not committed to an order), `on_hand` (On hand - everything physically at the location). Default: `available`.
- Reason (`reason`, text): Why the count changed, recorded in the store's inventory history. Defaults to 'correction'.

**Outputs**

- `adjustment` (object): What the change did

**Example output**

```json
{
  "adjustment": {
    "changes": [
      {
        "delta": 8,
        "item": {
          "id": "gid://shopify/InventoryItem/45001234567890",
          "sku": "TEE-NVY-M"
        },
        "name": "available",
        "quantityAfterChange": 50
      }
    ],
    "createdAt": "2026-08-31T10:05:00Z",
    "id": "gid://shopify/InventoryAdjustmentGroup/110123456789",
    "reason": "correction"
  }
}
```

### Update a customer

Change a customer's name, email, phone, note or tags. Only the fields filled in are touched. Tagging is how a workflow segments customers for a later step to act on.

**Inputs**

- Customer (`customer_id`, text, required): The customer to change, from a 'List customers' step.
- Email (`email`, text): A new email address.
- First name (`first_name`, text): A new first name.
- Last name (`last_name`, text): A new last name.
- Phone (`phone`, text): A new phone number, in international format.
- Note (`note`, text): A staff note. Replaces any existing note.
- Tags (`tags`, text): Tags, separated by commas. This replaces the existing tags rather than adding to them, so include the ones to keep.

**Outputs**

- `customer` (object): The customer as they now stand

**Example output**

```json
{
  "customer": {
    "amountSpent": {
      "amount": "163.80",
      "currencyCode": "USD"
    },
    "createdAt": "2026-01-19T11:20:00Z",
    "displayName": "Avery Chen",
    "email": "avery@example.com",
    "firstName": "Avery",
    "id": "gid://shopify/Customer/7001234567890",
    "lastName": "Chen",
    "legacyResourceId": "7001234567890",
    "note": null,
    "numberOfOrders": "3",
    "phone": null,
    "state": "ENABLED",
    "tags": [
      "newsletter",
      "vip"
    ],
    "updatedAt": "2026-08-30T14:02:11Z",
    "verifiedEmail": true
  }
}
```

### Update a product

Change a product's title, description, type, vendor, tags, URL handle or status. Only the fields filled in are touched, so this is safe to point at a product a person also edits. Setting the status to Active is how a draft goes on sale.

**Inputs**

- Product (`product_id`, text, required): The product to act on. Paste the number from its admin URL (/products/8001234567890) or use the id from a 'List products' step.
- Title (`title`, text): A new name. Leave empty to keep the current one.
- Description (`description_html`, text): A new description, as HTML. Leave empty to keep the current one.
- Product type (`product_type`, text): A new type. Leave empty to keep the current one.
- Vendor (`vendor`, text): A new vendor. Leave empty to keep the current one.
- Tags (`tags`, text): Tags, separated by commas. This replaces the existing tags rather than adding to them, so include the ones to keep.
- Status (`status`, text): A new status. Leave empty to keep the current one. One of: `ACTIVE` (Active - visible in the online store), `DRAFT` (Draft - not yet published), `ARCHIVED` (Archived - hidden and not for sale).
- URL handle (`handle`, text): A new URL slug. Changing this changes the product's storefront address.

**Outputs**

- `product` (object): The product as it now stands

**Example output**

```json
{
  "product": {
    "createdAt": "2026-03-04T10:15:00Z",
    "descriptionHtml": "<p>A soft, midweight cotton tee.</p>",
    "handle": "everyday-cotton-t-shirt",
    "id": "gid://shopify/Product/8001234567890",
    "legacyResourceId": "8001234567890",
    "onlineStoreUrl": "https://example-store.com/products/everyday-cotton-t-shirt",
    "priceRangeV2": {
      "maxVariantPrice": {
        "amount": "29.00",
        "currencyCode": "USD"
      },
      "minVariantPrice": {
        "amount": "24.00",
        "currencyCode": "USD"
      }
    },
    "productType": "Shirts",
    "publishedAt": "2026-03-05T08:00:00Z",
    "status": "ACTIVE",
    "tags": [
      "cotton",
      "core range"
    ],
    "title": "Everyday Cotton T-Shirt",
    "totalInventory": 128,
    "updatedAt": "2026-08-28T09:41:00Z",
    "vendor": "Northbound Supply"
  }
}
```

### Update a product variant

Change one variant's price, compare-at price, SKU, barcode or whether it is taxable. Only the fields filled in are touched. The product is asked for as well as the variant because Shopify only updates a variant through its product.

**Inputs**

- Product (`product_id`, text, required): The product to act on. Paste the number from its admin URL (/products/8001234567890) or use the id from a 'List products' step.
- Variant (`variant_id`, text, required): The variant to change, from a 'List product variants' step.
- Price (`price`, text): The new selling price, in the store's currency, without a currency symbol.
- Compare-at price (`compare_at_price`, text): The struck-through 'was' price shown next to the selling price.
- SKU (`sku`, text): A new stock keeping unit for the variant.
- Barcode (`barcode`, text): A new barcode (ISBN, UPC or GTIN).
- Charge tax (`taxable`, true/false): Whether tax is charged on this variant.
- Track inventory (`track_inventory`, true/false): Whether Shopify counts stock for this variant. Turn it off for something that never runs out, such as a service or a made-to-order item, and it can always be bought regardless of stock.

**Outputs**

- `variant` (object): The variant as it now stands

**Example output**

```json
{
  "variant": {
    "availableForSale": true,
    "barcode": "0123456789012",
    "compareAtPrice": "32.00",
    "displayName": "Everyday Cotton T-Shirt - Medium / Navy",
    "id": "gid://shopify/ProductVariant/44001234567890",
    "inventoryItem": {
      "id": "gid://shopify/InventoryItem/45001234567890",
      "tracked": true
    },
    "inventoryQuantity": 42,
    "legacyResourceId": "44001234567890",
    "position": 2,
    "price": "24.00",
    "product": {
      "handle": "everyday-cotton-t-shirt",
      "id": "gid://shopify/Product/8001234567890",
      "status": "ACTIVE",
      "title": "Everyday Cotton T-Shirt"
    },
    "selectedOptions": [
      {
        "name": "Size",
        "value": "Medium"
      },
      {
        "name": "Colour",
        "value": "Navy"
      }
    ],
    "sku": "TEE-NVY-M",
    "taxable": true,
    "title": "Medium / Navy"
  }
}
```

### Update an order

Change an order's staff note, tags or contact email. Tagging is how a workflow marks an order it has already handled, so the next run can skip it. An order's money and line items are not editable this way - Shopify does not allow it.

**Inputs**

- Order (`order_id`, text, required): The order to act on. Paste the number from its admin URL (/orders/5001234567890) or use the id from a 'List orders' step. This is not the order number customers see ('#1001').
- Note (`note`, text): A staff note on the order. Replaces any existing note.
- Tags (`tags`, text): Tags, separated by commas. This replaces the existing tags rather than adding to them, so include the ones to keep.
- Contact email (`email`, text): A new contact email address for the order.

**Outputs**

- `order` (object): The order as it now stands

**Example output**

```json
{
  "order": {
    "cancelledAt": null,
    "closedAt": null,
    "confirmed": true,
    "createdAt": "2026-08-30T14:02:11Z",
    "currencyCode": "USD",
    "customer": {
      "displayName": "Avery Chen",
      "email": "avery@example.com",
      "id": "gid://shopify/Customer/7001234567890",
      "phone": null
    },
    "displayFinancialStatus": "PAID",
    "displayFulfillmentStatus": "UNFULFILLED",
    "email": "avery@example.com",
    "id": "gid://shopify/Order/5001234567890",
    "legacyResourceId": "5001234567890",
    "name": "#1042",
    "note": null,
    "phone": null,
    "processedAt": "2026-08-30T14:02:11Z",
    "shippingAddress": {
      "address1": "418 Bathurst St",
      "city": "Toronto",
      "country": "Canada",
      "countryCodeV2": "CA",
      "firstName": "Avery",
      "lastName": "Chen",
      "province": "Ontario",
      "provinceCode": "ON",
      "zip": "M5T 2S5"
    },
    "subtotalPriceSet": {
      "shopMoney": {
        "amount": "48.00",
        "currencyCode": "USD"
      }
    },
    "tags": [
      "wholesale",
      "reviewed"
    ],
    "test": false,
    "totalPriceSet": {
      "shopMoney": {
        "amount": "54.60",
        "currencyCode": "USD"
      }
    },
    "totalRefundedSet": {
      "shopMoney": {
        "amount": "0.00",
        "currencyCode": "USD"
      }
    },
    "totalShippingPriceSet": {
      "shopMoney": {
        "amount": "6.60",
        "currencyCode": "USD"
      }
    },
    "totalTaxSet": {
      "shopMoney": {
        "amount": "0.00",
        "currencyCode": "USD"
      }
    },
    "updatedAt": "2026-08-30T14:05:40Z"
  }
}
```
