{/ Эта страница автоматически создается на основе файла SKILL.md навыка с помощью сайта site/scripts/generate-skill-docs.py. Редактируйте исходный код SKILL.md, а не эту страницу. /}
Shopify
Shopify Admin & Storefront API GraphQL через Curl. Товары, заказы, клиенты, инвентарь, метаполя.
Метаданные навыков
Источник
Необязательно — установите с помощью hermesskills installofficial/productivity/shopify
Ниже приведено полное определение навыка, которое Гермес загружает при активации этого навыка. Это то, что агент видит в качестве инструкций, когда навык активен.
Shopify — API GraphQL для администрирования и витрины магазина
Работайте с магазинами Shopify напрямую через «curl»: составляйте список продуктов, управляйте запасами, оформляйте заказы, обновляйте информацию о клиентах, читайте метаполя. Никакого SDK, никакой платформы приложений — только конечная точка GraphQL и токен доступа к пользовательскому приложению.
REST Admin API является устаревшим с 2024-04 года и получает только исправления безопасности. Используйте GraphQL Admin для всей административной работы. Используйте Storefront GraphQL для запросов к клиентам, доступных только для чтения (продукты, коллекции, корзина).
Предварительные условия
В админке Shopify: Настройки → Приложения и каналы продаж → Разработка приложений → Создать приложение.
Нажмите Настроить области Admin API, выберите то, что вам нужно (примеры ниже), сохраните.
Установить приложение → токен доступа к Admin API появляется ОДИН РАЗ. Скопируйте его немедленно — Shopify больше никогда его не покажет. Токены начинаются с shpat_.
Сохраните в ~/.hermes/.env:
SHOPIFY_ACCESS_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxx
SHOPIFY_STORE_DOMAIN=my-store.myshopify.com
SHOPIFY_API_VERSION=2026-01
Внимание! С 1 января 2026 г. новые «устаревшие пользовательские приложения», созданные в администраторе Shopify, исчезли. В новых настройках следует использовать Панель разработки (shopify.dev/docs/apps/build/dev-dashboard). Существующие приложения, созданные администратором, продолжают работать. Если в магазине пользователя нет пользовательского приложения и оно выпущено после 01 января 2026 г., направьте его на панель управления разработчиком вместо процесса администрирования.
Общие области применения по задачам:
- Товары/коллекции: 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
- Метаполя/метаобъекты: охватываются соответствующими областями ресурсов.
Заголовок аутентификации:X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN (НЕ Authorization: Bearer)
Метод: всегда POST, всегда Content-Type: application/json, тело — {"query": "...", "variables": {...}}
HTTP 200 не означает успех. GraphQL возвращает ошибки в массиве errors верхнего уровня и userErrors для каждого поля. Всегда проверяйте оба.
Идентификаторы представляют собой строки GID:gid://shopify/Product/10079467700516, gid://shopify/Variant/..., gid://shopify/Order/.... Передайте это дословно — не удаляйте префикс.
– Ограничение скорости: рассчитывается на основе стоимости запроса (дырявое ведро). Каждый ответ имеет extensions.cost с requestedQueryCost, actualQueryCost, throttleStatus.{currentlyAvailable, MaximumAvailable, RestorateRate}. Отступите, когда значение «currentlyAvailable» упадет ниже стоимости вашего следующего запроса. Стандартные магазины = ведро 100 очков, восстановление 50/с; Плюс = 1000/100.
Запасы основаны на инвентарных позициях, привязанных к вариантам, количество отслеживается по местоположению.
# 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:
Установить абсолютный запас (не дельту) — 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."}]}'
API витрины (публичный, только для чтения)
Другая конечная точка, другой токен, используемый для приложений, ориентированных на клиента, или автономных установок в стиле Hydrogen. Заголовки различаются:
Заголовок аутентификации (публичный):X-Shopify-Storefront-Access-Token: <public token> — встраивается в браузер
Заголовок аутентификации (частный):Shopify-Storefront-Private-Token: <частный токен> — только для сервера
curl-sS-XPOST\"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. При необходимости пересоберите клиентскую часть.
Вебхуки
Подпишитесь на события, чтобы не проводить опросы:
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"}}'
Проверьте входящий веб-перехватчик HMAC, используя секрет клиента приложения (а не токен доступа):
echo-n"$REQUEST_BODY"|openssldgst-sha256-hmac"$APP_SECRET"-binary|base64
# Compare to X-Shopify-Hmac-Sha256 header
Подводные камни
Конечные точки REST все еще существуют, но заморожены. Не создавайте новые интеграции с /admin/api/.../products.json. Используйте ГрафQL.
Проверка формата токена. Токены администратора начинаются с shpat_. Публичные токены витрины магазина с shpua_. Если у вас один и неправильный заголовок, каждый запрос возвращает 401 без полезного тела ошибки.
403 с действительным токеном = отсутствует область действия. Shopify возвращает {"errors":[{"message":"Доступ запрещен для..."}]}. Перенастройте области Admin API в приложении, а затем переустановите его, чтобы повторно создать токен.
userErrors пусто!= успех. Также проверьте, что data.<mutation>.<resource> не является нулевым. Некоторые ошибки не заполняют ни один из них — проверьте весь ответ.
GID против числового идентификатора. Устаревший REST предоставлял числовые идентификаторы; GraphQL требует полные строки GID. Чтобы преобразовать: gid://shopify/Product/<numeric>.
Сюрприз по ограничению ставок. Один «продукт (сначала: 250)» с глубокой вложенностью может стоить более 1000 баллов и немедленно ограничиваться в магазине со стандартным планом. Начните с узкого, прочтите «extensions.cost», скорректируйте.
Порядок нумерации страниц.products(first: N, обратный: true) сортируется по id DESC, а не create_at. Используйте sortKey: CREATED_AT, обратный: true для «сначала самые новые».
read_all_orders для исторических данных. Без него orders(...) автоматически ограничивается 60-дневным окном. Вы не получите ошибки, просто результатов будет меньше, чем ожидалось. Для продавцов Shopify Plus с большим количеством заказов запросите эту область через настройки защищенных данных приложения.
Валюты представляют собой строки. Суммы возвращаются как «49,00», а не как «49,0». Не используйте jq tonumber вслепую, если вас волнует заполнение нулями.
Мультивалютные поля «Деньги» содержат shopMoney (валюта магазина) И presentmentMoney (валюта клиента). Выбирайте один последовательно.
Безопасность
Мутации в Shopify реальны — они создают продукты, взимают возвраты, отменяют заказы, отправляют заказы. Прежде чем запускать productDelete, orderCancel, refundCreate или любую массовую мутацию: четко укажите, в чем заключается изменение, в каком магазине, и подтвердите это пользователю. Промежуточного клона производственных данных не существует, если у пользователя нет отдельного хранилища разработки.