======================== CODE SNIPPETS ======================== TITLE: Initializing Shopify API Client in TypeScript DESCRIPTION: Example of creating a new Shopify API client instance with complete configuration including API keys, scopes, hosting settings, billing configuration, and custom logging. Shows how to import required dependencies and set up essential parameters. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/shopifyApi.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` import {shopifyApi, ApiVersion, BillingInterval} from '@shopify/shopify-api'; import {restResources} from '@shopify/shopify-api/rest/admin/2022-07'; const shopify = shopifyApi({ apiKey: 'APIKeyFromPartnersDashboard', apiSecretKey: 'APISecretFromPartnersDashboard', scopes: ['read_products'], hostName: 'localhost:4321', hostScheme: 'http', apiVersion: ApiVersion.July22, isEmbeddedApp: true, isCustomStoreApp: false, userAgentPrefix: 'Custom prefix', privateAppStorefrontAccessToken: 'PrivateAccessToken', customShopDomains: ['*.my-custom-domain.io'], billing: { 'My plan': { amount: 5.0, currencyCode: 'USD', interval: BillingInterval.OneTime, }, }, logger: { log: (severity, message) => { myAppsLogFunction(severity, message); }, }, restResources, future: { // ... }, }); ``` ---------------------------------------- TITLE: Webhook Handler Configuration Updates DESCRIPTION: Updates webhook handler registration to use new async API pattern and DeliveryMethod specification for APP_UNINSTALLED webhook. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md#2025-04-17_snippet_15 LANGUAGE: diff CODE: ``` -Shopify.Webhooks.Registry.addHandler("APP_UNINSTALLED", { - path: "/api/webhooks", - webhookHandler: async (_topic, shop, _body) => { - await AppInstallations.delete(shop); +await shopify.webhooks.addHandlers({ + APP_UNINSTALLED: { + deliveryMethod: DeliveryMethod.Http, + callbackUrl: "/api/webhooks", + callback: async (_topic, shop, _body) => { + await AppInstallations.delete(shop); + }, }, }); ``` ---------------------------------------- TITLE: Updating Auth Redirect Handler for Shopify API v6 DESCRIPTION: Modifications to the auth redirect helper to use new shopify instance methods and handle redirections differently in API v6. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md#2025-04-17_snippet_13 LANGUAGE: diff CODE: ``` -import { Shopify } from "@shopify/shopify-api"; +import shopify from "../shopify.js"; [...remaining diff code...] ``` ---------------------------------------- TITLE: Initializing Shopify API with Express DESCRIPTION: Sets up the Shopify API library with configuration parameters and initializes an Express application. The example includes essential configuration like API keys, scopes, and hostname. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/README.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` import '@shopify/shopify-api/adapters/node'; import {shopifyApi, LATEST_API_VERSION} from '@shopify/shopify-api'; import express from 'express'; const shopify = shopifyApi({ // The next 4 values are typically read from environment variables for added security apiKey: 'APIKeyFromPartnersDashboard', apiSecretKey: 'APISecretFromPartnersDashboard', scopes: ['read_products'], hostName: 'ngrok-tunnel-address', ... }); const app = express(); ``` ---------------------------------------- TITLE: Initializing Shopify REST Client in TypeScript DESCRIPTION: Creates a new REST client instance for making API calls to Shopify. This example demonstrates how to initialize the client within an Express route handler using the current session and specifying the API version. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Rest.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` // Requests to /my-endpoint must be made with authenticatedFetch for embedded apps app.get('/my-endpoint', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Rest({ session, apiVersion: ApiVersion.January23, }); }); ``` ---------------------------------------- TITLE: Handling Paginated Requests with REST Resources in TypeScript DESCRIPTION: Demonstrates how to handle cursor-based pagination when fetching multiple sets of products using the all method of REST resources. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/rest-resources.md#2025-04-17_snippet_6 LANGUAGE: typescript CODE: ``` let pageInfo; do { const response = await shopify.rest.Product.all({ ...pageInfo?.nextPage?.query, session, limit: 10, }); const pageProducts = response.data; // ... use pageProducts pageInfo = response.pageInfo; } while (pageInfo?.nextPage); ``` ---------------------------------------- TITLE: Initializing Storefront API Client in TypeScript DESCRIPTION: Example of how to construct a Storefront API client using a Session object. The client is initialized within an Express route handler, getting the current session ID and retrieving the session from storage. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Storefront.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.get('/my-endpoint', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by the application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Storefront({ session, apiVersion: ApiVersion.January23, }); }); ``` ---------------------------------------- TITLE: Creating a Localized Cart with Shopify Storefront API in TypeScript DESCRIPTION: This snippet illustrates how to create a localized cart using the Shopify Storefront API. It includes a GraphQL mutation with country and language context variables for localization. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md#2025-04-17_snippet_6 LANGUAGE: typescript CODE: ``` const cartCreateMutation = ` mutation ($input: CartInput!, $country: CountryCode, $language: LanguageCode) @inContext(country: $country, language: $language) { cartCreate(input: $input) { userErrors { message code field } cart { id checkoutUrl } } } `; const {data, errors, extensions} = await client.request(cartCreateMutation, { variables: { input: {}, country: 'JP', language: 'JA', }, }); ``` ---------------------------------------- TITLE: Implementing Shopify OAuth Authentication in Cloudflare Workers DESCRIPTION: Example of implementing the OAuth authentication flow in a Cloudflare Workers environment. The code demonstrates handling authentication requests and returning the appropriate Response object. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/begin.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` async function handleFetch(request: Request): Promise { const {searchParams} = new URL(request.url); // The library will return a Response object return shopify.auth.begin({ shop: shopify.utils.sanitizeShop(searchParams.get('shop'), true), callbackPath: '/auth/callback', isOnline: false, rawRequest: request, }); } ``` ---------------------------------------- TITLE: Initializing Shopify API for a Custom Store App DESCRIPTION: Configures the Shopify API client for a store-specific custom app. Sets the API secret key, access token, and other required parameters to enable direct API access without OAuth flow. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/custom-store-app.md#2025-04-17_snippet_0 LANGUAGE: js CODE: ``` import "@shopify/shopify-api/adapters/node"; import { shopifyApi, ApiVersion, Session } from "@shopify/shopify-api"; import { restResources } from "@shopify/shopify-api/rest/admin/2023-04"; const shopify = shopifyApi({ apiSecretKey: "App_API_secret_key", // Note: this is the API Secret Key, NOT the API access token apiVersion: ApiVersion.April23, isCustomStoreApp: true, // this MUST be set to true (default is false) adminApiAccessToken: "Admin_API_Access_Token", // Note: this is the API access token, NOT the API Secret Key isEmbeddedApp: false, hostName: "my-shop.myshopify.com", // Mount REST resources. restResources, }); ``` ---------------------------------------- TITLE: Querying Products with GraphQL DESCRIPTION: Demonstrates how to query product data using GraphQL operations with the Admin API client SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` const operation = ` query ProductQuery($id: ID!) { product(id: $id) { id title handle } } `; const {data, errors, extensions} = await client.request(operation, { variables: { id: 'gid://shopify/Product/7608002183224', }, }); ``` ---------------------------------------- TITLE: Creating Storefront API Client in TypeScript (After v8) DESCRIPTION: Updated example of creating a Storefront API client using the new 'session' parameter instead of 'domain' and 'storefrontAccessToken'. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v8.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` app.get('/my-endpoint', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by the application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Storefront({ session, apiVersion: ApiVersion.January23, }); }); ``` ---------------------------------------- TITLE: Initializing REST API Client in TypeScript DESCRIPTION: Shows how to initialize the Shopify Admin REST API client with the necessary configuration, including store domain, API version, and access token. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md#2025-04-17_snippet_8 LANGUAGE: typescript CODE: ``` import {createAdminRestApiClient} from '@shopify/admin-api-client'; const client = createAdminRestApiClient({ storeDomain: 'your-shop-name.myshopify.com', apiVersion: '2023-04', accessToken: 'your-admin-api-access-token', }); ``` ---------------------------------------- TITLE: Updating a Product using REST Resources in TypeScript DESCRIPTION: Shows how to update a product using REST resources, which simplifies the process by abstracting the HTTP requests and response handling. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/rest-resources.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` const sessionId = await shopify.session.getCurrentId({ rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); // get a single product via its product id const product = await shopify.rest.Product.find({session, id: '7504536535062'}); product.title = 'A new title'; // After promise resolves, the product will be updated with the returned data await product.save({ update: true, }); ``` ---------------------------------------- TITLE: Implementing Shopify Auth Callback in Node.js DESCRIPTION: Example of handling Shopify's OAuth callback in a Node.js environment. The code processes the callback request, creates a new session, and redirects to the app's entry page. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/callback.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.get('/auth/callback', async (req, res) => { // The library will automatically set the appropriate HTTP headers const callback = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); // You can now use callback.session to make API requests res.redirect('/my-apps-entry-page'); }); ``` ---------------------------------------- TITLE: Initializing Shopify GraphQL Client in TypeScript DESCRIPTION: This snippet demonstrates how to create a new instance of the Shopify GraphQL client within an Express.js route handler. It shows the process of retrieving a session ID, fetching the session from storage, and initializing the client with the session and API version. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Graphql.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.get('/my-endpoint', async () => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Graphql({ session, apiVersion: ApiVersion.January23, }); }); ``` ---------------------------------------- TITLE: Configuring a Subscription Plan with a Single LineItem in Shopify API DESCRIPTION: Sets up a Shopify app subscription plan with a single recurring line item. The plan has a 7-day trial period and charges $30 USD every 30 days, with a $10 discount for the first three billing cycles. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/billing.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` import { shopifyApi, BillingInterval, BillingReplacementBehavior, } from '@shopify/shopify-api'; const shopify = shopifyApi({ // ... billing: { { "Single LineItem Plan": { replacementBehavior: BillingReplacementBehavior.ApplyImmediately, trialDays: 7, lineItems: [ { interval: BillingInterval.Every30Days, amount: 30, currencyCode: "USD", discount: { durationLimitInIntervals: 3, value: { amount: 10, }, }, } ], }, }, } future: { v10_lineItemBilling: true, }); ``` ---------------------------------------- TITLE: Creating a Product using REST Resources in TypeScript DESCRIPTION: Demonstrates how to create a new product using REST resources, setting various properties and saving it to Shopify. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/rest-resources.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` const product = new shopify.rest.Product({session: session}); product.title = 'Burton Custom Freestyle 151'; product.body_html = 'Good snowboard!'; product.vendor = 'Burton'; product.product_type = 'Snowboard'; product.status = 'draft'; // After promise resolves, product will be updated with the returned data await product.save({ update: true, }); ``` ---------------------------------------- TITLE: Using TypeScript Generic for GraphQL Response Typing DESCRIPTION: This example shows how to use TypeScript generics to type the response body of a GraphQL query. It defines an interface for the expected response structure and passes it as a type argument to the request method. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Graphql.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` // If using TypeScript, you can type the response body interface MyResponseBodyType { data: { //... }; } const response = await client.request(/* ... */); // response.body will be of type MyResponseBodyType console.log(response.body.data); ``` ---------------------------------------- TITLE: Configuring a Subscription Plan with Multiple LineItems in Shopify API DESCRIPTION: Creates a Shopify app subscription plan with both recurring and usage-based line items. The plan includes a 7-day trial, a $30 monthly recurring charge with a $10 discount for three cycles, and a usage-based charge for emails. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/billing.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` import { shopifyApi, BillingInterval, BillingReplacementBehavior, } from '@shopify/shopify-api'; const shopify = shopifyApi({ // ... billing: { { "Multiple LineItems Plan": { replacementBehavior: BillingReplacementBehavior.ApplyImmediately, trialDays: 7, lineItems: [ { interval: BillingInterval.Every30Days, amount: 30, currencyCode: "USD", discount: { durationLimitInIntervals: 3, value: { amount: 10, }, }, }, { interval: BillingInterval.Usage, amount: 30, currencyCode: "USD", terms: "per 1000 emails", }, ], }, }, }, future: { v10_lineItemBilling: true, }); ``` ---------------------------------------- TITLE: Using client.fetch() to Get Shopify API Data DESCRIPTION: This snippet shows how to use the client.fetch() method to retrieve data from the Shopify API. It demonstrates making a simple query for shop information and handling the response. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/graphql-client/README.md#2025-04-17_snippet_10 LANGUAGE: typescript CODE: ``` const shopQuery = ` query shop { shop { name id } } `; const response = await client.fetch(shopQuery); if (response.ok) { const {errors, data, extensions} = await response.json(); } ``` ---------------------------------------- TITLE: Accessing REST Resources in Shopify API v6 (TypeScript) DESCRIPTION: Demonstrates how to import and use REST resources in v6, which are now accessed via the Shopify API instance instead of direct imports from the dist folder. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md#2025-04-17_snippet_23 LANGUAGE: typescript CODE: ``` import {shopifyApi, ApiVersion} from '@shopify/shopify-api'; const apiVersion = ApiVersion.October22; let {restResources} = await import( `@shopify/shopify-api/rest/admin/${apiVersion}` ); const shopify = shopifyApi({ // ... apiVersion, restResources, }); // ... app.get('/api/products/count', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: false, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); const countData = await shopify.rest.Product.count({session}); res.status(200).send(countData); }); ``` ---------------------------------------- TITLE: Initializing Shopify API and Registering Webhooks after OAuth in Node.js DESCRIPTION: This snippet demonstrates how to initialize the Shopify API client and register webhooks after the OAuth flow completes in an Express.js application. It handles the OAuth callback, registers webhooks with Shopify using the session, and redirects the user. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` const shopify = shopifyApi({ /* ... */ }); // Call shopify.webhooks.addHandlers here (see examples below) ## Node.js const app = express(); // Register webhooks after OAuth completes app.get('/auth/callback', async (req, res) => { try { const callbackResponse = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); const response = await shopify.webhooks.register({ session: callbackResponse.session, }); if (!response['PRODUCTS_CREATE'][0].success) { console.log( `Failed to register PRODUCTS_CREATE webhook: ${response['PRODUCTS_CREATE'][0].result}`, ); } } catch (error) { console.error(error); // in practice these should be handled more gracefully } return res.redirect('/'); // or wherever you want your user to end up after OAuth completes }); ``` ---------------------------------------- TITLE: Canceling a Shopify App Subscription in TypeScript DESCRIPTION: Example of how to cancel a Shopify app subscription using the shopify.billing.cancel method. It demonstrates handling the subscription ID, optional prorating, and error handling with BillingError. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/cancel.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` const subscriptionId = "gid://shopify/AppSubscription/1234567890"; // this can be obtained from a call to shopify.billing.subscriptions() try { const canceledSubscription = await shopify.billing.cancel({ session, subscriptionId, prorate: true, // Whether to issue prorated credits for the unused portion of the app subscription. Defaults to true. }) } catch (error) { if (error typeof BillingError) { console.log(`Unable to cancel subscription ${subscriptionId}: ${JSON.stringify(error.errorData, null, 2)}`); // handle error appropriately } } // canceledSubscription will have the following shape: // { // id: string; // name: string; // test: boolean; // } ``` ---------------------------------------- TITLE: Processing Webhooks with Process Method and Callback in Express DESCRIPTION: This example demonstrates using the shopify.webhooks.process method with a callback function to handle webhook events. The handler function is defined separately and referenced in the webhook configuration, allowing for custom processing of specific events. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` const handleWebhookRequest = async ( topic: string, shop: string, webhookRequestBody: string, webhookId: string, apiVersion: string, context?: any, ) => { const sessionId = shopify.session.getOfflineId(shop); // Run your webhook-processing code here! }; // Add handlers for the events you want to subscribe to. You **MUST** set a callback function when calling `process` shopify.webhooks.addHandlers({ PRODUCTS_CREATE: [ { deliveryMethod: DeliveryMethod.Http, callbackUrl: '/webhooks', callback: handleWebhookRequest, }, ], }); // Process webhooks app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => { try { // Note: the express.text() given above is an Express middleware that will read // in the body as a string, and make it available at req.body, for this path only. await shopify.webhooks.process({ rawBody: req.body, // is a string rawRequest: req, rawResponse: res, }); } catch (error) { console.log(error.message); } }); ``` ---------------------------------------- TITLE: Implementing Custom Runtime Adapter Functions in TypeScript DESCRIPTION: Example showing implementation of custom runtime adapter functions for the Shopify API. Demonstrates setting up runtime string and header conversion functions with proper type definitions and abstract function implementations. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/runtimes.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` import { setAbstractConvertHeadersFunc, setAbstractRuntimeString, AbstractRuntimeStringFunc, AbstractConvertHeadersFunc, Headers, AdapterArgs, } from '@shopify/shopify-api/runtime'; type MyRequestType = any; type MyResponseType = any; interface MyRuntimeAdapterArgs extends AdapterArgs { rawRequest: MyRequestType; rawResponse?: MyResponseType; } const myRuntimeStringFunc: AbstractRuntimeStringFunc = () => { return `My runtime adapter ${myAdapterVersion}`; }; setAbstractRuntimeString(myRuntimeStringFunc); const myRuntimeHeaderFunc: AbstractConvertHeadersFunc = async ( headers: Headers, adapterArgs: MyRuntimeAdapterArgs, ) => { return magicHeaderConversion(headers); }; setAbstractConvertHeadersFunc(myRuntimeHeaderFunc); ``` ---------------------------------------- TITLE: Querying Shop Information with Shopify Storefront API in TypeScript DESCRIPTION: This example demonstrates a simple query to retrieve basic shop information using the Shopify Storefront API client. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md#2025-04-17_snippet_7 LANGUAGE: typescript CODE: ``` const shopQuery = ` query shop { shop { name id } } `; const {data, errors, extensions} = await client.request(shopQuery); ``` ---------------------------------------- TITLE: Configuring Logger in Shopify API (TypeScript) DESCRIPTION: Example configuration of the logger property in the shopifyApi initialization. Shows how to set log severity level, enable timestamps and HTTP request logging, and provide a custom log function. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/logger.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` import {shopifyApi, LogSeverity} from '@shopify/shopify-api'; const shopify = shopifyApi({ // other configuration settings logger: { level: LogSeverity.Debug, timestamps: true, httpRequests: true, log: async (severity, message) => {}, }, }); ``` ---------------------------------------- TITLE: Executing GraphQL Query with Variables in TypeScript DESCRIPTION: This snippet demonstrates how to send a GraphQL query to the Shopify Admin API using variables. It shows how to define a query with a variable and pass the variable value in the request options. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Graphql.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` const response = await client.request( `query GetProducts($first: Int!) { products (first: $first) { edges { node { id title descriptionHtml } } } }`, { variables: { first: 10, }, }, ); console.log(response.data, response.extensions); ``` ---------------------------------------- TITLE: Making API Requests with a Custom App Session DESCRIPTION: Demonstrates how to create a custom session for API requests in a store-specific app. Creates a session object using the customAppSession utility method and uses it to make REST API calls to retrieve store data. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/custom-store-app.md#2025-04-17_snippet_1 LANGUAGE: js CODE: ``` const session = shopify.session.customAppSession("my-shop.myshopify.com"); // Use REST resources to make calls. const { count: productCount } = await shopify.rest.Product.count({ session }); const { count: customerCount } = await shopify.rest.Customer.count({ session }); const { count: orderCount } = await shopify.rest.Order.count({ session }); console.log( `There are ${productCount} products, ${customerCount} customers, and ${orderCount} orders in the ${session.shop} store.` ); ``` ---------------------------------------- TITLE: Executing GraphQL Queries with Type Safety in TypeScript DESCRIPTION: Demonstrates how to execute GraphQL queries using client.request() and client.requestStream() with TypeScript type safety. Shows usage of auto-generated types and query printing. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md#2025-04-17_snippet_11 LANGUAGE: typescript CODE: ``` import {print} from 'graphql/language'; // GQL operation types are usually auto generated during the application build import {CollectionQuery, CollectionDeferredQuery} from 'types/appTypes'; import collectionQuery from './collectionQuery.graphql'; import collectionDeferredQuery from './collectionDeferredQuery.graphql'; const {data, errors, extensions} = await client.request( print(collectionQuery), { variables: { handle: 'sample-collection', }, } ); const responseStream = await client.requestStream( print(collectionDeferredQuery), { variables: {handle: 'sample-collection'}, } ); ``` ---------------------------------------- TITLE: Querying for a Product using Shopify API JavaScript Client DESCRIPTION: This snippet demonstrates how to use the Shopify API JavaScript client to query for a product. It includes a GraphQL query for fetching product details and shows how to make the request with variables. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/graphql-client/README.md#2025-04-17_snippet_4 LANGUAGE: typescript CODE: ``` const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, }); ``` ---------------------------------------- TITLE: Comparing Values Using safeCompare in TypeScript DESCRIPTION: Demonstrates various usage examples of the safeCompare method, including comparing string arrays, different array contents, and handling type mismatches. Shows successful comparisons and error scenarios. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/safeCompare.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` const stringArray1 = ['alice', 'bob', 'charlie']; const stringArray2 = ['alice', 'bob', 'charlie']; const stringArrayResult = shopify.auth.safeCompare(stringArray1, stringArray2); // true const array1 = ['one fish', 'two fish']; const array2 = ['red fish', 'blue fish']; const arrayResult = shopify.auth.safeCompare(array1, array2); // false const arg1 = 'hello'; const arg2 = ['world']; const argResult = shopify.auth.safeCompare(arg1, arg2); // throws SafeCompareError due to argument type mismatch ``` ---------------------------------------- TITLE: Creating Multi-Plan Billing Charges Based on User Selection DESCRIPTION: Example of a multi-plan billing setup where the plan is selected by the user on the frontend. The session is retrieved from storage using the session ID. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` app.post('/api/select-plan', async (req, res) => { const sessionId = shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // In this example, getSessionFromStorage() must be provided by app const session = await getSessionFromStorage(sessionId); const confirmationUrl = await shopify.billing.request({ session, // Receive the selected plan from the frontend plan: req.body.selectedPlan, isTest: true, }); res.redirect(confirmationUrl); }); ``` ---------------------------------------- TITLE: Updating a Product using REST Client in TypeScript DESCRIPTION: Demonstrates how to update a product using a plain REST client, including fetching the product, modifying its title, and sending a PUT request to update it. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/rest-resources.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` // App must provide response types interface ProductResponse { product: { id: number; title: string; // ... }; } const sessionId = await shopify.session.getCurrentId({ rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Rest({session}); // The following line sends a HTTP GET request to this constructed URL: // https://${session.shop}/admin/api/${shopify.config.api_version}/products/7504536535062.json const response = await client.get({ path: 'products/7504536535062', }); // Apps needs to dig into the response body to find the object response.body.product.title = 'A new title'; // The following sends a HTTP PUT request to this constructed URL... // https://${session.shop}/admin/api/${shopify.config.api_version}/products/${response.body.product.id}.json // ... with this body // {"product":{"id":response.body.product.id,"title":"A new title"}} await client.put({ path: `products/${response.body.product.id}`, data: response.body.product, }); ``` ---------------------------------------- TITLE: Initializing Shopify OAuth Authentication in Node.js DESCRIPTION: Example of implementing the OAuth authentication flow in a Node.js application. The code shows how to handle the initial authentication request and redirect users to Shopify's authentication screen. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/begin.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.get('/auth', async (req, res) => { // The library will automatically redirect the user await shopify.auth.begin({ shop: shopify.utils.sanitizeShop(req.query.shop, true), callbackPath: '/auth/callback', isOnline: false, rawRequest: req, rawResponse: res, }); }); ``` ---------------------------------------- TITLE: Adding Custom Headers to Shopify API Request DESCRIPTION: This snippet demonstrates how to add custom headers to a Shopify API request. It shows the process of including a 'Shopify-Storefront-Id' header when querying for a product. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/graphql-client/README.md#2025-04-17_snippet_6 LANGUAGE: typescript CODE: ``` const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, headers: { 'Shopify-Storefront-Id': 'shop-id', }, }); ``` ---------------------------------------- TITLE: Configuring Line Item Billing in TypeScript DESCRIPTION: Example configuration for multiple line item billing with trial period and discounts. Demonstrates usage of the unstable_lineItemBilling future flag to specify both recurring and usage based app billing in a single request. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/CHANGELOG.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` const shopify = shopifyApp({ billing: { MultipleLineItems: { replacementBehavior: BillingReplacementBehavior.ApplyImmediately, trialDays: 7, lineItems: [ { interval: BillingInterval.Usage, amount: 30, currencyCode: "USD", terms: "per 1000 emails", }, { interval: BillingInterval.Every30Days, amount: 30, currencyCode: "USD", discount: { durationLimitInIntervals: 3, value: { amount: 10, }, }, }, ], }, }, futures: { unstable_lineItemBilling: true, }, }); ``` ---------------------------------------- TITLE: Processing Webhooks with Validate Method in Express DESCRIPTION: This snippet shows how to add webhook handlers and process incoming webhooks using the shopify.webhooks.validate method in an Express application. It validates the webhook request and performs custom processing based on the topic and domain. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md#2025-04-17_snippet_1 LANGUAGE: typescript CODE: ``` // Add handlers for the events you want to subscribe to. You don't need a callback if you're just using `validate` shopify.webhooks.addHandlers({ PRODUCTS_CREATE: [ {deliveryMethod: DeliveryMethod.Http, callbackUrl: '/webhooks'}, ], }); // Handle webhooks app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => { const {valid, topic, domain} = await shopify.webhooks.validate({ rawBody: req.body, // is a string rawRequest: req, rawResponse: res, }); if (!valid) { console.error('Invalid webhook call, not handling it'); res.send(400); // Bad Request } console.log(`Received webhook for ${topic} for shop ${domain}`); const sessionId = shopify.session.getOfflineId(domain); // Run your webhook-processing code here! }); ``` ---------------------------------------- TITLE: Processing Webhooks with Express in Node.js DESCRIPTION: Example showing how to handle Shopify webhooks in an Express app using the shopify.webhooks.process method. This implementation uses express.text() middleware to read the raw body as a string and passes it to the process method. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/webhooks/process.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => { try { // Note: the express.text() given above is an Express middleware that will read // in the body as a string, and make it available at req.body, for this path only. await shopify.webhooks.process({ rawBody: req.body, // is a string rawRequest: req, rawResponse: res, }); } catch (error) { console.log(error.message); } }); ``` ---------------------------------------- TITLE: Querying Product Data with GraphQL in TypeScript DESCRIPTION: Demonstrates how to use the GraphQL client to query for a product's data, including ID, title, and handle. It also shows how to handle variables in the query. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` const productQuery = ` query ProductQuery($id: ID!) { product(id: $id) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { id: 'gid://shopify/Product/7608002183224', }, }); ``` ---------------------------------------- TITLE: Updating Product Data with Shopify Admin REST API DESCRIPTION: Shows how to update a product's handle using the PUT method. Demonstrates proper data structure for update operations. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md#2025-04-17_snippet_11 LANGUAGE: typescript CODE: ``` const response = await client.put("products/1234567890", { data: { product: { handle: "my-new-handle", } } } ); if (response.ok) { const body = await response.json(); } ``` ---------------------------------------- TITLE: Defining Shopify Type with Rest Resources in TypeScript (After v8) DESCRIPTION: Updated example of explicitly using the Shopify type with rest resources after v8, including the ConfigParams type. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v8.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` import { restResources, ConfigParams, } from '@shopify/shopify-api/rest/admin/2023-10'; const myVariable: Shopify; ``` ---------------------------------------- TITLE: Querying Product Data with Shopify Storefront API in TypeScript DESCRIPTION: This snippet demonstrates how to query for a product using the Shopify Storefront API client. It includes a GraphQL query for product details and shows how to make a request with variables. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md#2025-04-17_snippet_4 LANGUAGE: typescript CODE: ``` const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, }); ``` ---------------------------------------- TITLE: Creating Server-Enabled GraphQL Client DESCRIPTION: Initializing a client with custom fetch API for server-side usage using node-fetch SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/graphql-client/README.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` import {createGraphQLClient} from '@shopify/graphql-client'; import {fetch as nodeFetch} from 'node-fetch'; const client = createGraphQLClient({ url: 'http://your-shop-name.myshopify.com/api/2023-10/graphql.json', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': 'public-token', }, customFetchApi: nodeFetch }); ``` ---------------------------------------- TITLE: Updating Product Creator for Shopify API v6 DESCRIPTION: Updates to the product creator helper to use the new shopify instance and error handling mechanisms from API v6. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md#2025-04-17_snippet_12 LANGUAGE: diff CODE: ``` -import { Shopify } from "@shopify/shopify-api"; +import { GraphqlQueryError } from "@shopify/shopify-api"; +import shopify from "../shopify.js"; [...remaining diff code...] ``` ---------------------------------------- TITLE: Registering Webhook Handlers in Shopify API JavaScript DESCRIPTION: This snippet demonstrates how to initialize the Shopify API client, define a webhook handler function, and register multiple handlers for the PRODUCTS_CREATE topic using the HTTP delivery method. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/webhooks/addHandlers.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` const shopify = shopifyApi({ /* ... */ }); const handleWebhookRequest = async ( topic: string, shop: string, webhookRequestBody: string, webhookId: string, apiVersion: string, ) => { const sessionId = shopify.session.getOfflineId(shop); // Fetch the session from storage and process the webhook event }; shopify.webhooks.addHandlers({ PRODUCTS_CREATE: [ { deliveryMethod: DeliveryMethod.Http, callbackUrl: '/webhooks', callback: handleWebhookRequest, }, { deliveryMethod: DeliveryMethod.Http, callbackUrl: '/webhooks', callback: handleWebhookRequestPart2, }, ], }); ``` ---------------------------------------- TITLE: Registering Webhooks in Shopify API v6 (TypeScript) DESCRIPTION: Shows how to register webhooks using the new register method, which now only requires the session object. The response structure has changed to include an array of results for each topic. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md#2025-04-17_snippet_21 LANGUAGE: typescript CODE: ``` const response = await shopify.webhooks.register({session: session}); // Response will be a list indexed by topic: console.log(response[topic][0].success, response[topic][0].result); ``` ---------------------------------------- TITLE: Querying Product Info with @defer Directive in Shopify API DESCRIPTION: This example shows how to use the @defer directive in a GraphQL query to fetch product information. It demonstrates the use of client.requestStream for handling deferred fields and processing the response as an async iterator. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/graphql-client/README.md#2025-04-17_snippet_5 LANGUAGE: typescript CODE: ``` const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id handle ... @defer(label: "deferredFields") { title description } } } `; const responseStream = await client.requestStream(productQuery, { variables: {handle: 'sample-product'}, }); // await available data from the async iterator for await (const response of responseStream) { const {data, errors, extensions, hasNext} = response; } ``` ---------------------------------------- TITLE: Implementing GraphQL Proxy Route in a Shopify App DESCRIPTION: Example of creating an Express route that forwards GraphQL requests to Shopify Admin API. This demonstrates retrieving the current session ID, fetching the session from storage, and using the graphqlProxy client to forward the request. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/graphqlProxy.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` app.post('/graphql/proxy', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by application const session = await getSessionFromStorage(sessionId); const response = await shopify.clients.graphqlProxy({ session, rawBody: req.rawBody, // From my app }); res.send(response.body); }); ``` ---------------------------------------- TITLE: Implementing Billing Helper for Shopify API v6 DESCRIPTION: New implementation of billing helper using Shopify API v6's built-in billing support. Handles checking and requesting payments for app usage. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md#2025-04-17_snippet_11 LANGUAGE: typescript CODE: ``` import shopify from '../shopify.js'; export default async function ensureBilling( session, isProdOverride = process.env.NODE_ENV === 'production', ) { [...remaining code...] ``` ---------------------------------------- TITLE: Saving a Session to Storage in Shopify API JS DESCRIPTION: This snippet demonstrates how to save a session to storage after completing OAuth using shopify.auth.callback. It shows how to convert the Session object to a plain JavaScript object for storage. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/session-storage.md#2025-04-17_snippet_0 LANGUAGE: typescript CODE: ``` const callbackResponse = shopify.auth.callback({ rawRequest: req, rawResponse: res, }); // app stores Session in its own storage mechanism await addSessionToStorage(callbackResponse.session.toObject()); ``` ---------------------------------------- TITLE: Initializing Server-Side Client with Private Access Token DESCRIPTION: TypeScript code showing how to create a server-enabled client using a private access token and a custom Fetch API implementation for server-to-server communication. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` import {createStorefrontApiClient, CustomFetchApi} from '@shopify/storefront-api-client'; import {fetch as nodeFetch} from 'node-fetch'; const client = createStorefrontApiClient({ storeDomain: 'http://your-shop-name.myshopify.com', apiVersion: '2023-10', privateAccessToken: 'your-storefront-private-access-token', customFetchApi: nodeFetch, }); ``` ---------------------------------------- TITLE: Making Typed GET Request with TypeScript Generics DESCRIPTION: Demonstrates how to use TypeScript generics to cast the response body to a specific type. This pattern allows for better type safety when working with the API response data. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Rest.md#2025-04-17_snippet_2 LANGUAGE: typescript CODE: ``` interface MyResponseBodyType { products: { /* ... */ }; } const response = await client.get({ path: 'products', }); // response.body will be of type MyResponseBodyType console.log(response.body.products); ``` ---------------------------------------- TITLE: Processing Webhooks in Cloudflare Workers Environment DESCRIPTION: This snippet demonstrates how to process Shopify webhooks in a Cloudflare Workers serverless environment. It extracts the request body and passes it to the webhooks.process method along with context information specific to Cloudflare Workers. SOURCE: https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md#2025-04-17_snippet_3 LANGUAGE: typescript CODE: ``` async function handleFetch( request: Request, env: unknown, context: any, ): Promise { try { await shopify.webhooks.process({ context: {env, ...context}, // is object or undefined rawBody: await request.text(), // is a string rawRequest: request, }); } catch (error) { console.log(error.message); } } ```