Skill metadata
Reference: full SKILL.md
The following is the complete skill definition that Mibyan loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
Shopify — Admin & Storefront GraphQL APIs
Work with Shopify stores directly throughcurl: list products, manage inventory, pull orders, update customers, read metafields. No SDK, no app framework — just the GraphQL endpoint and a custom-app access token.
The REST Admin API is legacy since 2024-04 and only receives security fixes. Use GraphQL Admin for all admin work. Use Storefront GraphQL for read-only customer-facing queries (products, collections, cart).
Prerequisites
- In Shopify admin: Settings → Apps and sales channels → Develop apps → Create an app.
- Click Configure Admin API scopes, select what you need (examples below), save.
- Install app → the Admin API access token appears ONCE. Copy it immediately — Shopify will never show it again. Tokens start with
shpat_. - Save to
${mibyan_HOME:-~/.mibyan}/.env:
Heads up: As of January 1, 2026, new “legacy custom apps” created in the Shopify admin are gone. New setups should use the Dev Dashboard (shopify.dev/docs/apps/build/dev-dashboard). Existing admin-created apps keep working. If the user’s shop has no existing custom app and it’s after 2026-01-01, direct them to Dev Dashboard instead of the admin flow.
Common scopes by task:
- Products / collections:
read_products,write_products - Inventory:
read_inventory,write_inventory,read_locations - Orders:
read_orders,write_orders(30 most recent withoutread_all_orders) - Customers:
read_customers,write_customers - Draft orders:
read_draft_orders,write_draft_orders - Fulfillments:
read_fulfillments,write_fulfillments - Metafields / metaobjects: covered by the matching resource scopes
API Basics
- Endpoint:
https://$SHOPIFY_STORE_DOMAIN/admin/api/$SHOPIFY_API_VERSION/graphql.json - Auth header:
X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN(NOTAuthorization: Bearer) - Method: always
POST, alwaysContent-Type: application/json, body is{"query": "...", "variables": {...}} - HTTP 200 does not mean success. GraphQL returns errors in a top-level
errorsarray and per-fielduserErrors. Always check both. - IDs are GID strings:
gid://shopify/Product/10079467700516,gid://shopify/Variant/...,gid://shopify/Order/.... Pass these verbatim — don’t strip the prefix. - Rate limit: calculated via query cost (leaky bucket). Each response has
extensions.costwithrequestedQueryCost,actualQueryCost,throttleStatus.{currentlyAvailable, maximumAvailable, restoreRate}. Back off whencurrentlyAvailabledrops below your next query’s cost. Standard shops = 100 points bucket, 50/s restore; Plus = 1000/100.
jq for readable output. -sS keeps errors visible but hides the progress bar.
Discovery
Shop info + current API version
List all supported API versions
Products
Search products (first 20 matching query)
title:, sku:, vendor:, product_type:, status:active, tag:, created_at:>2025-01-01. Full grammar: https://shopify.dev/docs/api/usage/search-syntax
Paginate products (cursor)
Get a product with variants + metafields
Create a product with one variant
Update price / SKU
Orders
List recent orders (last 30 by default without read_all_orders)
financial_status:paid|pending|refunded, fulfillment_status:unfulfilled|fulfilled, created_at:>2025-01-01, tag:gift, email:foo@example.com.
Fetch a single order with shipping address
Customers
Inventory
Inventory lives on inventory items tied to variants, quantities tracked per location.inventoryAdjustQuantities:
inventorySetQuantities:
Metafields & Metaobjects
Metafields attach custom data to resources (products, customers, orders, shop).Storefront API (public read-only)
Different endpoint, different token, used for customer-facing apps/hydrogen-style headless setups. Headers differ:- Endpoint:
https://$SHOPIFY_STORE_DOMAIN/api/$SHOPIFY_API_VERSION/graphql.json - Auth header (public):
X-Shopify-Storefront-Access-Token: <public token>— embeddable in browser - Auth header (private):
Shopify-Storefront-Private-Token: <private token>— server-only
Bulk Operations
For dumps larger than rate limits allow (full product catalog, all orders for a year):__parentId. Reassemble client-side if needed.
Webhooks
Subscribe to events so you don’t have to poll:Pitfalls
- REST endpoints still exist but are frozen. Don’t write new integrations against
/admin/api/.../products.json. Use GraphQL. - Token format check. Admin tokens start with
shpat_. Storefront public tokens withshpua_. If you have one and the wrong header, every request returns 401 without a useful error body. - 403 with a valid token = missing scope. Shopify returns
{"errors":[{"message":"Access denied for ..."}]}. Re-configure Admin API scopes on the app, then reinstall to regenerate the token. userErrorsis empty != success. Also checkdata.<mutation>.<resource>is non-null. Some failures populate neither — inspect the whole response.- GID vs numeric ID. Legacy REST gave numeric IDs; GraphQL wants full GID strings. To convert:
gid://shopify/Product/<numeric>. - Rate limit surprise. A single
products(first: 250)with deep nesting can cost 1000+ points and throttle immediately on a standard-plan shop. Start narrow, readextensions.cost, adjust. - Pagination order.
products(first: N, reverse: true)sorts byid DESC, notcreated_at. UsesortKey: CREATED_AT, reverse: truefor “newest first.” read_all_ordersfor historical data. Without it,orders(...)silently caps at the 60-day window. You won’t get an error, just fewer results than expected. For Shopify Plus merchants with many orders, request this scope via the app’s protected-data settings.- Currencies are strings. Amounts come back as
"49.00"not49.0. Don’tjq tonumberblindly if you care about zero-padding. - Multi-currency Money fields have
shopMoney(store’s currency) ANDpresentmentMoney(customer’s). Pick one consistently.
Safety
Mutations in Shopify are real — they create products, charge refunds, cancel orders, ship fulfillments. Before runningproductDelete, orderCancel, refundCreate, or any bulk mutation: state clearly what the change is, on which shop, and confirm with the user. There is no staging clone of production data unless the user has a separate dev store.
