shopify-api-integration

Shopify API Best Practices

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-integration" with this command: npx skills add trantuananh-17/product-reviews/trantuananh-17-product-reviews-shopify-api-integration

Shopify API Best Practices

API Version Check (CRITICAL)

Always verify API version before implementing!

Shopify deprecates API versions regularly. Check:

  • Current API version in shopify.app.toml or app config

  • Shopify release notes for breaking changes

  • Use Shopify MCP tools to verify current schema

// Check what version your app uses // shopify.app.toml [api] api_version = "2024-10" // Verify this matches your implementation

API Selection Guide

Need Solution

Customize checkout UI Checkout UI Extension

Apply discounts Discount Function

Validate cart Cart Validation Function

React to events Webhooks

Read/write data GraphQL Admin API

Sync large data Bulk Operations

Store custom data Metafields/Metaobjects

GraphQL Admin API

Basic Query

const query = query getProduct($id: ID!) { product(id: $id) { id title handle variants(first: 10) { nodes { id price } } } };

const response = await shopify.graphql(query, { id: productId });

Pagination

async function getAllProducts(shopify) { const products = []; let hasNextPage = true; let cursor = null;

while (hasNextPage) { const query = query getProducts($cursor: String) { products(first: 50, after: $cursor) { pageInfo { hasNextPage } edges { cursor node { id title } } } } ;

const response = await shopify.graphql(query, { cursor });
const { edges, pageInfo } = response.products;

products.push(...edges.map(e => e.node));
hasNextPage = pageInfo.hasNextPage;
cursor = edges[edges.length - 1]?.cursor;

}

return products; }

Bulk Operations (ALWAYS Consider First)

Before implementing any Shopify data sync, ask: "Can this hit API limits?"

Rate Limits Context:

  • Regular metafield API: 2 requests/second, 40 requests/minute

  • Bulk Operations: No rate limits - runs server-side on Shopify

Volume Decision Guide

Volume Strategy

< 50 items Regular GraphQL

50-500 items Batch with Cloud Tasks + rate limiting

500+ items Bulk Operations API

For detailed bulk mutation patterns, see: shopify-bulk-operations skill

Rate Limiting

Cloud Tasks (Recommended for Rate Limits)

// BAD: In-function sleep wastes CPU time await sleep(60000); // 60s sleep = 60s CPU billed

// GOOD: Schedule retry with Cloud Tasks async function scheduleRetry(payload, delaySeconds) { await client.createTask({ parent: client.queuePath(project, location, 'shopify-retry'), task: { httpRequest: { url: ${baseUrl}/api/retry-shopify, body: Buffer.from(JSON.stringify(payload)).toString('base64'), headers: { 'Content-Type': 'application/json' } }, scheduleTime: { seconds: Math.floor(Date.now() / 1000) + delaySeconds } } }); }

Metafields

Set Metafields (Batch)

const mutation = mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) { metafieldsSet(metafields: $metafields) { metafields { id key value } userErrors { field message } } };

await shopify.graphql(mutation, { metafields: [ { ownerId: customerId, namespace: 'loyalty', key: 'points', type: 'number_integer', value: '500' }, { ownerId: customerId, namespace: 'loyalty', key: 'tier', type: 'single_line_text_field', value: 'Gold' } ] });

Webhooks

Response Time (CRITICAL)

Must respond within 5 seconds!

// BAD: Heavy processing (may timeout) app.post('/webhooks/orders/create', async (req, res) => { await calculatePoints(req.body); await updateCustomer(req.body); await syncToShopify(req.body); res.status(200).send('OK'); });

// GOOD: Queue and respond fast app.post('/webhooks/orders/create', async (req, res) => { // Quick validation if (!verifyHmac(req)) { return res.status(401).send('Unauthorized'); }

// Queue for background processing await webhookQueueRef.add({ type: 'orders/create', payload: req.body });

// Respond immediately res.status(200).send('OK'); });

HMAC Verification

import crypto from 'crypto';

function verifyHmac(req) { const hmac = req.get('X-Shopify-Hmac-Sha256'); const body = req.rawBody; const secret = process.env.SHOPIFY_WEBHOOK_SECRET;

const hash = crypto .createHmac('sha256', secret) .update(body, 'utf8') .digest('base64');

return crypto.timingSafeEqual( Buffer.from(hmac), Buffer.from(hash) ); }

App Bridge (Direct API)

When to Use

Scenario Use App Bridge Use Firebase API

Simple Shopify CRUD Yes No

Need Firestore data No Yes

Complex business logic No Yes

Background processing No Yes

Direct API Call

import { authenticatedFetch } from '@shopify/app-bridge/utilities';

async function fetchProducts(app) { const response = await authenticatedFetch(app)( '/admin/api/2024-04/graphql.json', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: { products(first: 10) { nodes { id title } } } }) } );

return response.json(); }

Benefits:

  • Faster (no Firebase roundtrip)

  • Lower cost (no function invocation)

  • Uses shop's session directly

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.

General

bigquery-analytics

No summary provided by upstream source.

Repository SourceNeeds Review
General

Youtube Podcast Generator

Extracts the original text of Youtube video and converts it into a multi-voice AI podcast using a local Node.js API and FFmpeg. It also can show you the text...

Registry SourceRecently Updated
General

ERPClaw

AI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842,...

Registry SourceRecently Updated
General

Whisper AI Audio to Text Transcriber

Turn raw transcripts into structured summaries, meeting minutes, and action items.

Registry SourceRecently Updated