shopify-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShopify API Integration
Shopify API集成指南
Expert guidance for all Shopify APIs including GraphQL Admin API, REST Admin API, Storefront API, Ajax API, authentication, and webhooks.
针对所有Shopify API的专业指导,包括GraphQL Admin API、REST Admin API、Storefront API、Ajax API、认证和Webhook。
When to Use This Skill
适用场景
Invoke this skill when:
- Making GraphQL or REST API calls to Shopify
- Implementing OAuth 2.0 authentication for apps
- Fetching product, collection, order, or customer data programmatically
- Using Storefront API for headless commerce
- Implementing Ajax cart operations in themes
- Setting up webhooks for event handling
- Working with API version 2025-10
- Handling rate limiting and API errors
- Building custom integrations with Shopify
- Using Shopify Admin API from Node.js, Python, or other languages
在以下场景中使用本技能:
- 向Shopify发起GraphQL或REST API调用
- 为应用实现OAuth 2.0认证
- 程序化获取商品、商品集合、订单或客户数据
- 使用Storefront API实现无头电商
- 在主题中实现Ajax购物车操作
- 设置Webhook进行事件处理
- 使用API版本2025-10
- 处理速率限制和API错误
- 构建与Shopify的自定义集成
- 从Node.js、Python或其他语言调用Shopify Admin API
Core Capabilities
核心功能
1. GraphQL Admin API
1. GraphQL Admin API
Modern API for Shopify Admin operations with efficient data fetching.
Endpoint:
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.jsonHeaders:
javascript
{
'X-Shopify-Access-Token': 'shpat_...',
'Content-Type': 'application/json'
}Basic Query:
graphql
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
status
vendor
productType
# Pricing
priceRange {
minVariantPrice { amount currencyCode }
maxVariantPrice { amount currencyCode }
}
# Images
images(first: 5) {
edges {
node {
id
url
altText
}
}
}
# Variants
variants(first: 10) {
edges {
node {
id
title
sku
price
inventoryQuantity
available: availableForSale
}
}
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}Variables:
json
{
"first": 10
}JavaScript Example:
javascript
async function getProducts(accessToken, store, limit = 10) {
const query = `
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
priceRange {
minVariantPrice { amount currencyCode }
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const response = await fetch(
`https://${store}.myshopify.com/admin/api/2025-10/graphql.json`,
{
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables: { first: limit },
}),
}
);
const { data, errors } = await response.json();
if (errors) {
console.error('GraphQL Errors:', errors);
throw new Error(errors[0].message);
}
return data.products;
}Common Mutations:
Create product:
graphql
mutation CreateProduct($input: ProductInput!) {
productCreate(input: $input) {
product {
id
title
handle
}
userErrors {
field
message
}
}
}Update product:
graphql
mutation UpdateProduct($input: ProductInput!) {
productUpdate(input: $input) {
product {
id
title
status
}
userErrors {
field
message
}
}
}Set metafield:
graphql
mutation SetMetafield($input: MetafieldInput!) {
metafieldSet(input: $input) {
metafield {
id
namespace
key
value
type
}
userErrors {
field
message
}
}
}用于Shopify后台操作的现代化API,支持高效数据获取。
端点:
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json请求头:
javascript
{
'X-Shopify-Access-Token': 'shpat_...',
'Content-Type': 'application/json'
}基础查询:
graphql
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
status
vendor
productType
# Pricing
priceRange {
minVariantPrice { amount currencyCode }
maxVariantPrice { amount currencyCode }
}
# Images
images(first: 5) {
edges {
node {
id
url
altText
}
}
}
# Variants
variants(first: 10) {
edges {
node {
id
title
sku
price
inventoryQuantity
available: availableForSale
}
}
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}变量:
json
{
"first": 10
}JavaScript示例:
javascript
async function getProducts(accessToken, store, limit = 10) {
const query = `
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
priceRange {
minVariantPrice { amount currencyCode }
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const response = await fetch(
`https://${store}.myshopify.com/admin/api/2025-10/graphql.json`,
{
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables: { first: limit },
}),
}
);
const { data, errors } = await response.json();
if (errors) {
console.error('GraphQL Errors:', errors);
throw new Error(errors[0].message);
}
return data.products;
}常见变更操作:
创建商品:
graphql
mutation CreateProduct($input: ProductInput!) {
productCreate(input: $input) {
product {
id
title
handle
}
userErrors {
field
message
}
}
}更新商品:
graphql
mutation UpdateProduct($input: ProductInput!) {
productUpdate(input: $input) {
product {
id
title
status
}
userErrors {
field
message
}
}
}设置元字段:
graphql
mutation SetMetafield($input: MetafieldInput!) {
metafieldSet(input: $input) {
metafield {
id
namespace
key
value
type
}
userErrors {
field
message
}
}
}2. REST Admin API
2. REST Admin API
Traditional REST API for Shopify Admin operations.
Base URL:
https://{store}.myshopify.com/admin/api/2025-10/Authentication:
javascript
headers: {
'X-Shopify-Access-Token': 'shpat_...'
}Common Endpoints:
Get products:
javascript
GET /admin/api/2025-10/products.json?limit=50&status=active
// JavaScript
const response = await fetch(
`https://${store}.myshopify.com/admin/api/2025-10/products.json?limit=50`,
{
headers: {
'X-Shopify-Access-Token': accessToken,
},
}
);
const { products } = await response.json();Get single product:
javascript
GET /admin/api/2025-10/products/{product_id}.jsonCreate product:
javascript
POST /admin/api/2025-10/products.json
// Body
{
"product": {
"title": "New Product",
"body_html": "<p>Description</p>",
"vendor": "My Vendor",
"product_type": "Shoes",
"status": "draft"
}
}Update product:
javascript
PUT /admin/api/2025-10/products/{product_id}.json
// Body
{
"product": {
"id": 123456789,
"title": "Updated Title"
}
}Get orders:
javascript
GET /admin/api/2025-10/orders.json?status=any&limit=50Get customers:
javascript
GET /admin/api/2025-10/customers.json?limit=50用于Shopify后台操作的传统REST API。
基础URL:
https://{store}.myshopify.com/admin/api/2025-10/认证:
javascript
headers: {
'X-Shopify-Access-Token': 'shpat_...'
}常见端点:
获取商品:
javascript
GET /admin/api/2025-10/products.json?limit=50&status=active
// JavaScript
const response = await fetch(
`https://${store}.myshopify.com/admin/api/2025-10/products.json?limit=50`,
{
headers: {
'X-Shopify-Access-Token': accessToken,
},
}
);
const { products } = await response.json();获取单个商品:
javascript
GET /admin/api/2025-10/products/{product_id}.json创建商品:
javascript
POST /admin/api/2025-10/products.json
// 请求体
{
"product": {
"title": "New Product",
"body_html": "<p>Description</p>",
"vendor": "My Vendor",
"product_type": "Shoes",
"status": "draft"
}
}更新商品:
javascript
PUT /admin/api/2025-10/products/{product_id}.json
// 请求体
{
"product": {
"id": 123456789,
"title": "Updated Title"
}
}获取订单:
javascript
GET /admin/api/2025-10/orders.json?status=any&limit=50获取客户:
javascript
GET /admin/api/2025-10/customers.json?limit=503. OAuth 2.0 Authentication
3. OAuth 2.0认证
Complete OAuth flow for custom apps.
Step 1: Authorization Request
GET https://{shop}.myshopify.com/admin/oauth/authorize?
client_id={api_key}&
redirect_uri={redirect_uri}&
scope={scopes}&
state={random_state}Scopes:
javascript
const scopes = [
'read_products',
'write_products',
'read_orders',
'write_orders',
'read_customers',
'write_customers',
'read_inventory',
'write_inventory',
'read_metafields',
'write_metafields',
].join(',');Step 2: Handle Callback
javascript
// User approves, Shopify redirects to:
GET {redirect_uri}?code={auth_code}&state={state}&hmac={hmac}&shop={shop}
// Verify HMAC for security
function verifyHmac(query, secret) {
const { hmac, ...params } = query;
const message = Object.keys(params)
.sort()
.map(key => `${key}=${params[key]}`)
.join('&');
const hash = crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
return hash === hmac;
}Step 3: Exchange Code for Token
javascript
POST https://{shop}.myshopify.com/admin/oauth/access_token
// Body
{
"client_id": "{api_key}",
"client_secret": "{api_secret}",
"code": "{auth_code}"
}
// Response
{
"access_token": "shpat_...",
"scope": "write_products,read_orders"
}
// Node.js example
async function getAccessToken(shop, code, apiKey, apiSecret) {
const response = await fetch(
`https://${shop}/admin/oauth/access_token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: apiKey,
client_secret: apiSecret,
code,
}),
}
);
const { access_token, scope } = await response.json();
return { access_token, scope };
}自定义应用的完整OAuth流程。
步骤1:授权请求
GET https://{shop}.myshopify.com/admin/oauth/authorize?
client_id={api_key}&
redirect_uri={redirect_uri}&
scope={scopes}&
state={random_state}权限范围:
javascript
const scopes = [
'read_products',
'write_products',
'read_orders',
'write_orders',
'read_customers',
'write_customers',
'read_inventory',
'write_inventory',
'read_metafields',
'write_metafields',
].join(',');步骤2:处理回调
javascript
// 用户授权后,Shopify重定向至:
GET {redirect_uri}?code={auth_code}&state={state}&hmac={hmac}&shop={shop}
// 验证HMAC确保安全
function verifyHmac(query, secret) {
const { hmac, ...params } = query;
const message = Object.keys(params)
.sort()
.map(key => `${key}=${params[key]}`)
.join('&');
const hash = crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
return hash === hmac;
}步骤3:交换授权码获取访问令牌
javascript
POST https://{shop}.myshopify.com/admin/oauth/access_token
// 请求体
{
"client_id": "{api_key}",
"client_secret": "{api_secret}",
"code": "{auth_code}"
}
// 响应
{
"access_token": "shpat_...",
"scope": "write_products,read_orders"
}
// Node.js示例
async function getAccessToken(shop, code, apiKey, apiSecret) {
const response = await fetch(
`https://${shop}/admin/oauth/access_token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: apiKey,
client_secret: apiSecret,
code,
}),
}
);
const { access_token, scope } = await response.json();
return { access_token, scope };
}4. Rate Limiting
4. 速率限制
GraphQL uses points-based rate limiting.
Rate Limits:
- 50 cost points per second maximum
- Bucket refills at 50 points/second
- Each query has a calculated cost
Check Rate Limit:
javascript
const response = await fetch(graphqlEndpoint, options);
const rateLimitHeader = response.headers.get('X-Shopify-GraphQL-Admin-Api-Call-Limit');
// Example: "42/50" (42 points used, 50 max)
const [used, limit] = rateLimitHeader.split('/').map(Number);
if (used > 40) {
// Approaching limit, slow down
await delay(1000);
}Implement Retry Logic:
javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
// Rate limited
const retryAfter = response.headers.get('Retry-After') || 2;
await delay(retryAfter * 1000 * Math.pow(2, i)); // Exponential backoff
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}GraphQL采用基于点数的速率限制机制。
速率限制规则:
- 每秒最多50个点数
- 点数桶每秒补充50个点数
- 每个查询有对应的计算成本
检查速率限制:
javascript
const response = await fetch(graphqlEndpoint, options);
const rateLimitHeader = response.headers.get('X-Shopify-GraphQL-Admin-Api-Call-Limit');
// 示例:"42/50"(已使用42个点数,上限50)
const [used, limit] = rateLimitHeader.split('/').map(Number);
if (used > 40) {
// 接近限制,放缓请求
await delay(1000);
}实现重试逻辑:
javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
// 触发速率限制
const retryAfter = response.headers.get('Retry-After') || 2;
await delay(retryAfter * 1000 * Math.pow(2, i)); // 指数退避
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}5. Storefront API
5. Storefront API
Public API for headless/custom storefronts.
Endpoint:
POST https://{store}.myshopify.com/api/2025-10/graphql.jsonHeaders (Public Access):
javascript
{
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': '{public_token}' // Optional for public stores
}Query Products:
graphql
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
description
priceRange {
minVariantPrice { amount currencyCode }
maxVariantPrice { amount currencyCode }
}
images(first: 3) {
edges {
node {
url
altText
}
}
}
variants(first: 10) {
edges {
node {
id
title
price { amount currencyCode }
availableForSale
sku
}
}
}
}
}
}
}Cart Operations:
Create cart:
graphql
mutation CreateCart($input: CartInput!) {
cartCreate(input: $input) {
cart {
id
checkoutUrl
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
... on ProductVariant {
id
title
price { amount }
}
}
}
}
}
cost {
totalAmount { amount currencyCode }
subtotalAmount { amount }
totalTaxAmount { amount }
}
}
}
}Add to cart:
graphql
mutation AddToCart($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
id
lines(first: 10) {
edges {
node {
id
quantity
}
}
}
}
}
}用于无头/自定义店铺前端的公开API。
端点:
POST https://{store}.myshopify.com/api/2025-10/graphql.json请求头(公开访问):
javascript
{
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': '{public_token}' // 公开店铺可选
}查询商品:
graphql
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
description
priceRange {
minVariantPrice { amount currencyCode }
maxVariantPrice { amount currencyCode }
}
images(first: 3) {
edges {
node {
url
altText
}
}
}
variants(first: 10) {
edges {
node {
id
title
price { amount currencyCode }
availableForSale
sku
}
}
}
}
}
}
}购物车操作:
创建购物车:
graphql
mutation CreateCart($input: CartInput!) {
cartCreate(input: $input) {
cart {
id
checkoutUrl
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
... on ProductVariant {
id
title
price { amount }
}
}
}
}
}
cost {
totalAmount { amount currencyCode }
subtotalAmount { amount }
totalTaxAmount { amount }
}
}
}
}添加商品到购物车:
graphql
mutation AddToCart($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
id
lines(first: 10) {
edges {
node {
id
quantity
}
}
}
}
}
}6. Ajax API (Theme-Only)
6. Ajax API(仅主题可用)
JavaScript API for cart operations in themes.
Get Cart:
javascript
fetch('/cart.js')
.then(response => response.json())
.then(cart => {
console.log('Cart:', cart);
console.log('Item count:', cart.item_count);
console.log('Total:', cart.total_price);
console.log('Items:', cart.items);
});Add to Cart:
javascript
fetch('/cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: variantId, // Required: variant ID
quantity: 1, // Optional: default 1
properties: { // Optional: custom data
'Gift wrap': 'Yes',
'Note': 'Happy Birthday!'
}
})
})
.then(response => response.json())
.then(item => {
console.log('Added to cart:', item);
})
.catch(error => {
console.error('Error:', error);
});Update Cart:
javascript
fetch('/cart/change.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
line: 1, // Line item index (1-based)
quantity: 2 // New quantity (0 = remove)
})
})
.then(response => response.json())
.then(cart => console.log('Updated cart:', cart));Clear Cart:
javascript
fetch('/cart/clear.js', { method: 'POST' })
.then(response => response.json())
.then(cart => console.log('Cart cleared'));Update Cart Attributes:
javascript
fetch('/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
attributes: {
'gift_wrap': 'true',
'gift_message': 'Happy Birthday!'
},
note: 'Please handle with care'
})
})
.then(response => response.json())
.then(cart => console.log('Cart updated'));用于主题中购物车操作的JavaScript API。
获取购物车信息:
javascript
fetch('/cart.js')
.then(response => response.json())
.then(cart => {
console.log('Cart:', cart);
console.log('Item count:', cart.item_count);
console.log('Total:', cart.total_price);
console.log('Items:', cart.items);
});添加商品到购物车:
javascript
fetch('/cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: variantId, // 必填:商品变体ID
quantity: 1, // 可选:默认1
properties: { // 可选:自定义数据
'Gift wrap': 'Yes',
'Note': 'Happy Birthday!'
}
})
})
.then(response => response.json())
.then(item => {
console.log('Added to cart:', item);
})
.catch(error => {
console.error('Error:', error);
});更新购物车:
javascript
fetch('/cart/change.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
line: 1, // 商品行索引(从1开始)
quantity: 2 // 新数量(0表示移除)
})
})
.then(response => response.json())
.then(cart => console.log('Updated cart:', cart));清空购物车:
javascript
fetch('/cart/clear.js', { method: 'POST' })
.then(response => response.json())
.then(cart => console.log('Cart cleared'));更新购物车属性:
javascript
fetch('/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
attributes: {
'gift_wrap': 'true',
'gift_message': 'Happy Birthday!'
},
note: 'Please handle with care'
})
})
.then(response => response.json())
.then(cart => console.log('Cart updated'));7. Webhooks
7. Webhook
Event-driven notifications for app integrations.
Common Webhooks:
javascript
// Product events
'products/create'
'products/update'
'products/delete'
// Order events
'orders/create'
'orders/updated'
'orders/paid'
'orders/fulfilled'
'orders/cancelled'
// Customer events
'customers/create'
'customers/update'
'customers/delete'
// Cart events
'carts/create'
'carts/update'
// Inventory events
'inventory_levels/update'
// App events
'app/uninstalled'Register Webhook (GraphQL):
graphql
mutation CreateWebhook($input: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(input: $input) {
webhookSubscription {
id
topic
endpoint {
__typename
... on WebhookHttpEndpoint {
callbackUrl
}
}
}
userErrors {
field
message
}
}
}Variables:
json
{
"input": {
"topic": "ORDERS_CREATE",
"webhookSubscription": {
"callbackUrl": "https://your-app.com/webhooks/orders",
"format": "JSON"
}
}
}Handle Webhook (Node.js/Express):
javascript
app.post('/webhooks/orders', async (req, res) => {
// Verify webhook HMAC
const hmac = req.headers['x-shopify-hmac-sha256'];
const body = JSON.stringify(req.body);
const hash = crypto
.createHmac('sha256', SHOPIFY_WEBHOOK_SECRET)
.update(body)
.digest('base64');
if (hash !== hmac) {
return res.status(401).send('Invalid HMAC');
}
// Process order
const order = req.body;
console.log('New order:', order.id, order.email);
// Respond quickly (within 5 seconds)
res.status(200).send('OK');
// Process in background
await processOrder(order);
});用于应用集成的事件驱动通知。
常见Webhook主题:
javascript
// 商品事件
'products/create'
'products/update'
'products/delete'
// 订单事件
'orders/create'
'orders/updated'
'orders/paid'
'orders/fulfilled'
'orders/cancelled'
// 客户事件
'customers/create'
'customers/update'
'customers/delete'
// 购物车事件
'carts/create'
'carts/update'
// 库存事件
'inventory_levels/update'
// 应用事件
'app/uninstalled'注册Webhook(GraphQL):
graphql
mutation CreateWebhook($input: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(input: $input) {
webhookSubscription {
id
topic
endpoint {
__typename
... on WebhookHttpEndpoint {
callbackUrl
}
}
}
userErrors {
field
message
}
}
}变量:
json
{
"input": {
"topic": "ORDERS_CREATE",
"webhookSubscription": {
"callbackUrl": "https://your-app.com/webhooks/orders",
"format": "JSON"
}
}
}处理Webhook(Node.js/Express):
javascript
app.post('/webhooks/orders', async (req, res) => {
// 验证Webhook HMAC
const hmac = req.headers['x-shopify-hmac-sha256'];
const body = JSON.stringify(req.body);
const hash = crypto
.createHmac('sha256', SHOPIFY_WEBHOOK_SECRET)
.update(body)
.digest('base64');
if (hash !== hmac) {
return res.status(401).send('Invalid HMAC');
}
// 处理订单
const order = req.body;
console.log('New order:', order.id, order.email);
// 快速响应(5秒内)
res.status(200).send('OK');
// 后台处理
await processOrder(order);
});Common Patterns
常见模式
Pagination (GraphQL)
分页(GraphQL)
javascript
async function getAllProducts(accessToken, store) {
let allProducts = [];
let hasNextPage = true;
let cursor = null;
while (hasNextPage) {
const query = `
query GetProducts($first: Int!, $after: String) {
products(first: $first, after: $after) {
edges {
node { id title }
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables: { first: 50, after: cursor },
}),
});
const { data } = await response.json();
allProducts.push(...data.products.edges.map(e => e.node));
hasNextPage = data.products.pageInfo.hasNextPage;
cursor = data.products.pageInfo.endCursor;
}
return allProducts;
}javascript
async function getAllProducts(accessToken, store) {
let allProducts = [];
let hasNextPage = true;
let cursor = null;
while (hasNextPage) {
const query = `
query GetProducts($first: Int!, $after: String) {
products(first: $first, after: $after) {
edges {
node { id title }
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables: { first: 50, after: cursor },
}),
});
const { data } = await response.json();
allProducts.push(...data.products.edges.map(e => e.node));
hasNextPage = data.products.pageInfo.hasNextPage;
cursor = data.products.pageInfo.endCursor;
}
return allProducts;
}Error Handling
错误处理
javascript
async function safeApiCall(query, variables) {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const { data, errors } = await response.json();
if (errors) {
console.error('GraphQL Errors:', errors);
throw new Error(errors[0].message);
}
return data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
}javascript
async function safeApiCall(query, variables) {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const { data, errors } = await response.json();
if (errors) {
console.error('GraphQL Errors:', errors);
throw new Error(errors[0].message);
}
return data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
}Best Practices
最佳实践
- Always check API version - Use latest stable (2025-10)
- Implement rate limit handling - Use exponential backoff
- Verify webhook HMAC - Security critical
- Use GraphQL over REST when possible - More efficient
- Request only needed fields - Reduce response size
- Handle errors gracefully - Check and
errorsuserErrors - Store access tokens securely - Never expose in client code
- Use minimum necessary scopes - Security best practice
- Implement retry logic - Handle transient failures
- Respond to webhooks quickly - Within 5 seconds
- 始终检查API版本 - 使用最新稳定版(2025-10)
- 实现速率限制处理 - 使用指数退避策略
- 验证Webhook HMAC - 安全关键步骤
- 优先使用GraphQL而非REST - 更高效
- 仅请求所需字段 - 减小响应体积
- 优雅处理错误 - 检查和
errorsuserErrors - 安全存储访问令牌 - 绝不在客户端代码中暴露
- 使用最小必要权限范围 - 安全最佳实践
- 实现重试逻辑 - 处理临时故障
- 快速响应Webhook - 5秒内完成响应
Detailed References
详细参考
- references/graphql-queries.md - Complete query examples
- references/rest-endpoints.md - All REST endpoints
- references/webhook-payloads.md - Webhook payload structures
- references/graphql-queries.md - 完整查询示例
- references/rest-endpoints.md - 所有REST端点
- references/webhook-payloads.md - Webhook负载结构
Integration with Other Skills
与其他技能集成
- shopify-app-dev - Use when building custom Shopify apps
- shopify-liquid - Use when displaying API data in theme templates
- shopify-debugging - Use when troubleshooting API errors
- shopify-performance - Use when optimizing API request patterns
- shopify-app-dev - 构建自定义Shopify应用时使用
- shopify-liquid - 在主题模板中展示API数据时使用
- shopify-debugging - 排查API错误时使用
- shopify-performance - 优化API请求模式时使用
Quick Reference
快速参考
javascript
// GraphQL Admin API
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }
// REST Admin API
GET https://{store}.myshopify.com/admin/api/2025-10/products.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }
// Storefront API
POST https://{store}.myshopify.com/api/2025-10/graphql.json
Headers: { 'X-Shopify-Storefront-Access-Token': 'token' }
// Ajax API (theme)
fetch('/cart.js')
fetch('/cart/add.js', { method: 'POST', body: ... })
fetch('/cart/change.js', { method: 'POST', body: ... })javascript
// GraphQL Admin API
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }
// REST Admin API
GET https://{store}.myshopify.com/admin/api/2025-10/products.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }
// Storefront API
POST https://{store}.myshopify.com/api/2025-10/graphql.json
Headers: { 'X-Shopify-Storefront-Access-Token': 'token' }
// Ajax API (主题)
fetch('/cart.js')
fetch('/cart/add.js', { method: 'POST', body: ... })
fetch('/cart/change.js', { method: 'POST', body: ... })