@kody/shopify
Shopify Admin API helpers for products, orders, customers, and GraphQL — secret-backed, no OAuth app.
AGENTS.md
144 lines · 4.6 KB · Markdown@kody/shopify — agent notes
Human setup and intent live in README.md. This file is for
agents: imports, smoke/dryRun execute snippets, and edge cases. Secrets by
name only — never paste token values. Do not disable live webhooks or jobs.
Auth
| Lane | Credential | Notes |
|---|---|---|
| Preferred | User secrets shopifyClientId + shopifyClientSecret | Dev Dashboard client credentials; token exchanged per invoke |
| Legacy | User secret shopifyAdminAccessToken | Static Admin token (shpat_…); wins if present |
Pass shop: "your-store" (myshopify subdomain) on each call. Approve host
{shop}.myshopify.com. Default API version 2026-07 (apiVersion override).
No platform Shopify OAuth integration.
Import paths
| Export | Import |
|---|---|
| package overview | kody:@kody/shopify |
| graphql | kody:@kody/shopify/graphql |
| request | kody:@kody/shopify/request |
| shop | kody:@kody/shopify/shop |
| products | kody:@kody/shopify/products |
| orders | kody:@kody/shopify/orders |
| customers | kody:@kody/shopify/customers |
| inventory | kody:@kody/shopify/inventory |
| collections | kody:@kody/shopify/collections |
| fulfillments | kody:@kody/shopify/fulfillments |
| draft-orders | kody:@kody/shopify/draft-orders |
| webhooks | kody:@kody/shopify/webhooks |
| metafields | kody:@kody/shopify/metafields |
| config | kody:@kody/shopify/config |
| smoke-test | kody:@kody/shopify/smoke-test |
| types | kody:@kody/shopify/types |
Prefer static kody:@kody/shopify/... imports from execute. Do not lead with
packages.invoke.
Default exports: ./graphql → graphql; ./request → shopifyRequest;
./shop → getShop; ./products → listProducts; ./orders → listOrders;
./customers → listCustomers; ./inventory → listLocations;
./collections → listCollections; ./fulfillments → listFulfillmentOrders;
./draft-orders → listDraftOrders; ./webhooks → listWebhooks;
./metafields → listMetafields; ./config → getConfig;
./smoke-test → smokeTest.
Smoke test
./smoke-test always runs local shop/id helper checks. When shop and
credentials are present it also reads shop { name }.
import smokeTest from 'kody:@kody/shopify/smoke-test'
export default async function main() {
return await smokeTest({ shop: 'acme' })
}Common snippets
Read shop, products, unpaid orders:
import { getShop } from 'kody:@kody/shopify/shop'
import { listProducts } from 'kody:@kody/shopify/products'
import { listOrders } from 'kody:@kody/shopify/orders'
export default async function main() {
const shop = await getShop({ shop: 'acme' })
const products = await listProducts({
shop: 'acme',
query: 'status:active',
first: 10,
})
const unpaid = await listOrders({
shop: 'acme',
query: 'financial_status:pending',
first: 10,
})
return { shop, products, unpaid }
}Unwrapped GraphQL:
import { shopifyGraphql } from 'kody:@kody/shopify/graphql'
export default async function main() {
return await shopifyGraphql({
shop: 'acme',
query: `query ($query: String) {
products(first: 5, query: $query) {
nodes { id title handle }
}
}`,
variables: { query: 'vendor:acme' },
})
}dryRun (writes)
Writes default to dry-run. Pass dryRun: false only after the user
confirms the exact shop and mutation.
import { createProduct } from 'kody:@kody/shopify/products'
export default async function main() {
const preview = await createProduct({
shop: 'acme',
title: 'Hiking backpack',
status: 'DRAFT',
})
// => { dryRun: true, wouldCall: { mutation: 'productCreate', product: { ... } } }
const created = await createProduct({
shop: 'acme',
title: 'Hiking backpack',
status: 'DRAFT',
dryRun: false,
})
return { preview, created }
}Edge cases / fork notes
- GraphQL is the supported Admin surface. REST remains as
./requestfor older resources still documented there. - Requests stay on
{shop}.myshopify.com/admin/…. Arbitrary hosts are rejected. - Client-credentials tokens are requested per invoke and never written to
packageStorage(). - Rate limits: GraphQL uses calculated query cost; REST is 40 req/min (higher
on Shopify Plus). The client retries
429/5xxand honorsRetry-After. - Helpers project slim objects. Use
./graphqlwhen you need extra fields. - Numeric ids are accepted and normalized to
gid://shopify/{Type}/{id}. - Fork first: do not treat live
@kody/shopifypackageStorage()as yours. - Never paste Shopify client secrets or Admin access tokens into chat or logs.