Chuyển tới nội dung chính

{/* Trang này được tạo tự động từ SKILL.md của kỹ năng bởi website/scripts/generate-skill-docs.py. Chỉnh sửa nguồn SKILL.md, không phải trang này. */}

Shopify

API GraphQL của quản trị viên & mặt tiền cửa hàng Shopify thông qua tính năng cuộn tròn. Sản phẩm, đơn đặt hàng, khách hàng, hàng tồn kho, siêu trường dữ liệu.

Siêu dữ liệu kỹ năng

NguồnTùy chọn — cài đặt với
`Hermes skills install official/productivity/shopify
`
Đường dẫn

optional-skills/productivity/shopify ` | | Phiên bản |

1.0.0 ` | | Tác giả | cộng đồng | | Giấy phép | MIT | | Nền tảng | Linux, macOS, Windows | | Thẻ |

Shopify

, `E-commerce

, `Commerce

, `API

, GraphQL | | Kỹ năng liên quan | XPROTECTX29XPROTECTX, XPROTECTX30XPROTECTX |

Tham khảo: đầy đủ SKILL.md

thông tin

Sau đây là định nghĩa kỹ năng đầy đủ mà Hermes tải khi kỹ năng này được kích hoạt. Đây là những gì tác nhân coi là hướng dẫn khi kỹ năng được kích hoạt.

Shopify — API GraphQL của quản trị viên và mặt tiền cửa hàng

Làm việc trực tiếp với các cửa hàng Shopify thông qua `curl

: liệt kê sản phẩm, quản lý hàng tồn kho, lấy đơn hàng, cập nhật khách hàng, đọc siêu trường dữ liệu. Không có SDK, không có khung ứng dụng — chỉ có điểm cuối GraphQL và mã thông báo truy cập ứng dụng tùy chỉnh.

API quản trị REST là cũ kể từ năm 2024-2004 và chỉ nhận được các bản sửa lỗi bảo mật. Sử dụng Quản trị viên GraphQL cho tất cả công việc của quản trị viên. Sử dụng Storefront GraphQL cho các truy vấn chỉ đọc dành cho khách hàng (sản phẩm, bộ sưu tập, giỏ hàng).

Điều kiện tiên quyết

  1. Trong trang quản trị Shopify: Cài đặt → Ứng dụng và kênh bán hàng → Phát triển ứng dụng → Tạo ứng dụng.
  2. Nhấp vào Định cấu hình phạm vi API quản trị, chọn những gì bạn cần (ví dụ bên dưới), lưu lại.
  3. Cài đặt ứng dụng → mã thông báo truy cập API quản trị xuất hiện MỘT LẦN. Sao chép ngay lập tức — Shopify sẽ không bao giờ hiển thị lại. Mã thông báo bắt đầu bằng `shpat_

. 4. Lưu vào

~/.Hermes/.env

:

` SHOPIFY_ACCESS_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxx SHOPIFY_STORE_DOMAIN=my-store.myshopify.com SHOPIFY_API_VERSION=2026-01

``> Lưu ý: Kể từ ngày 1 tháng 1 năm 2026, "ứng dụng tùy chỉnh cũ" mới được tạo trong trang quản trị Shopify sẽ không còn nữa. Các thiết lập mới nên sử dụng Trang tổng quan dành cho nhà phát triển ( `shopify.dev/docs/apps/build/dev-dashboard

). Các ứng dụng hiện có do quản trị viên tạo vẫn tiếp tục hoạt động. Nếu cửa hàng của người dùng hiện không có ứng dụng tùy chỉnh nào và sau ngày 01 tháng 1 năm 2026, hãy hướng họ tới Bảng thông tin dành cho nhà phát triển thay vì luồng quản trị viên.

Phạm vi chung theo nhiệm vụ:

  • Sản phẩm/bộ sưu tập: `read_products

, `write_products

  • Hàng tồn kho: `read_inventory

, `write_inventory

, `read_locations

  • Đơn hàng: `read_orders

, write_orders (30 đơn hàng gần đây nhất không có `read_all_orders

)

  • Khách hàng: `read_customers

, `write_customers

  • Lệnh nháp: `read_draft_orders

, `write_draft_orders

  • Thực hiện: `read_fulfiLLMents

, `write_fulfiLLMents

  • Siêu trường dữ liệu / siêu đối tượng: được bao phủ bởi phạm vi tài nguyên phù hợp

API cơ bản

  • Điểm cuối: `https://$SHOPIFY_STORE_DOMAIN/admin/API/$SHOPIFY_API_VERSION/graphql.JSON

  • Tiêu đề xác thực: X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN (KHÔNG phải `Authorization: Bearer

)

  • Phương thức: luôn là `POST

, luôn là `Content-Type: application/JSON

