shopify-api-patterns

Shopify API Patterns Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "shopify-api-patterns" with this command: npx skills add sarojpunde/shopify-dev-toolkit-claude-plugins/sarojpunde-shopify-dev-toolkit-claude-plugins-shopify-api-patterns

Shopify API Patterns Skill

Purpose

Provides reusable patterns for common Shopify Admin GraphQL API operations including product queries, metafield management, webhook handling, and bulk operations.

When This Skill Activates

  • Working with Shopify Admin GraphQL API

  • Querying products, variants, customers, or orders

  • Managing metafields

  • Implementing webhooks

  • Handling bulk operations

  • Implementing rate limiting

Core Patterns

  1. Product Query with Pagination

query getProducts($first: Int!, $after: String) { products(first: $first, after: $after) { edges { node { id title vendor handle productType tags variants(first: 10) { edges { node { id title price sku } } } } cursor } pageInfo { hasNextPage endCursor } } }

  1. Metafield Query Pattern

query getProductMetafields($productId: ID!) { product(id: $productId) { id title metafields(first: 20, namespace: "custom") { edges { node { id namespace key value type } } } } }

  1. Metafield Update Mutation

mutation updateMetafields($metafields: [MetafieldsSetInput!]!) { metafieldsSet(metafields: $metafields) { metafields { id namespace key value type } userErrors { field message } } }

Usage Example:

const response = await admin.graphql(UPDATE_METAFIELDS, { variables: { metafields: [ { ownerId: "gid://shopify/Product/123", namespace: "custom", key: "color", value: "Red", type: "single_line_text_field", }, ], }, });

  1. Metafield Definition Creation

mutation createMetafieldDefinition($definition: MetafieldDefinitionInput!) { metafieldDefinitionCreate(definition: $definition) { createdDefinition { id name namespace key type ownerType } userErrors { field message } } }

Usage:

await admin.graphql(CREATE_METAFIELD_DEFINITION, { variables: { definition: { name: "Product Color", namespace: "custom", key: "color", type: "single_line_text_field", ownerType: "PRODUCT", }, }, });

  1. Webhook Registration

mutation registerWebhook($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) { webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) { webhookSubscription { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } } userErrors { field message } } }

Common Topics:

  • PRODUCTS_CREATE

  • PRODUCTS_UPDATE

  • PRODUCTS_DELETE

  • ORDERS_CREATE

  • CUSTOMERS_CREATE

  1. Pagination Helper

async function fetchAllProducts(admin) { let hasNextPage = true; let cursor = null; const allProducts = [];

while (hasNextPage) { const response = await admin.graphql(GET_PRODUCTS, { variables: { first: 250, after: cursor }, });

const data = await response.json();

if (data.errors) {
  throw new Error(`GraphQL error: ${data.errors[0].message}`);
}

const products = data.data.products.edges.map(edge => edge.node);
allProducts.push(...products);

hasNextPage = data.data.products.pageInfo.hasNextPage;
cursor = data.data.products.pageInfo.endCursor;

// Rate limiting check
const rateLimitCost = response.headers.get("X-Shopify-Shop-Api-Call-Limit");
if (rateLimitCost) {
  const [used, total] = rateLimitCost.split("/").map(Number);
  if (used > total * 0.8) {
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
}

}

return allProducts; }

  1. Bulk Operation Pattern

mutation bulkOperationRunQuery { bulkOperationRunQuery( query: """ { products { edges { node { id title metafields { edges { node { namespace key value } } } } } } } """ ) { bulkOperation { id status } userErrors { field message } } }

Check Status:

query { currentBulkOperation { id status errorCode createdAt completedAt objectCount fileSize url } }

Download and Process Results:

async function processBulkOperationResults(url: string) { const response = await fetch(url); const jsonl = await response.text();

const lines = jsonl.trim().split("\n"); const results = lines.map(line => JSON.parse(line));

return results; }

  1. Rate Limiting Handler

async function graphqlWithRetry(admin, query, variables, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await admin.graphql(query, { variables });

  // Check rate limit
  const rateLimitCost = response.headers.get("X-Shopify-Shop-Api-Call-Limit");
  if (rateLimitCost) {
    const [used, total] = rateLimitCost.split("/").map(Number);
    console.log(`API calls: ${used}/${total}`);

    if (used > total * 0.9) {
      console.warn("Approaching rate limit, slowing down...");
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }

  const data = await response.json();

  if (data.errors) {
    throw new Error(`GraphQL error: ${data.errors[0].message}`);
  }

  return data;
} catch (error) {
  if (error.message.includes("Throttled") &#x26;&#x26; i &#x3C; maxRetries - 1) {
    const delay = Math.pow(2, i) * 1000; // Exponential backoff
    console.log(`Rate limited, retrying in ${delay}ms...`);
    await new Promise(resolve => setTimeout(resolve, delay));
    continue;
  }
  throw error;
}

} }

Best Practices

  • Pagination - Always use cursor-based pagination for large result sets

  • Field Selection - Only request fields you need to reduce response size

  • Rate Limiting - Monitor API call limits and implement backoff

  • Error Handling - Check both errors and userErrors in responses

  • Bulk Operations - Use for processing 1000+ products

  • Metafield Types - Use appropriate types (single_line_text_field, number_integer, json, etc.)

  • Webhook Verification - Always verify HMAC signatures

  • Caching - Cache frequently accessed data like metafield definitions

  • Retry Logic - Implement exponential backoff for transient failures

  • Logging - Log API calls and errors for debugging

Common Metafield Types

  • single_line_text_field

  • Short text

  • multi_line_text_field

  • Long text

  • number_integer

  • Whole numbers

  • number_decimal

  • Decimal numbers

  • json

  • Structured data

  • color

  • Color values

  • url

  • URLs

  • boolean

  • True/false

  • date

  • Date values

  • list.single_line_text_field

  • Array of strings

Quick Reference

Get Product by Handle

query getProductByHandle($handle: String!) { productByHandle(handle: $handle) { id title vendor } }

Get Product Variants

query getProductVariants($productId: ID!) { product(id: $productId) { variants(first: 100) { edges { node { id title price sku inventoryQuantity } } } } }

Update Product

mutation productUpdate($input: ProductInput!) { productUpdate(input: $input) { product { id title } userErrors { field message } } }

Remember: Always check the Shopify Admin API documentation for the latest schema and deprecations.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

shopify workflow & tools

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

polaris-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

polaris-compositions

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shopify liquid fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review