All docs
Connect

Shopify: generate an Admin token and let the agent make changes

TL;DR

Shopify connects at three levels. The store domain alone unlocks anonymous catalog, product and cart tools. Adding an Admin API access token (or custom-app client credentials, or the OAuth app) unlocks read-only orders, products, customers and a server-side sales summary. With write scopes on that connection, the agent can also change the store — discount codes, product, price, inventory and collection changes — each going through the approval gate before it runs, and the irreversible or money-moving ones always waiting for a person.

The three connection tiers

Pick the tier by what you want the agent to do. You can start at tier 1 and upgrade later — adding a token to an existing store never breaks the storefront tools.

TierWhat you provideWhat the agent can do
1 — StorefrontStore domain onlySearch the public catalog, read product details, build a cart and get a checkout link, search store policies and FAQs. No credentials at all.
2 — Admin readAdmin API access token, or custom-app client ID + secret, or the OAuth appEverything above, plus orders, admin-side products (including DRAFT/ARCHIVED and live inventory), customers, shop info, and an aggregated sales summary.
3 — Admin writeThe same connection, with write scopes granted (ticked on the token, or on the Shopify app's consent screen)Everything above, plus store changes — typed tools for discount codes, inventory, product copy / tags / SEO / status, variant prices, product media and the app's web pixel, and Admin GraphQL mutations for anything else your scopes allow. Every change is approval-gated; deletions, money-moving mutations, repricing, an absolute stock set, deactivating a code, a discount of 50 % off or more and a product status flip wait for a person.
Credentials are encrypted at rest, scoped to your organization, and never returned to the browser.

Generate a Shopify Admin API access token

This is the custom-app path — the fastest way to get a token, and the one where you choose the scopes yourself, write scopes included. You need to be the store owner or a staff account with the “Develop apps” permission.

  1. 1In Shopify admin, go to Settings → Apps and sales channels → Develop apps (since 2026 this hands off to the Shopify Dev Dashboard — same flow, newer screens).
  2. 2Create an app and give it a name (e.g. “Agent Planners”).
  3. 3Open Configuration → Admin API integration, and tick the scopes you want (see the scope table below) — include write_* scopes if you want approval-gated store changes.
  4. 4Save, then install the app on your store from the API credentials / app settings screen.
  5. 5On API credentials, click “Reveal token once” next to Admin API access token — it starts with shpat_ and Shopify shows it exactly once, so copy it now (check your scopes BEFORE revealing).
  6. 6In Agent Planners, open Integrations → Shopify → Connect store, enter your store domain, choose “+ Admin token”, paste the token, and click “Validate + connect”.
The connection is validated live before it's saved — a bad token, a wrong domain or a missing scope fails at connect time instead of silently mid-run. The “API key and secret key” on the same screen are this app's client ID/secret under an older name; the “+ Client credentials” tab only works for Dev-Dashboard-created apps (Shopify refuses the grant for other app types — if that happens, use the Admin token instead).

Which scopes to grant

Grant only what you actually want the agent to reach. A missing scope isn't a crash — Shopify answers with an ACCESS_DENIED message naming the scope, so you can add it and retry. The one exception is read_all_orders: without it Shopify silently serves only the last 60 days of orders.

You wantScope to tick
Orders, revenue, the sales summary, fulfillments and trackingread_orders
Admin product list, inventory counts, draft/archived productsread_products
Customer list and lifetime spendread_customers
Inventory levelsread_inventory
The agent to create or edit products and priceswrite_products
The agent to adjust inventorywrite_inventory
Locations — the ids every inventory change needsread_locations
Discount codes (list)read_discounts
The agent to create, edit, activate, deactivate or delete discount codeswrite_discounts
Returnsread_returns
Shopify Marketing activities (read only)read_marketing_events
The app's web pixel — works only when the app ships a web-pixel extensionwrite_pixels + read_customer_events
Orders older than 60 days, in order reads and the sales summaryread_all_orders — without it Shopify silently serves the last 60 days
Sessions and conversion rate (ShopifyQL)read_reports, plus Shopify's Level 2 protected-customer-data approval
Read scopes alone keep the store strictly read-only — the mutation tool will exist but every write Shopify sees will be refused for lack of scope. That's a deliberate, safe default: start read-only, add write scopes when you're ready.

The other two ways to connect

  • Client credentials — paste the custom app's client ID and client secret instead of a token. Agent Planners exchanges them for a short-lived Bearer automatically and refreshes it before expiry, so there's no long-lived token sitting in storage.
  • Shopify app (OAuth) — enter your your-store.myshopify.com domain and authorize in Shopify. No custom app to build and no token to copy. The consent screen lists exactly the scopes this deployment requests (read_products, read_orders, read_customers, read_inventory by default; an operator can add write scopes), the store's row shows what Shopify actually granted, and Sync scopes re-reads it. Every typed write checks that grant first and answers with the missing scope instead of failing mid-run.
OAuth only works on the canonical .myshopify.com domain, not a custom storefront domain. Public apps issue expiring tokens, which are refreshed automatically; a custom app's offline token does not expire.

What the agent can read

CapabilityWhat comes back
Sales summaryServer-side aggregation over the window: order count, revenue, average order value, revenue by day, orders by financial status, and top products by units. The totals are computed in code, so the model never re-adds order rows by hand.
OrdersRecent orders with name, date, financial and fulfilment status, total and line items — in the shop's own currency, with the date window anchored to the shop's timezone.
Products (admin view)Title, status, vendor, product type, live inventory and price range — including DRAFT and ARCHIVED products the public storefront never shows.
CustomersOrder count and lifetime spend per customer. The name (Shopify's display name, which falls back to the email or phone) comes back only when a person's own request in an interactive task asks for identified customers — never over MCP, in an autonomous run, on a schedule or on a dashboard.
Shop infoName, currency, timezone, myshopify and primary domain.
Admin GraphQL queryA generic read gateway for anything the wrappers don't cover. Mutation documents are rejected outright on this tool.
Storefront catalog / cart / policiesPublic product search, product details, cart building with a checkout URL, and policy/FAQ search — available with no credentials.
Locations and inventory levelsThe store's locations, and available / on-hand / committed / incoming per location for a product's variants — the pairs an inventory change needs (read_locations, read_inventory).
Discount codes, returns, fulfillmentsCode and automatic discounts with status, dates, usage and value (the API's 0–1 percentage is shown as a percent too); orders with returns; fulfillments with tracking and delivery dates.
Marketing activities, app scopes, web pixelShopify Marketing's own campaign records with their UTMs and spend; what the store's authorization grants right now versus the row; the app's web pixel.
Landing URLA UTM-tagged storefront URL on the primary domain for an ad's destination — existing parameters kept byte for byte, values encoded once, nothing written.
No dedicated tool writes orders or takes payment — cart building returns a checkout URL for a human to complete in their own browser. Order mutations are reachable only through the generic mutation gateway, only when the connection carries order write scopes, and the money-moving ones — refunds, captures, voids, cancellations, completing a draft order, charging a saved payment method — always wait for a person.

How the agent makes changes to your store

Store changes run through one Admin GraphQL mutation gateway, so anything your connection is scoped for is reachable — product create/update/delete, variant and price updates, inventory adjustments, collection management, and so on. You describe the change in plain language; the agent writes the mutation and shows it to you before it runs.

Since rev808 the common changes are typed tools with their own checks: create / update / activate / delete a discount code, adjust inventory by a delta (an idempotency key is minted per request) or set it absolutely, edit product copy, tags, SEO and status, reprice variants, add product media from public URLs, and manage the app's web pixel. Every one checks the store's granted scope first and pauses for approval; deleting a code or the pixel, an absolute inventory set, repricing, deactivating a code (or ending / postponing it by date), a discount of 50 % off or more (typed, or a discount written through the mutation gateway) and a product status flip always wait for a person.

  1. 1Write the goal in the Workspace, e.g. “Mark every product with zero inventory as draft.”
  2. 2The agent reads the store first to find exactly which products match — you see the list before anything changes.
  3. 3Each mutation stops at the approval gate showing the exact GraphQL document and variables it will send.
  4. 4Approve (in-app or by email magic-link) and it runs once. Reject and that step is skipped without aborting the rest of the run.
  5. 5The result is verified and written to the audit log with before/after detail.
Start with read_* scopes only and run a few audits first. Add write_products when you trust the plans it produces.

Write safety

  • Always approval-gated. Shopify mutations are force-gated at the registry level — a plan cannot mark one as pre-approved to skip the gate, and the irreversible or money-moving ones wait for a person even on a task or schedule you put on auto-approve.
  • Never retried. A mutation is attempted exactly once. A retry after an ambiguous send would double-apply the change.
  • Honest failure. Shopify answers HTTP 200 even when a write fails, tucking the reason into userErrors. Every mutation must select userErrors { field message } up front, and any non-empty result is reported as a failure — never as a silent success.
  • Read-only stays read-only. The query gateway rejects mutation documents, and the mutation gateway rejects query documents, so neither can be used to sneak past the other's rules.
There's no spend-magnitude cap on Shopify writes, unlike the ad platforms — product, price and inventory changes carry no ad-budget semantics. The protection is the approval gate plus two bounds: an inventory change is capped per call (SHOPIFY_MAX_INVENTORY_CHANGE), and the changes with the widest reach — repricing variants, an absolute stock set, a discount of 50 % off or more — wait for a person.

Use cases

These are goals you'd type into the Workspace with a Shopify store selected in the context picker. The read-only ones run immediately; the write ones plan the change and pause for your approval.

Goal you'd typeWhat the agent does
"Give me the last 30 days of Shopify sales — daily revenue, AOV and top products."Runs the aggregated sales summary and writes it up as a report, with the numbers computed server-side rather than re-added by the model.
"Join last month's Google Ads cost with Shopify order revenue and give me true ROAS per campaign."Pulls Google Ads cost and Shopify revenue in the same run and reports blended ROAS off your real order data instead of platform-reported conversions.
"Which products sold nothing in 60 days but still have inventory?"Cross-references the sales summary's top-products data with the admin product list and its live inventory counts.
"Find products missing a vendor or product type and list them."Reads the admin product list — including drafts — and reports the gaps in your catalog metadata.
"Mark every out-of-stock product as draft."Finds the matching products, then proposes one productUpdate mutation per product, each waiting for your approval.
"Raise the price of everything in the Summer collection by 10%."Reads the collection, computes the new prices, and shows you the exact variant price mutations before any of them run.
"Who are my top 20 customers by lifetime spend, with their names?"Reads the customer list sorted by amount spent (needs the read_customers scope). The names come back because your own request asks for them; the same list read by a schedule, an API key or a dashboard carries ids, order counts and totals only.
"Email me a Shopify sales report every Monday morning."Turn the goal into a schedule — each fire re-reads live data, so the report is never stale.
"Build a cart with these three products and send me the checkout link."Uses the anonymous storefront tools — no credentials needed — and returns a checkout URL for a human to complete.
For a worked routine that combines these with Google Ads and Search Console data, see a daily Shopify optimization loop.

Troubleshooting

SymptomFix
"This Shopify connection is storefront-only"You connected with the domain alone. On the Integrations page, authorize the Shopify app (OAuth) with your your-store.myshopify.com domain, or add an Admin token or client credentials, to unlock orders and admin data.
HTTP 401 / 403 from the Admin APIThe token is invalid, revoked, or missing the scope for what you asked. Check the scope table above, add it in the custom app, reinstall, and reconnect. On a Shopify app (OAuth) connection, press Re-authorize on the store's row — a scope the app does not request yet is first added by the operator to the app's released version and to the scopes this deployment requests.
ACCESS_DENIED naming a scopeShopify is telling you exactly which scope to tick — add it in the custom app's Admin API configuration and reinstall the app. On a Shopify app (OAuth) connection, the operator adds it to the app's released version and the scopes this deployment requests, then you press Re-authorize on the store's row (a typed write names the missing scope from the store's grant before it calls Shopify).
"Admin token expired"Paste a fresh token on the Integrations page. Client-credentials connections refresh themselves and shouldn't hit this.
OAuth rejects your domainThe OAuth path needs the canonical your-store.myshopify.com domain, not a custom storefront domain.
A mutation was refused before it ranThe mutation document must select userErrors { field message }. The agent re-writes it and retries automatically when this happens.

Frequently asked questions

How do I generate a Shopify Admin API access token?
In Shopify admin go to Settings → Apps and sales channels → Develop apps — since 2026 Shopify hands app creation off to its Dev Dashboard, and an existing custom app keeps working — configure the Admin API scopes you want (e.g. read_orders, read_products, write_products), save, then Install app and reveal the Admin API access token — it starts with shpat_. Paste it into the Shopify card on the Integrations page with your store domain, or skip the token and authorize the Shopify app (OAuth) with the domain alone.
What scopes does Agent Planners need for Shopify?
read_orders for orders, fulfillments and the sales summary, read_products for the admin product list and inventory, read_customers for customers, and read_inventory for stock levels. The typed tools add read_locations, read_discounts, read_returns and read_marketing_events; read_all_orders reaches orders older than 60 days (without it Shopify silently serves only the last 60), and ShopifyQL sessions and conversion rate need read_reports plus Shopify's Level 2 protected-customer-data approval. Add write_products / write_inventory / write_discounts (and write_pixels + read_customer_events for the app's web pixel) only if you want the agent to change the store — reads alone keep it strictly read-only. On the Shopify app (OAuth) you tick nothing: the consent screen carries exactly the scopes this deployment requests.
Can the agent actually change my Shopify store?
Yes, if your connection carries write scopes — ticked on a custom-app token, or granted on the Shopify app's consent screen when this deployment requests them. It reaches the Admin GraphQL mutation surface — create and update products, change prices, adjust inventory, manage collections and discount codes — but every mutation is force-gated: you see the exact document and variables and approve it before it runs (unless you put the task or schedule on auto-approve, which never covers the irreversible or money-moving ones), it's attempted only once, and a Shopify-side rejection is reported as a failure rather than a silent success.
Do I need a token at all?
No. The store domain alone connects the anonymous Storefront tier — catalog search, product details, cart building with a checkout link, and store policy search. Add a token, or authorize the Shopify app (OAuth), when you want orders, admin data or writes.
Can the agent place an order or take payment?
Not unless your connection carries order write scopes. No dedicated tool writes orders or takes payment — cart building returns a checkout URL and a human completes payment in their own browser. With write_orders or write_draft_orders on your token (or on the Shopify app's grant, when this deployment requests them), the generic mutation gateway can reach order mutations; the ones that move money — refunds (a return processed with a refund included), captures, cancellations, voids, completing a draft order, charging a saved payment method — and every delete always wait for a person, as does editing an order's line items. Creating an order, updating its notes, tags or addresses, or marking one as paid (which records a payment taken outside Shopify) takes the ordinary approval.
Should I use a token, client credentials or OAuth?
Use the Shopify app (OAuth) for the fastest setup, with no custom app to build — its consent screen carries exactly the scopes this deployment requests (four reads by default; write scopes when the operator adds them). Use a custom-app Admin token when you want to choose the scopes yourself, write scopes included. Use client credentials if you'd rather not store a long-lived token (they're exchanged for a short-lived Bearer that refreshes itself). On every path, each store change goes through the approval step.
Can I use my custom domain?
For the token and client-credentials paths, yes — enter either your custom domain or the myshopify.com one. The OAuth path works only on the canonical your-store.myshopify.com domain.

Related