### Multi-plan setup - charge based on user selection (returnObject) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md Example of requesting a charge for a multi-plan setup based on user selection, using the returnObject parameter for a detailed response. ```javascript 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 billingResponse = await shopify.billing.request({ session, // Receive the selected plan from the frontend plan: req.body.selectedPlan, isTest: true, returnObject: true, }); res.redirect(billingResponse.confirmationUrl); }); ``` -------------------------------- ### Multi-plan setup - charge based on user selection Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md Example of requesting a charge for a multi-plan setup based on user selection. It shows how to retrieve the session and then call shopify.billing.request with the selected plan. ```javascript 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); }); ``` -------------------------------- ### Development Environment Setup Source: https://github.com/shopify/shopify-api-js/blob/main/CONTRIBUTING.md Steps to clone the repository, install dependencies, and build the library for development. Requires Node.js v16+ and Yarn v1.22+. ```bash git clone git@github.com:Shopify/shopify-api-js.git cd shopify-node-api yarn install yarn build ``` -------------------------------- ### Install Storefront API Client Source: https://github.com/shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md Instructions for installing the Storefront API Client using different package managers. ```sh yarn add @shopify/storefront-api-client ``` ```sh npm install @shopify/storefront-api-client --s ``` ```sh pnpm add @shopify/storefront-api-client ``` -------------------------------- ### Install Shopify GraphQL Client Source: https://github.com/shopify/shopify-api-js/blob/main/packages/graphql-client/README.md Instructions for installing the Shopify GraphQL Client using different package managers (yarn, npm, pnpm). ```sh yarn add @shopify/graphql-client ``` ```sh npm install @shopify/graphql-client --s ``` ```sh pnpm add @shopify/graphql-client ``` -------------------------------- ### Shopify API Client Setup Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/README.md This section outlines the steps to create a REST or GraphQL API client using the shopify-api-js package after completing the OAuth flow and fetching session information. It guides users on how to use these clients to query the Shopify Admin API. ```javascript 1. Fetch the current session 2. Create a [REST](docs/reference/clients/Rest.md) or [GraphQL](docs/reference/clients/Graphql.md) API client. 3. Use the client to query the appropriate [Admin API](https://shopify.dev/api/admin). ``` -------------------------------- ### Single-plan setup - charge after OAuth completes (returnObject) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md Example of requesting a charge for a single plan after OAuth completes, utilizing the returnObject parameter to receive a detailed response. ```javascript app.get('/auth/callback', async () => { const callback = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); // Check if we require payment, using shopify.billing.check() const billingResponse = await shopify.billing.request({ session: callback.session, plan: 'My billing plan', isTest: true, returnObject: true, }); res.redirect(billingResponse.confirmationUrl); }); ``` -------------------------------- ### Single-plan setup - charge after OAuth completes Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md Example of requesting a charge for a single plan after OAuth completes. It demonstrates how to obtain the session and then call shopify.billing.request. ```javascript app.get('/auth/callback', async () => { const callback = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); // Check if we require payment, using shopify.billing.check() const confirmationUrl = await shopify.billing.request({ session: callback.session, plan: 'My billing plan', isTest: true, }); res.redirect(confirmationUrl); }); ``` -------------------------------- ### Query for a product Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md Example of how to fetch a product by its ID using the GET method. ```typescript const response = await client.get("products/1234567890"); if (response.ok) { const body = await response.json(); } ``` -------------------------------- ### Install @shopify/shopify-api Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/README.md Installs the @shopify/shopify-api package using a Node package manager like yarn. ```bash yarn add @shopify/shopify-api ``` -------------------------------- ### Shopify API Reference and Guides Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/README.md Provides links to detailed reference documentation for all methods provided by the shopify-api-js package and guides for high-level instructions on API access and usage. ```APIDOC Reference Documentation: - [./docs/reference/README.md](https://github.com/shopify/shopify-api-js/blob/main/docs/reference/README.md) Guides: - [Performing OAuth](docs/guides/oauth.md) - [Storing sessions](docs/guides/session-storage.md) - [Setting up webhooks](docs/guides/webhooks.md) - [Using REST resources](docs/guides/rest-resources.md) - [Using GraphQL types](docs/guides/graphql-types.md) - [Configuring Billing](docs/guides/billing.md) - [Adding custom runtimes](docs/guides/runtimes.md) - [Customizing logging configuration](docs/guides/logger.md) - [Setting up a custom store app](docs/guides/custom-store-app.md) ``` -------------------------------- ### Successful API Response Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md An example of a successful response from the Shopify Admin API, including the requested product data and extension information detailing query costs and throttle status. ```json { "data": { "product": { "id": "gid:////shopify/Product/7608002183224", "title": "Aera", "handle": "aera-helmet" } }, "extensions": { "cost": { "requestedQueryCost": 1, "actualQueryCost": 1, "throttleStatus": { "maximumAvailable": 1000.0, "currentlyAvailable": 999, "restoreRate": 50.0 } } } } ``` -------------------------------- ### shopify.auth.begin API Documentation Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/begin.md Details the parameters and return values for the shopify.auth.begin function, which starts the OAuth authentication flow for Shopify applications. ```APIDOC shopify.auth.begin(options: { shop: string, callbackPath: string, isOnline: boolean, rawRequest: AdapterRequest, rawResponse?: AdapterResponse }): Promise Parameters: shop: string | required A Shopify domain name in the form {exampleshop}.myshopify.com. callbackPath: string | required The path to the callback endpoint, with a leading /. This URL must be allowed in the Partners dashboard, or using the CLI to run your app. isOnline: boolean | required true if the session is online and false otherwise. Learn more about [OAuth access modes](https://shopify.dev/docs/apps/auth/oauth/access-modes). rawRequest: AdapterRequest | required The HTTP Request object used by your runtime. rawResponse: AdapterResponse | optional, required for Node.js The HTTP Response object used by your runtime. Required for Node.js. Returns: Node.js: Promise This method triggers a response to the given request automatically. Cloudflare workers: Promise The response to be returned from the request handler. ``` -------------------------------- ### Shopify GraphQL Client via CDN Source: https://github.com/shopify/shopify-api-js/blob/main/packages/graphql-client/README.md Example of how to include and initialize the Shopify GraphQL Client using a CDN link. ```html ``` -------------------------------- ### GraphQL Codegen Configuration with @shopify/api-codegen-preset Source: https://github.com/shopify/shopify-api-js/blob/main/packages/api-codegen-preset/README.md Example configuration for graphql-codegen using the @shopify/api-codegen-preset. This setup enables `#graphql` tag support, defines schema and document locations, and configures type generation for different API types (Admin, Storefront, etc.). ```ts import { ApiType, pluckConfig, preset } from "@shopify/api-codegen-preset"; export default { // For syntax highlighting / auto-complete when writing operations schema: "https://shopify.dev/admin-graphql-direct-proxy", documents: ["./**/*.{js,ts,jsx,tsx}"], projects: { default: { // For type extraction schema: "https://shopify.dev/admin-graphql-direct-proxy", documents: ["./**/*.{js,ts,jsx,tsx}"], extensions: { codegen: { // Enables support for `#graphql` tags, as well as `/* GraphQL */` pluckConfig, generates: { "./types/admin.schema.json": { plugins: ["introspection"], config: { minify: true }, }, "./types/admin.types.d.ts": { plugins: ["typescript"], }, "./types/admin.generated.d.ts": { preset, presetConfig: { apiType: ApiType.Admin, }, }, }, }, }, }, }, }; ``` -------------------------------- ### Install @shopify/api-codegen-preset Source: https://github.com/shopify/shopify-api-js/blob/main/packages/api-codegen-preset/README.md Installs the @shopify/api-codegen-preset package as a development dependency using yarn, npm, or pnpm. ```sh yarn add --dev @shopify/api-codegen-preset ``` ```sh npm add --save-dev @shopify/api-codegen-preset ``` ```sh pnpm add -D @shopify/api-codegen-preset ``` -------------------------------- ### Storefront Client API Migration (Before) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v8.md Example demonstrating the previous method of creating a Storefront API client using `domain` and `storefrontAccessToken`. ```ts 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 adminApiClient = new shopify.clients.Rest({ session }); const storefrontTokenResponse = await adminApiClient.post({ path: 'storefront_access_tokens', data: { storefront_access_token: { title: 'This is my test access token', }, }, }); const storefrontAccessToken = storefrontTokenResponse.body.storefront_access_token.access_token; // For simplicity, this example creates a token every time it's called, but that is not ideal. // You can fetch existing Storefront access tokens using the Admin API client. const storefrontClient = new shopify.clients.Storefront({ domain: session.shop, storefrontAccessToken, apiVersion: ApiVersion.January23, }); }); ``` -------------------------------- ### Storefront Client Constructor Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Storefront.md Demonstrates how to construct a Storefront API client instance using a session object and API version. ```ts 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, }); }); ``` -------------------------------- ### Storefront Client API Migration (After) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v8.md Example demonstrating the updated method of creating a Storefront API client using the `session` object. ```ts 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, }); }); ``` -------------------------------- ### Query for a Product using REST Client Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md Shows how to fetch product data from the Shopify Admin API using the initialized REST client. This example performs a GET request for a specific product identified by its ID and demonstrates how to handle the response, including parsing the JSON body. ```typescript const response = await client.get("products/1234567890"); if (response.ok) { const body = await response.json(); } ``` -------------------------------- ### Query for a product Source: https://github.com/shopify/shopify-api-js/blob/main/packages/graphql-client/README.md Example of how to query for product information using the Shopify API client. It demonstrates making a GraphQL request and accessing the returned data, errors, and extensions. ```typescript const productQuery = " query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } "; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, }); ``` -------------------------------- ### CDN Usage Source: https://github.com/shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md Example of how to include the Storefront API Client via CDN and initialize it. ```html // The minified `0.2.3` version of the Storefront API Client ``` -------------------------------- ### Get All Resources Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/rest-resources.md Explains how to fetch a list of all products using the `shopify.rest.Product.all` method. This method returns the product data, pagination information, and response headers. The example shows how to access these properties. ```ts // Session is built by the OAuth process const products = await shopify.rest.Product.all({ session: session, }); // The list of products console.log(products.data); // The pagination information console.log(products.pageInfo); // The response headers console.log(products.headers); ``` -------------------------------- ### Initialize Shopify API Instance (shopify.js) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md Creates a new shopify.js file to initialize the Shopify API instance. It includes importing the Node.js adapter, configuring API keys, scopes, and other settings, and setting up optional billing configurations. This example demonstrates how to set up the API for use in a Node.js environment. ```javascript import '@shopify/shopify-api/adapters/node'; import { shopifyApi, BillingInterval, LATEST_API_VERSION, LogSeverity, } from '@shopify/shopify-api'; let {restResources} = await import( `@shopify/shopify-api/rest/admin/${LATEST_API_VERSION}` ); // The transactions with Shopify will always be marked as test transactions, unless NODE_ENV is production. // See the ensureBilling helper to learn more about billing in this template. const billingConfig = { 'My Shopify One-Time Charge': { // This is an example configuration that would do a one-time charge for $5 (only USD is currently supported) amount: 5.0, currencyCode: 'USD', interval: BillingInterval.OneTime, }, }; const apiConfig = { apiKey: process.env.SHOPIFY_API_KEY, apiSecretKey: process.env.SHOPIFY_API_SECRET, scopes: process.env.SCOPES.split(','), hostName: process.env.HOST.replace(/https?:\/\//, ''), hostScheme: process.env.HOST.split('://')[0], apiVersion: LATEST_API_VERSION, isEmbeddedApp: true, ...(process.env.SHOP_CUSTOM_DOMAIN && { customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN], }), billing: undefined, // or replace with billingConfig above to enable example billing restResources, }; const shopify = shopifyApi(apiConfig); export default shopify; ``` -------------------------------- ### Install Shopify API Package Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md Installs or updates the @shopify/shopify-api package to the latest version using common package managers like yarn, npm, or pnpm. ```shell yarn install # or npm install # or pnpm install ``` -------------------------------- ### Shopify API Response Examples Source: https://github.com/shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md Illustrates the structure of successful and error responses from the Shopify API. Includes examples for network errors and GraphQL API errors, detailing the fields like `networkStatusCode`, `message`, and `graphQLErrors`. ```json { "data": { "product": { "id": "gid://shopify/Product/12345678912", "title": "Sample product # 1" } }, "extensions": { "context": { "country": "US", "language": "EN" } } } ``` ```json { "errors": { "networkStatusCode": 401, "message": "" } } ``` ```json { "errors": { "networkStatusCode": 200, "message": "An error occurred while fetching from the API. Review the `graphQLErrors` object for details.", "graphQLErrors": [ { "message": "Field 'testField' doesn't exist on type 'Product'", "locations": [ { "line": 17, "column": 3 } ], "path": ["fragment ProductFragment", "testField"], "extensions": { "code": "undefinedField", "typeName": "Product", "fieldName": "testField" } } ] } } ``` -------------------------------- ### Node.js Callback Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/callback.md Example of handling the Shopify OAuth callback in a Node.js environment. It uses `shopify.auth.callback` to process the request and redirect the user. ```ts 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'); }); ``` -------------------------------- ### Install Updated Library Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md After updating package.json, install the new version of the library using your preferred package manager. ```shell yarn install # or npm install # or pnpm install ``` -------------------------------- ### Install Dependencies for Shopify API Codegen Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/graphql-types.md Installs the necessary packages for Shopify API codegen, including the preset and the API clients. These commands are provided for yarn, npm, and pnpm package managers. ```bash yarn add --dev @shopify/api-codegen-preset yarn add @shopify/admin-api-client @shopify/storefront-api-client ``` ```bash npm add --save-dev @shopify/api-codegen-preset npm add @shopify/admin-api-client @shopify/storefront-api-client ``` ```bash pnpm add --save-dev @shopify/api-codegen-preset pnpm add @shopify/admin-api-client @shopify/storefront-api-client ``` -------------------------------- ### Storefront API Request Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/Storefront.md Shows how to send a GraphQL query to the Storefront API using the client's request method. ```ts const products = await storefrontClient.request( `{ products (first: 10) { edges { node { id title descriptionHtml } } } }`, ); // do something with the returned data ``` -------------------------------- ### Process Webhooks (Cloudflare Workers) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md Provides an example of how to process incoming Shopify webhooks within a Cloudflare Workers environment. It demonstrates using `shopify.webhooks.process` with the raw request body obtained from `request.text()` and passing context information. ```javascript 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); } } ``` -------------------------------- ### Webhook Processing Example (Worker Environment) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/webhooks/process.md Illustrates the usage of shopify.webhooks.process in a Cloudflare Workers environment, showing how to handle the response or errors. ```ts let response: Response; try { response = await shopify.webhooks.process({ rawBody: req.body, rawRequest: req, rawResponse: res, }); } catch (error) { console.log(error.message); response = error.response; } return response; ``` -------------------------------- ### Install SQLite Session Storage Adapter Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/example-migration-v5-node-template-to-v6.md Installs the @shopify/shopify-app-session-storage-sqlite package using Yarn, npm, or pnpm. This package provides the necessary adapter for storing Shopify session data in a SQLite database. ```shell yarn add @shopify/shopify-app-session-storage-sqlite # or npm install @shopify/shopify-app-session-storage-sqlite # or pnpm install @shopify/shopify-app-session-storage-sqlite ``` -------------------------------- ### Shopify Type Update Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v8.md Demonstrates the change in how the Shopify type is defined, requiring explicit passing of ConfigParams for apps that previously set the resources generic. ```typescript import {restResources} from '@shopify/shopify-api/rest/admin/2023-10'; const myVariable: Shopify; ``` ```typescript import { restResources, ConfigParams, } from '@shopify/shopify-api/rest/admin/2023-10'; const myVariable: Shopify; ``` -------------------------------- ### GraphQL Proxy Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/clients/graphqlProxy.md Demonstrates how to use the `graphqlProxy` method to forward a GraphQL request from the client side to the Shopify Admin API. It includes session retrieval and handling the response. ```javascript 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); }); ``` -------------------------------- ### Update Version String for Release Candidate Source: https://github.com/shopify/shopify-api-js/blob/main/RELEASING.md Example of how to format the version string in package.json or version.ts for a release candidate. ```text 7.0.0-rc.1 ``` -------------------------------- ### Webhook Processing Example (Node.js) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/webhooks/process.md Demonstrates how to use shopify.webhooks.process in a Node.js Express application. It includes setting up middleware to read the raw request body as text. ```ts app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => { try { await shopify.webhooks.process({ rawBody: req.body, // is a string rawRequest: req, rawResponse: res, }); } catch (error) { console.log(error.message); } }); ``` -------------------------------- ### Codegen Configuration File (.graphqlrc.ts) Source: https://github.com/shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md Example configuration file for the GraphQL Codegen CLI using the Shopify API preset. It specifies the schema endpoint, documents to scan, and project settings including API type, version, and output directory for generated types. ```typescript import { ApiType, shopifyApiProject } from "@shopify/api-codegen-preset"; export default { schema: "https://shopify.dev/storefront-graphql-direct-proxy", documents: ["*.ts", "!node_modules"], projects: { default: shopifyApiProject({ apiType: ApiType.Storefront, apiVersion: "2023-10", outputDir: "./types", }), }, }; ``` -------------------------------- ### Node.js OAuth Initiation Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/begin.md Initiates the OAuth process by redirecting the merchant to Shopify's authentication screen. This example demonstrates usage within a Node.js Express.js route. ```ts 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, }); }); ``` -------------------------------- ### Configure Billing Plans Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md Demonstrates how to configure billing plans in the shopify-api-js library. The 'After' example shows the updated approach where multiple billing plans can be indexed by their names. ```typescript const shopify = shopifyApi({ // ... billing: { 'My plan': { amount: 5.0, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, }, }); ``` -------------------------------- ### Plan Overrides Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/billing/request.md Demonstrates how to override billing configuration fields like trialDays and amount at request time when calling shopify.billing.request. ```javascript const billingResponse = await shopify.billing.request({ session: callback.session, plan: 'My billing plan', returnObject: true, isTest: true, trialDays: 4, // Overrides the trial days set in 'My billing plan' amount: 13, // Overrides the amount set in 'My billing plan' }); res.redirect(billingResponse.confirmationUrl); ``` -------------------------------- ### Register Webhooks Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/webhooks/register.md Demonstrates how to register Shopify webhooks after a successful OAuth callback. It includes error handling for webhook registration failures. ```ts 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 }); ``` -------------------------------- ### Cloudflare Workers Callback Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/callback.md Example of handling the Shopify OAuth callback in a Cloudflare Workers environment. It processes the request and returns a response with redirect headers. ```ts async function handleFetch(request: Request): Promise { const callback = await shopify.auth.callback({ rawRequest: request, }); // You can now use callback.session to make API requests // The callback returns some HTTP headers, but you can redirect to any route here return new Response('', { status: 302, // Headers are of type [string, string][] headers: [...callback.headers, ['Location', '/my-apps-entry-page']], }); } ``` -------------------------------- ### Network Error Response Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md An example of a network error response from the Shopify API client, indicating an unauthorized request with a 401 status code and a corresponding error message. ```json { "networkStatusCode": 401, "message": "Unauthorized" } ``` -------------------------------- ### Token Exchange Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/auth/tokenExchange.md Demonstrates how to initiate the token exchange process in a Node.js application using the shopify-api-js library. It shows how to extract the session token from request headers or URL parameters and then calls the `shopify.auth.tokenExchange` function. ```ts app.get('/auth', async (req, res) => { const shop = shopify.utils.sanitizeShop(req.query.shop, true) const headerSessionToken = getSessionTokenHeader(request); const searchParamSessionToken = getSessionTokenFromUrlParam(request); const sessionToken = (headerSessionToken || searchParamSessionToken)!; await shopify.auth.tokenExchange({ sessionToken, shop, requestedTokenType: RequestedTokenType.OfflineAccessToken // or RequestedTokenType.OnlineAccessToken }); }); function getSessionTokenHeader(request){ // Get session token from header `authorization` // Header Format is: "Authorization", "Bearer this-is-the-session-token" // Return "this-is-the-session-token" from request header } function getSessionTokenFromUrlParam(request){ // Get session token from the request URL param // The param is "id_token" // Example: "${app_url}/?shop=${shop}&id_token=this-is-the-session-token" // Return "this-is-the-session-token" from URL param } ``` -------------------------------- ### Handling Registration Errors Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md Provides an example of how to check for and log errors from the webhook registration response in v6. ```javascript response = { PRODUCTS_CREATE: [ { deliveryMethod: DeliveryMethod.Http; success: false; result: { errors: [ { message: "Error message", } ]; }; }, ], } if (!response["PRODUCTS_CREATE"][0].success) { console.log(response["PRODUCTS_CREATE"][0].result.errors[0].message); // "Error message" } ``` -------------------------------- ### Get Webhook Handlers Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/migrating-to-v6.md Demonstrates the change from `getHandler` to `getHandlers` for retrieving webhook configurations. ```javascript Shopify.Webhooks.Registry.addHandler({ topic: 'PRODUCTS', path: '/webhooks', webhookHandler: productsWebhookHandler, }); // Previously, getHandler would retrieve a specific handler. // Now, getHandlers retrieves all handlers for a topic. ``` -------------------------------- ### GraphQL Query with Type Generation Source: https://github.com/shopify/shopify-api-js/blob/main/packages/api-codegen-preset/README.md An example of a TypeScript GraphQL query that utilizes the `#graphql` tag for codegen and demonstrates type casting with generated types. ```ts import "../types/admin.generated.d.ts"; const response = await myGraphqlClient.graphql( `#graphql query getProducts($first: Int!) { products(first: $first) { edges { node { id handle } } } }`, { variables: { first: 1, } as GetProductsQueryVariables, } ); const data: GetProductsQuery = response.data; ``` -------------------------------- ### Get Shopify Session ID Example Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/reference/session/getCurrentId.md Demonstrates how to use `shopify.session.getCurrentId` to extract a session ID from a request and subsequently retrieve session data. ```typescript app.get('/fetch-some-data', 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); // Build a client and make requests with session.accessToken // See the REST, GraphQL, or Storefront API documentation for more information }); ``` -------------------------------- ### Shopify API Request Examples Source: https://github.com/shopify/shopify-api-js/blob/main/packages/storefront-api-client/README.md Demonstrates various ways to use the `client.request()` method for different Shopify API operations, including product queries, cart mutations, and shop information retrieval. It also shows how to dynamically set API versions, add custom headers, and configure retries. ```typescript const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, }); ``` ```typescript 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; } ``` ```typescript 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', }, }); ``` ```typescript const shopQuery = ` query shop { shop { name id } } `; const {data, errors, extensions} = await client.request(shopQuery); ``` ```typescript const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, apiVersion: '2023-07', }); ``` ```typescript 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', }, }); ``` ```typescript const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, retries: 2, }); ``` -------------------------------- ### Shopify API Codegen Configuration Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md Provides instructions and configuration examples for using `@shopify/api-codegen-preset` to generate TypeScript types from GraphQL operations, enhancing type safety. ```bash npm install --save-dev @shopify/api-codegen-preset ``` ```typescript import { ApiType, shopifyApiProject } from "@shopify/api-codegen-preset"; export default { schema: "https://shopify.dev/admin-graphql-direct-proxy", documents: ["*.ts", "!node_modules"], projects: { default: shopifyApiProject({ apiType: ApiType.Admin, apiVersion: "2023-10", outputDir: "./types", }), }, }; ``` ```json { "scripts": { "graphql-codegen": "graphql-codegen" } } ``` ```typescript const {data, errors, extensions} = await client.request( `#graphql query Shop { shop { name } }` ); console.log(data?.shop.name); ``` -------------------------------- ### Query for a Product Source: https://github.com/shopify/shopify-api-js/blob/main/packages/admin-api-client/README.md Demonstrates how to query for a specific product using its ID with the Shopify API client. This example shows the GraphQL query and how to pass variables and handle the response. ```typescript const productQuery = "\n query ProductQuery($id: ID!) {\n product(id: $id) {\n id\n title\n handle\n }\n }\n"; const {data, errors, extensions} = await client.request(productQuery, { variables: { id: 'gid:////shopify/Product/7608002183224', }, }); ``` -------------------------------- ### Shopify API JS Webhooks Reference Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md API documentation for the Shopify API JS library's webhook functionalities. Covers methods like `addHandlers`, `register`, `validate`, and `process`, detailing their parameters, return values, and usage contexts. ```APIDOC shopify.webhooks.addHandlers(handlers: WebhookHandlers) - Registers webhook handlers for specific topics. - Parameters: - handlers: An object where keys are webhook topics (e.g., 'PRODUCTS_CREATE') and values are arrays of handler configurations. - Each handler configuration can include: - deliveryMethod: The method for delivering the webhook (e.g., DeliveryMethod.Http). - callbackUrl: The URL to send the webhook to (if deliveryMethod is Http). - callback: An optional function to execute when the webhook is processed. shopify.webhooks.register(options: { session: Session }): Promise - Registers the configured webhook handlers with Shopify for a given session. - Parameters: - session: The authenticated session object for the shop. - Returns: A promise that resolves to an object detailing the success or failure of each webhook registration. shopify.webhooks.validate(options: { rawBody: string, rawRequest: any, rawResponse: any }): Promise<{ valid: boolean, topic: string, domain: string }> - Validates an incoming webhook request. - Parameters: - rawBody: The raw string body of the incoming webhook request. - rawRequest: The original request object (e.g., Express request). - rawResponse: The original response object (e.g., Express response). - Returns: A promise that resolves to an object indicating if the webhook is valid, along with its topic and shop domain. shopify.webhooks.process(options: { rawBody: string, rawRequest: any, rawResponse: any, context?: any }): Promise - Processes an incoming webhook request, executing registered callbacks if provided. - Parameters: - rawBody: The raw string body of the incoming webhook request. - rawRequest: The original request object (e.g., Express request). - rawResponse: The original response object (e.g., Express response). - context: Optional context object, useful for environments like Cloudflare Workers. - Note: This method expects the body to be a string and does not read the request body directly. ``` -------------------------------- ### Configure a One-Time Charge Source: https://github.com/shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/billing.md Provides an example of how to configure a one-time charge for a Shopify app. This setup is used for single, non-recurring payments and specifies the amount and currency code. ```typescript import { shopifyApi, BillingInterval, BillingReplacementBehavior, } from '@shopify/shopify-api'; const shopify = shopifyApi({ // ... billing: { { "One Time Charge": { interval: BillingInterval.OneTime, amount: 30, currencyCode: "USD", }, }, } future: { v10_lineItemBilling: true, }); ```