A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Shopify API is how an app or AI agent works with a Shopify store through its Admin API: listing and updating products, reading and editing orders, managing customers, and adjusting inventory across locations. Access is granted through an access token obtained when a merchant installs the app, and the token carries OAuth scopes, paired as read and write per area, that set which parts of the store a call can read or change. Shopify ships a new dated version of the API each quarter and supports each for at least a year, and a change in the store can emit an event to a registered endpoint.
How an app or AI agent connects to Shopify determines what it can reach. There is a route for making calls, a route for receiving events, and hosted servers that expose Shopify to AI agents, and each is governed by the access token behind it and the scopes that token carries.
The primary Admin API is GraphQL. An app sends every read and write as a query or a mutation to a single store endpoint and asks for exactly the fields it needs back. A request authenticates with an access token in the X-Shopify-Access-Token header, and the version is part of the request path. The REST Admin API still exists but is legacy and no longer receiving new features.
Shopify POSTs a payload to an HTTPS endpoint when a subscribed topic fires, like an order being created. The receiver verifies the X-Shopify-Hmac-Sha256 header against the app's client secret to confirm the request came from Shopify. Subscriptions are created in the app config or through the webhookSubscriptionCreate mutation.
Shopify's hosted Storefront MCP server lets an AI agent handle shopping tasks for a store: searching the catalog, managing carts, and reading store policies, so a shopping assistant can help a customer through to checkout. Shopify also ships first-party Customer Account and Checkout MCP servers for their domains. These are storefront and shopper facing, not the Admin API.
Shopify's Dev MCP server, part of the open-sourced Shopify AI Toolkit, runs locally and exposes Shopify's documentation and GraphQL schema to an AI coding tool, so an agent can look up and validate API calls. It is a developer aid for building against the API, not a runtime path to store data, and runs without authentication.
A public app installed by a merchant uses the OAuth 2.0 authorization-code flow to request scopes and receive an access token for that store. The token is sent in the X-Shopify-Access-Token header on every Admin API call and reaches only the scopes the merchant approved.
A custom app built for a single store is given an Admin API access token directly in the Shopify admin, with scopes selected at setup. It calls the Admin API the same way, with the token in the X-Shopify-Access-Token header, and skips the OAuth flow.
An embedded app running inside the Shopify admin uses short-lived session tokens to identify the merchant, then exchanges them for an access token through token exchange. This avoids long-lived tokens in the browser.
The Admin API is split into areas an agent can act on, like products, orders, customers, inventory, fulfillment, and draft orders. Each area has its own operations and its own access scope, and a write in some areas changes a live storefront or a real order.
Operations for reading and writing products, their variants, and product media.
Operations for reading and updating orders placed in a store.
Operations for reading and writing customer records.
Operations for reading and adjusting stock levels across locations.
Operations for reading fulfillment orders and creating fulfillments.
Operations for building draft orders and turning them into real orders.
Operations for grouping products into collections.
Operations for reading and setting custom metafield data on records.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
Products & variantsOperations for reading and writing products, their variants, and product media.5 | ||||||
| POST | query products | List products in the store, filtered and paginated through a connection. | read | read_products | Current | |
Read-only. The products connection is part of the QueryRoot. Acts onProduct Permission (capability) read_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | query product | Fetch a single product by id, including its variants and media. | read | read_products | Current | |
Read-only. Acts onProduct Permission (capability) read_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation productCreate | Create a product with attributes such as title, description, vendor, and media. | write | write_products | Current | |
A product is created in an unpublished state, then made available with a separate publish step. Acts onProduct Permission (capability) write_productsVersionAvailable since the API’s base version Webhook event products-createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation productUpdate | Update an existing product's attributes. | write | write_products | Current | |
A core catalog write that a storefront reflects. Acts onProduct Permission (capability) write_productsVersionAvailable since the API’s base version Webhook event products-updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation productVariantsBulkCreate | Create multiple variants for a single product in one operation, such as sizes or colors. | write | write_products | Current | |
Adds variants in bulk to an existing product. Acts onProductVariant Permission (capability) write_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
OrdersOperations for reading and updating orders placed in a store.4 | ||||||
| POST | query orders | List orders in the store, filtered and paginated through a connection. | read | read_orders | Current | |
read_orders returns orders from the last 60 days; read_all_orders, which needs Shopify approval, removes that window. Acts onOrder Permission (capability) read_ordersVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | query order | Fetch a single order by id, including line items, transactions, and fulfillments. | read | read_orders | Current | |
Reading customer details on an order also needs protected customer data approval. Acts onOrder Permission (capability) read_ordersVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation orderUpdate | Update an order's attributes, like its email, shipping address, tags, or metafields. | write | write_orders | Current | |
A write to a real order. Acts onOrder Permission (capability) write_ordersVersionAvailable since the API’s base version Webhook event orders-updatedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation orderCreate | Create an order directly, for orders that originate outside the standard checkout. | write | write_orders | Current | |
Creates a real order in the store. Acts onOrder Permission (capability) write_ordersVersionAvailable since the API’s base version Webhook event orders-createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
CustomersOperations for reading and writing customer records.3 | ||||||
| POST | query customers | List customers in the store, filtered and paginated through a connection. | read | read_customers | Current | |
Customer fields like name, email, and address are protected customer data and need Shopify approval. Acts onCustomer Permission (capability) read_customersVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation customerCreate | Create a customer record from name, email, and address details. | write | write_customers | Current | |
Writes a real customer record; the input is protected customer data. Acts onCustomer Permission (capability) write_customersVersionAvailable since the API’s base version Webhook event customers-createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation customerUpdate | Update an existing customer's details. | write | write_customers | Current | |
A write to a real customer record. Acts onCustomer Permission (capability) write_customersVersionAvailable since the API’s base version Webhook event customers-updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
InventoryOperations for reading and adjusting stock levels across locations.2 | ||||||
| POST | query inventoryItem | Read an inventory item and its levels across locations. | read | read_inventory | Current | |
Read-only. Acts onInventoryItem Permission (capability) read_inventoryVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation inventoryAdjustQuantities | Apply incremental changes to inventory quantities at specific locations, with a reason code. | write | write_inventory | Current | |
Changes the stock count a store sells against. Acts onInventoryLevel Permission (capability) write_inventoryVersionAvailable since the API’s base version Webhook event inventory_levels-updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
FulfillmentOperations for reading fulfillment orders and creating fulfillments.2 | ||||||
| POST | query order.fulfillmentOrders | Read the fulfillment orders for an order, the units of work assigned to a location. | read | read_fulfillments | Current | |
Read scope depends on who manages the fulfillment; assigned, merchant-managed, or third-party each have their own scope. Acts onFulfillmentOrder Permission (capability) read_fulfillmentsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation fulfillmentCreateV2 | Create a fulfillment for one or more fulfillment orders assigned to the same location. | write | write_fulfillments | Current | |
Marks goods as shipped and can send the customer a shipment notification. Acts onFulfillment Permission (capability) write_fulfillmentsVersionAvailable since the API’s base version Webhook event fulfillments-createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Draft ordersOperations for building draft orders and turning them into real orders.3 | ||||||
| POST | query draftOrders | List draft orders in the store, paginated through a connection. | read | read_draft_orders | Current | |
Read-only. Acts onDraftOrder Permission (capability) read_draft_ordersVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation draftOrderCreate | Create a draft order combining custom line items with existing products. | write | write_draft_orders | Current | |
A draft is not yet a real order until it is completed. Acts onDraftOrder Permission (capability) write_draft_ordersVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation draftOrderComplete | Complete a draft order, turning it into a real order. | write | write_draft_orders | Current | |
Creates a real order that can take payment. Acts onDraftOrder Permission (capability) write_draft_ordersVersionAvailable since the API’s base version Webhook event orders-createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
CollectionsOperations for grouping products into collections.2 | ||||||
| POST | query collections | List collections in the store, paginated through a connection. | read | read_products | Current | |
Collections are covered by the products scope. Acts onCollection Permission (capability) read_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | mutation collectionCreate | Create a collection that groups products together on the storefront and other sales channels. | write | write_products | Current | |
Collections are covered by the products scope. Acts onCollection Permission (capability) write_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
MetafieldsOperations for reading and setting custom metafield data on records.1 | ||||||
| POST | mutation metafieldsSet | Set custom metafield values on a record, creating or overwriting them. | write | write_products | Current | |
Sets up to 25 metafields at a time. The scope needed matches the record the metafield is on, like write_products for a product. Acts onMetafield Permission (capability) write_productsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Shopify can notify an app when something happens in a store, like an order being placed or a product changing. It sends a topic and a payload describing what changed, so an integration learns about activity without polling.
| Event | What it signals | Triggered by |
|---|---|---|
orders/create | An order was placed in the store. The primary signal to start fulfillment and downstream processing. | mutation orderCreatemutation draftOrderComplete |
orders/updated | An order changed, like its shipping address, tags, or status. | mutation orderUpdate |
products/create | A new product was created in the catalog. | mutation productCreate |
products/update | A product changed, like its title, price, or variants. | mutation productUpdate |
customers/create | A new customer record was created. | mutation customerCreate |
customers/update | A customer record changed. | mutation customerUpdate |
inventory_levels/update | An inventory level changed at a location, used to keep external stock systems in sync. | mutation inventoryAdjustQuantities |
fulfillments/create | A fulfillment was created for an order, marking goods as shipped. | mutation fulfillmentCreateV2 |
Shopify limits how much an app can call by a calculated cost per request rather than a fixed number of requests, with a points budget that refills at a set rate per second and a separate ceiling on the cost of any single query.
The GraphQL Admin API meters by a calculated query cost, not a request count, using a leaky bucket. Each operation costs points by the data it touches: a scalar or enum costs 0, an object costs 1, a connection is sized by its first or last argument, and a mutation costs 10. The bucket refills at a fixed rate per second that depends on the store's plan, 100 points per second on Standard, 200 on Advanced, 1,000 on Shopify Plus, and 2,000 on the enterprise tier, and starts at a capacity of 40 times that rate. No single query may cost more than 1,000 points, checked before it runs. Each response reports requestedQueryCost, actualQueryCost, currentlyAvailable, and restoreRate under the extensions key, and going over returns a THROTTLED error.
GraphQL connections are cursor-based. A query asks for a page with the first or last argument, up to 250 items, and reads the cursor and a hasNextPage flag from pageInfo to fetch the following page. Page size feeds directly into the query cost, so a larger page costs more points.
A single GraphQL query may not exceed a calculated cost of 1,000 points. A connection returns at most 250 items per page. The metafieldsSet mutation accepts up to 25 metafields per call, within a 10MB request payload.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 200 | userErrors | A mutation ran but the action was rejected for a business reason, like an invalid field or a missing record. The GraphQL response is HTTP 200, and the detail is in the mutation's userErrors field, not the HTTP status. | Always request the userErrors field on a mutation, then read its field and message to see what was rejected and why, and fix the input. |
| 200 | THROTTLED | The request cost more points than the app's bucket currently held. GraphQL returns HTTP 200 with a THROTTLED entry in the top-level errors array and the throttle state under extensions. | Read the cost and restore rate from the extensions cost data, wait for the bucket to refill, and retry. Lower the cost by requesting fewer fields or smaller pages. |
| 200 | MAX_COST_EXCEEDED | A single query's calculated cost exceeds the 1,000-point per-query ceiling, which is checked before the query runs regardless of plan. | Split the query into smaller queries, request fewer nested connections, or reduce the page size on connections. |
| 401 | ACCESS_DENIED / Unauthorized | The request carried no valid access token, or the token was revoked. | Confirm a valid X-Shopify-Access-Token is sent, and re-run the install or token exchange if the token was revoked. |
| 402 | Payment Required | The store is frozen, usually for an unpaid Shopify bill, so the API is unavailable until the store is reactivated. | The merchant must resolve the billing issue with Shopify; the integration cannot bypass it. |
| 403 | Forbidden | The token is valid but lacks the scope this operation needs, or the store has been flagged. | Request the missing scope and have the merchant re-approve, or confirm the store's status. |
| 404 | Not Found | The endpoint, store, or API version in the request path does not exist or is not reachable. | Check the store domain and that the API version in the path is a supported, dated version. |
| 423 | Locked | The store is temporarily unavailable, for example due to repeated rate limiting or a fraud flag. | Back off and retry later, and reduce request volume. |
| 500 | Internal Server Error | An error on Shopify's side, which can also appear as other 5xx codes. | Retry with backoff, and contact Shopify if it persists. |
Shopify ships a new dated version of the Admin API every quarter, and each version is supported for at least a year, so an integration pins a version and moves up on its own schedule.
Shopify releases a new dated Admin API version each quarter and supports each for at least 12 months, with at least nine months of overlap between consecutive versions. The version is part of the request path, so an app pins a version and upgrades on its own schedule. 2026-04 is the latest stable version as of mid-2026.
The first quarterly release of 2026, dated 2026-01.
The October 2025 quarterly release, dated 2025-10.
The July 2025 quarterly release, dated 2025-07.
Pin a dated version and move up before the one in use is retired.
Shopify developer changelog ↗Bollard AI sits between a team's AI agents and Shopify. Grant each agent exactly the access it needs, read or write, resource by resource, and every call is checked and logged.