title: “Shopify — Shopify Admin & Storefront GraphQL APIs via curl” sidebar_label: “Shopify” description: “Shopify Admin & Storefront GraphQL APIs via curl”
{/* 本页面由 website/scripts/generate-skill-docs.py 根据技能对应的 SKILL.md 文件自动生成。请直接编辑源文件 SKILL.md,而非此页面。 */}
Shopify
通过 curl 访问 Shopify 管理后台及前端店铺的 GraphQL API,可处理产品、订单、客户、库存以及元字段等相关操作。
技能元数据
| 来源 | 可选 — 通过 hermes skills install official/productivity/shopify 安装 |
| 路径 | optional-skills/productivity/shopify |
| 版本 | 1.0.0 |
| 创建者 | 社区用户 |
| 许可协议 | MIT |
| 支持平台 | linux、macos、windows |
| 标签 | Shopify、电子商务、Commerce、API、GraphQL |
| 相关技能 | airtable、xurl |
参考:完整的 SKILL.md 文件
Shopify — 管理后台及前端店铺 GraphQL API
可直接通过 curl 操作 Shopify 店铺:列出产品、管理库存、查询订单、更新客户信息、读取元字段等。无需 SDK 也不用应用框架,仅需 GraphQL 接口以及自定义应用的访问令牌即可。
自 2024 年 4 月起,REST 管理后台 API 已属于旧版本,仅会接收安全补丁。所有管理操作请使用 GraphQL 管理 API;针对仅用于读取的客户端查询(如产品、系列、购物车信息),则可使用 前端店铺 GraphQL API。
前提条件
- 进入 Shopify 管理后台:设置 → 应用与销售渠道 → 开发应用 → 创建应用。
- 点击 配置管理 API 权限范围,选择所需功能(见下方示例),然后保存。
- 安装应用 — 管理 API 访问令牌仅会显示一次,请立即复制,因为 Shopify 不会再次展示该令牌。令牌开头为
shpat_。 - 将该令牌保存到
${HERMES_HOME:-~/.hermes}/.env文件中:SHOPIFY_ACCESS_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxx SHOPIFY_STORE_DOMAIN=my-store.myshopify.com SHOPIFY_API_VERSION=2026-01
重要提示: 自2026年1月1日起,通过Shopify管理后台创建的新“传统自定义应用”将不再存在。新的应用开发应使用开发者控制台(
shopify.dev/docs/apps/build/dev-dashboard)。现有通过管理后台创建的应用仍可正常使用。如果用户的店铺在2026-01-01之后且没有现有的自定义应用,请引导其使用开发者控制台,而非传统的管理后台流程。
按任务划分的常用权限范围:
- 产品/系列:
read_products、write_products - 库存:
read_inventory、write_inventory、read_locations - 订单:
read_orders、write_orders(仅返回最近的30笔订单,不支持read_all_orders) - 客户:
read_customers、write_customers - 草稿订单:
read_draft_orders、write_draft_orders - 发货处理:
read_fulfillments、write_fulfillments - 元字段/元对象:由对应的资源权限范围控制
API基础知识
- 端点地址: `https://$
shop_gql() {
local query="$1"
local variables="${2:-{}}"
curl -sS -X POST \
"https://${SHOPIFY_STORE_DOMAIN}/admin/api/${SHOPIFY_API_VERSION:-2026-01}/graphql.json" \
-H "Content-Type: application/json" \
-H "X-Shopify-Access-Token: ${SHOPIFY_ACCESS_TOKEN}" \
--data "$(jq -nc --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')"
}
通过 jq 处理输出以提升可读性。选项 -sS 能够显示错误信息,同时隐藏进度条。
发现功能
商店信息与当前 API 版本
shop_gql '{ shop { name myshopifyDomain primaryDomain { url } currencyCode plan { displayName } } }' | jq
列出所有受支持的 API 版本
shop_gql '{ publicApiVersions { handle supported } }' | jq '.data.publicApiVersions[] | select(.supported)'
产品
搜索产品(显示前20个匹配结果)
shop_gql '
query($q: String!) {
products(first: 20, query: $q) {
edges { node { id title handle status totalInventory variants(first: 5) { edges { node { id sku price inventoryQuantity } } } } }
pageInfo { hasNextPage endCursor }
}
}' '{"q":"hoodie status:active"}' | jq
查询语法支持使用 title:、sku:、vendor:、product_type:、status:active、tag: 以及 created_at:>2025-01-01 等条件。完整的语法规范请参见:https://shopify.dev/docs/api/usage/search-syntax
按页获取产品(游标方式)
shop_gql '
query($cursor: String) {
products(first: 100, after: $cursor) {
edges { cursor node { id handle } }
pageInfo { hasNextPage endCursor }
}
}' '{"cursor":null}'
# subsequent calls: pass the previous endCursor
获取具有变体及元字段的产品
shop_gql '
query($id: ID!) {
product(id: $id) {
id title handle descriptionHtml tags status
variants(first: 20) { edges { node { id sku price compareAtPrice inventoryQuantity selectedOptions { name value } } } }
metafields(first: 20) { edges { node { namespace key type value } } }
}
}' '{"id":"gid://shopify/Product/10079467700516"}' | jq
创建具有一个变体的产品
shop_gql '
mutation($input: ProductCreateInput!) {
productCreate(product: $input) {
product { id handle }
userErrors { field message }
}
}' '{"input":{"title":"Test Hoodie","status":"DRAFT","vendor":"Hermes","productType":"Apparel","tags":["test"]}}'
在最新版本中,变体现已拥有独立的突变机制:
# Add variants after creating the product
shop_gql '
mutation($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
productVariantsBulkCreate(productId: $productId, variants: $variants) {
productVariants { id sku price }
userErrors { field message }
}
}' '{"productId":"gid://shopify/Product/...","variants":[{"optionValues":[{"optionName":"Size","name":"M"}],"price":"49.00","inventoryItem":{"sku":"HD-M","tracked":true}}]}'
更新价格/SKU信息
shop_gql '
mutation($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
productVariantsBulkUpdate(productId: $productId, variants: $variants) {
productVariants { id sku price }
userErrors { field message }
}
}' '{"productId":"gid://shopify/Product/...","variants":[{"id":"gid://shopify/ProductVariant/...","price":"55.00"}]}'
订单
查看近期订单(默认显示最近30笔订单,如不使用read_all_orders参数则可查看全部)
shop_gql '
{
orders(first: 20, reverse: true, query: "financial_status:paid") {
edges { node {
id name createdAt displayFinancialStatus displayFulfillmentStatus
totalPriceSet { shopMoney { amount currencyCode } }
customer { id displayName email }
lineItems(first: 10) { edges { node { title quantity sku } } }
} }
}
}' | jq
实用的订单查询筛选条件包括:financial_status:paid|pending|refunded、fulfillment_status:unfulfilled|fulfilled、created_at:>2025-01-01、tag:gift 以及 email:foo@example.com。
获取包含配送地址的单一订单信息
shop_gql '
query($id: ID!) {
order(id: $id) {
id name email
shippingAddress { name address1 address2 city province country zip phone }
lineItems(first: 50) { edges { node { title quantity variant { sku } originalUnitPriceSet { shopMoney { amount currencyCode } } } } }
transactions { id kind status amountSet { shopMoney { amount currencyCode } } }
}
}' '{"id":"gid://shopify/Order/...."}' | jq
客户端
# Search
shop_gql '
{
customers(first: 10, query: "email:*@example.com") {
edges { node { id email displayName numberOfOrders amountSpent { amount currencyCode } } }
}
}'
# Create
shop_gql '
mutation($input: CustomerInput!) {
customerCreate(input: $input) {
customer { id email }
userErrors { field message }
}
}' '{"input":{"email":"test@example.com","firstName":"Test","lastName":"User","tags":["api-created"]}}'
库存管理
库存信息存储在与具体款式关联的库存条目中,并按存放位置来记录相应的数量。
# Get inventory for a variant across all locations
shop_gql '
query($id: ID!) {
productVariant(id: $id) {
id sku
inventoryItem {
id tracked
inventoryLevels(first: 10) {
edges { node { location { id name } quantities(names: ["available","on_hand","committed"]) { name quantity } } }
}
}
}
}' '{"id":"gid://shopify/ProductVariant/..."}'
调整库存(增量)——使用 inventoryAdjustQuantities 函数:
shop_gql '
mutation($input: InventoryAdjustQuantitiesInput!) {
inventoryAdjustQuantities(input: $input) {
inventoryAdjustmentGroup { reason changes { name delta } }
userErrors { field message }
}
}' '{
"input": {
"reason": "correction",
"name": "available",
"changes": [{"delta": 5, "inventoryItemId": "gid://shopify/InventoryItem/...", "locationId": "gid://shopify/Location/..."}]
}
}'
设置绝对库存量(而非变动量)——inventorySetQuantities:
shop_gql '
mutation($input: InventorySetQuantitiesInput!) {
inventorySetQuantities(input: $input) {
inventoryAdjustmentGroup { id }
userErrors { field message }
}
}' '{"input":{"reason":"correction","name":"available","ignoreCompareQuantity":true,"quantities":[{"inventoryItemId":"gid://shopify/InventoryItem/...","locationId":"gid://shopify/Location/...","quantity":100}]}}'
元字段与元对象
元字段用于为资源(产品、客户、订单、店铺)添加自定义数据。
# Read
shop_gql '
query($id: ID!) {
product(id: $id) {
metafields(first: 10, namespace: "custom") {
edges { node { key type value } }
}
}
}' '{"id":"gid://shopify/Product/..."}'
# Write (works for any owner type)
shop_gql '
mutation($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields { id key namespace }
userErrors { field message code }
}
}' '{"metafields":[{"ownerId":"gid://shopify/Product/...","namespace":"custom","key":"care_instructions","type":"multi_line_text_field","value":"Wash cold. Tumble dry low."}]}'
Storefront API(公共只读版)
该版本使用独立的端点与令牌,专为面向客户的应用程序及氢能架构风格的无头系统设计。其请求头也有所不同:
- 端点地址: `https://$
curl -sS -X POST \
"https://${SHOPIFY_STORE_DOMAIN}/api/${SHOPIFY_API_VERSION:-2026-01}/graphql.json" \
-H "Content-Type: application/json" \
-H "X-Shopify-Storefront-Access-Token: ${SHOPIFY_STOREFRONT_TOKEN}" \
-d '{"query":"{ shop { name } products(first: 5) { edges { node { id title handle } } } }"}' | jq
批量操作
针对超过速率限制大小的导出数据(如完整产品目录、全年的所有订单):
# 1. Start bulk query
shop_gql '
mutation {
bulkOperationRunQuery(query: """
{ products { edges { node { id title handle variants { edges { node { sku price } } } } } } }
""") {
bulkOperation { id status }
userErrors { field message }
}
}'
# 2. Poll status
shop_gql '{ currentBulkOperation { id status errorCode objectCount fileSize url partialDataUrl } }'
# 3. When status=COMPLETED, download the JSONL file
curl -sS "$URL" > products.jsonl
每行 JSONL 数据代表一个节点,而嵌套关系则会通过添加 __parentId 字段以独立行形式呈现。如有需要,可在客户端进行重新组合。
Webhooks
订阅事件即可,无需手动轮询:
shop_gql '
mutation($topic: WebhookSubscriptionTopic!, $sub: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(topic: $topic, webhookSubscription: $sub) {
webhookSubscription { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } }
userErrors { field message }
}
}' '{"topic":"ORDERS_CREATE","sub":{"callbackUrl":"https://example.com/webhook","format":"JSON"}}'
请使用应用程序的客户端密钥(而非访问令牌)来验证传入的 Webhook HMAC 值:
echo -n "$REQUEST_BODY" | openssl dgst -sha256 -hmac "$APP_SECRET" -binary | base64
# Compare to X-Shopify-Hmac-Sha256 header
常见问题
- REST 接口虽存在但已冻结。 请勿再为
/admin/api/.../products.json开发新的集成方案,应改用 GraphQL。 - 令牌格式校验。 管理员令牌以
shpat_开头,而店铺公开令牌则以shpua_开头。如果使用了错误的令牌格式,所有请求都会返回 401 错误,且不会附带有用的错误信息。 - 使用有效令牌却仍返回 403 错误 = 缺少权限范围。 Shopify 会返回
{"errors":[{"message":"Access denied for ..."}]}。此时需在应用中重新配置管理员 API 的权限范围,然后重新安装应用以生成新的令牌。 userErrors为空并不代表操作成功。 还需检查data.<mutation>.<resource>的值是否非空。某些失败情况会导致这两个字段均为空,因此需要仔细查看完整响应内容。- GID 与数字 ID 的区别。 旧版的 REST 接口返回的是数字 ID,而 GraphQL 要求使用完整的 GID 字符串。转换方法为:
gid://shopify/Product/<numeric>。 - 速率限制的意外影响。 单次调用
products(first: 250)且嵌套层级较深时,可能会消耗 1000 多个积分,导致使用标准套餐的店铺立即被限流。建议先缩小查询范围,查看extensions.cost的数值后再进行调整。 - 分页顺序问题。
products(first: N, reverse: true)是按id降序排列,而非按created_at排序。如需按“最新优先”排序,应使用sortKey: CREATED_AT, reverse: true。 - 获取历史数据需使用
read_all_orders。 若不使用该权限范围,orders(...)查询将默认仅返回最近 60 天内的订单数据。此时不会出现错误,但返回的结果数量会少于预期。对于拥有大量订单的 Shopify Plus 商家,可通过应用的保护数据设置来申请此权限范围。 - 货币类型为字符串。 金额将以
"49.00"的字符串形式返回,而非49.0这样的数字形式。如果需要处理零填充问题,切勿盲目使用jq tonumber工具。 - 多货币金额字段包含
shopMoney(店铺货币)和presentmentMoney(客户显示货币)两种类型。 应始终统一选择其中一种格式进行使用。
安全性注意事项
在 Shopify 中执行的变更操作都是真实有效的——它们能够创建产品、处理退款、取消订单以及安排发货。在运行 productDelete、orderCancel、refundCreate 或任何批量变更操作之前,务必明确说明要进行的更改内容、涉及的店铺,並获得用户确认。除非用户拥有独立的开发店铺,否则无法使用生产环境数据的分支环境进行测试。