, phần thân là

{"query": "...", "variables": {...}}

  • HTTP 200 không có nghĩa là thành công. GraphQL trả về lỗi trong mảng errors cấp cao nhất và userErrors trên mỗi trường. Luôn kiểm tra cả hai.
  • ID là chuỗi GID: `gid://shopify/Product/10079467700516

, `gid://shopify/Variant/...

, `gid://shopify/Order/...

. Truyền nguyên văn những điều này - không loại bỏ tiền tố.

  • Giới hạn tỷ lệ: được tính thông qua chi phí truy vấn (nhóm bị rò rỉ). Mỗi phản hồi có extensions.cost với `requestedQueryCost

, `actualQueryCost

, `throttleStatus.{currentlyAvailable, maximumAvailable, restoreRate}

. Hãy dừng lại khi currentlyAvailable giảm xuống dưới mức chi phí cho truy vấn tiếp theo của bạn. Cửa hàng tiêu chuẩn = nhóm 100 điểm, khôi phục 50/s; Cộng = 1000/100.

Mẫu uốn cong cơ bản (có thể tái sử dụng):

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}')"
}

`
``Truyền qua
`jq
` để có đầu ra có thể đọc được.

-sS
` hiển thị lỗi nhưng ẩn thanh tiến trình.`##Khám phá

### Thông tin cửa hàng + phiên bản API hiện tại

`
``` bash
shop_gql '{ shop { name myshopifyDomain primaryDomain { url } currencyCode plan { displayName } } }' | jq

`

### Liệt kê tất cả các phiên bản API được hỗ trợ

`
`bash
shop_gql '{ publicAPIVersions { handle supported } }' | jq '.data.publicAPIVersions[] | select(.supported)'

`

## Sản phẩm

### Tìm kiếm sản phẩm (20 truy vấn phù hợp đầu tiên)

`
`bash
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

`
``Cú pháp truy vấn hỗ trợ
`title:

,
`sku:

,
`vendor:

,
`product_type:

,
`status:active

,
`tag:

,
`created_at:>2025-01-01

. Ngữ pháp đầy đủ: https://shopify.dev/docs/API/usage/search-syntax

### Phân trang sản phẩm (con trỏ)

`
`bash
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

`

### Nhận sản phẩm có biến thể + siêu trường dữ liệu

`
``` bash
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

`

### Tạo sản phẩm với một mẫu mã

`
`bash
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"]}}'

`
``Các biến thể hiện có đột biến riêng trong các phiên bản gần đây:

`bash

# 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}}]}'

`

### Cập nhật giá/SKU

`
``` bash
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"}]}'

`

## Đơn hàng### Liệt kê các đơn hàng gần đây (30 đơn hàng gần nhất theo mặc định không có
`read_all_orders

)

`
`bash
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

`
``Bộ lọc truy vấn đơn hàng hữu ích:
`financial_status:paid|pending|refunded

,
`fulfiLLMent_status:unfulfilled|fulfilled

,
`created_at:>2025-01-01

,
`tag:gift

,
`email:foo@example.com

.

### Lấy một đơn hàng có địa chỉ giao hàng

`
`bash
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

`

## Khách hàng

`bash

# 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"]}}'

`

## Hàng tồn kho

Khoảng không quảng cáo tồn tại dựa trên **các mặt hàng trong kho** gắn với các biến thể, số lượng được theo dõi trên mỗi **vị trí**.

``` bash

# 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/..."}'

`
``Điều chỉnh cổ phiếu (delta) - sử dụng
`inventoryAdjustQuantities

:

``` bash
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/..."}]
}
}'

`
``Đặt cổ phiếu tuyệt đối (không phải delta) -
`inventorySetQuantities

:

`bash
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}]}}'

`

## Siêu trường & Siêu đối tượng

Siêu trường đính kèm dữ liệu tùy chỉnh vào tài nguyên (sản phẩm, khách hàng, đơn đặt hàng, cửa hàng).

`bash

# 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."}]}'

`

## API mặt tiền cửa hàng (chỉ đọc công khai)

Điểm cuối khác nhau, mã thông báo khác nhau, được sử dụng cho các ứng dụng hướng tới khách hàng/thiết lập không đầu kiểu hydro. Tiêu đề khác nhau:
- **Điểm cuối:**
`https://$SHOPIFY_STORE_DOMAIN/API/$SHOPIFY_API_VERSION/graphql.JSON

- **Tiêu đề xác thực (công khai):**
`X-Shopify-Storefront-Access-Token: <public token
` — có thể nhúng trong trình duyệt
- **Tiêu đề xác thực (riêng tư):**
`Shopify-Storefront-Private-Token: <private token
` — chỉ dành cho máy chủ

``` bash
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

`

## Hoạt động hàng loạt

Đối với các bãi thải lớn hơn giới hạn tỷ lệ cho phép (danh mục sản phẩm đầy đủ, tất cả các đơn đặt hàng trong một năm):

``` bash

# 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

`
``Mỗi dòng JSONL là một nút và các kết nối lồng nhau được phát ra dưới dạng các dòng riêng biệt với
`__parentId

. Lắp ráp lại phía khách hàng nếu cần.

## Webhook

Đăng ký các sự kiện để bạn không phải thăm dò ý kiến:

``` bash
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"}}'

`
``Xác minh webhook HMAC đến bằng bí mật ứng dụng khách của ứng dụng (không phải mã thông báo truy cập):

`bash
echo -n "$REQUEST_BODY" | openSSL dgst -sha256 -hmac "$APP_SECRET" -binary | base64

# Compare to X-Shopify-Hmac-Sha256 header

`

## cạm bẫy
- **Điểm cuối REST vẫn tồn tại nhưng đã bị đóng băng.** Không viết các phần tích hợp mới chống lại

/admin/API/.../products.JSON

. Sử dụng GraphQL.
- **Kiểm tra định dạng mã thông báo.** Mã thông báo quản trị bắt đầu bằng
`shpat_

. Mã thông báo công khai trên cửa hàng với
`shpua_

. Nếu bạn có một và tiêu đề sai, mọi yêu cầu đều trả về 401 mà không có nội dung lỗi hữu ích.
- **403 có mã thông báo hợp lệ = thiếu phạm vi.** Shopify trả về

\{"errors":[\{"message":"Access denied for ..."}]}

. Định cấu hình lại phạm vi API quản trị trên ứng dụng, sau đó cài đặt lại để tạo lại mã thông báo.
- **
`userErrors
` trống != thành công.** Đồng thời kiểm tra
`data.<mutation.<resource
` có phải là không rỗng không. Một số lỗi không xuất hiện - hãy kiểm tra toàn bộ phản hồi.
- **GID so với ID số.** REST kế thừa cung cấp ID số; GraphQL muốn chuỗi GID đầy đủ. Để chuyển đổi:
`gid://shopify/Product/<numeric

.
- **Giới hạn tỷ lệ bất ngờ.** Một
`products(first: 250)
` duy nhất có khả năng lồng sâu có thể tiêu tốn hơn 1000 điểm và tăng tốc ngay lập tức tại cửa hàng có gói tiêu chuẩn. Bắt đầu thu hẹp, đọc
`extensions.cost

, điều chỉnh.
- **Thứ tự phân trang.**
`products(first: N, reverse: true)
` sắp xếp theo
`id DESC

, không phải
`created_at

. Sử dụng
`sortKey: CREATED_AT, reverse: true
` cho "mới nhất trước tiên".
- **
`read_all_orders
` để biết dữ liệu lịch sử.** Nếu không có nó,
`orders(...)
` sẽ âm thầm giới hạn trong thời hạn 60 ngày. Bạn sẽ không gặp lỗi, chỉ có kết quả ít hơn mong đợi. Đối với thương nhân dùng Shopify Plus có nhiều đơn hàng, hãy yêu cầu phạm vi này thông qua cài đặt dữ liệu được bảo vệ của ứng dụng.
- **Tiền tệ là chuỗi.** Số tiền trả về dưới dạng

"49.00"
` chứ không phải
`49.0

. Đừng
`jq tonumber
` một cách mù quáng nếu bạn quan tâm đến phần đệm bằng 0.
- **Các trường Tiền nhiều loại tiền** có
`shopMoney
` (tiền của cửa hàng)
`presentmentMoney
` (của khách hàng). Chọn một cách nhất quán.

## An toàn

Đột biến trong Shopify là có thật — họ tạo ra sản phẩm, tính tiền hoàn lại, hủy đơn hàng, thực hiện đơn hàng. Trước khi chạy
`productDelete

,
`orderCancel

,
`refundCreate
` hoặc bất kỳ đột biến hàng loạt nào: nêu rõ thay đổi là gì, ở cửa hàng nào và xác nhận với người dùng. Không có bản sao dàn dựng của dữ liệu sản xuất trừ khi người dùng có cửa hàng phát triển riêng.