@shopify/shopify-api is the foundation library for building Shopify apps in Node.js and JavaScript runtime environments. It provides OAuth authentication, Admin and Storefront API clients, webhook handling, billing integration, and session management.
Installation
npm install @shopify/shopify-api
Requires Node.js >= 20.0.0
Getting Started
Initialize the API
The shopifyApi() function creates a configured Shopify API instance:
import { shopifyApi , ApiVersion , LogSeverity } from "@shopify/shopify-api" ;
import "@shopify/shopify-api/adapters/node" ;
const shopify = shopifyApi ({
// Required: API credentials
apiKey: process . env . SHOPIFY_API_KEY ,
apiSecretKey: process . env . SHOPIFY_API_SECRET ,
// Required: OAuth scopes
scopes: [ "read_products" , "write_products" ],
// Required: Your app's hostname
hostName: process . env . HOST ?. replace ( /https ? : \/\/ / , "" ),
// Required: API version
apiVersion: ApiVersion . January24 ,
// Whether app is embedded in Shopify Admin
isEmbeddedApp: true ,
// Custom store app settings
isCustomStoreApp: false ,
// Logging configuration
logger: {
level: LogSeverity . Info ,
httpRequests: true ,
timestamps: true ,
},
});
Configuration Parameters
Your app’s API key (Client ID). Found in Partner Dashboard.
Your app’s API secret (Client Secret). Found in Partner Dashboard.
OAuth scopes your app needs. Not required for Shopify managed installation. Examples: ["read_products", "write_orders"]
Your app’s hostname (without protocol). Example: "myapp.example.com"
hostScheme
'http' | 'https'
default: "https"
URL scheme for your app.
Shopify API version to use. Example: ApiVersion.January24
Whether the app is embedded in Shopify Admin.
Whether this is a custom store app (private app).
App-wide access token for custom apps only.
REST resources for type-safe REST API access. import { restResources } from "@shopify/shopify-api/rest/admin/2024-01" ;
Authentication
OAuth Flow
Begin OAuth
Start the OAuth process: // Redirect user to Shopify authorization
const authRoute = await shopify . auth . begin ({
shop: "example.myshopify.com" ,
callbackPath: "/auth/callback" ,
isOnline: false ,
rawRequest: request ,
rawResponse: response ,
});
Handle Callback
Process the OAuth callback: // In your /auth/callback route
const callback = await shopify . auth . callback ({
rawRequest: request ,
rawResponse: response ,
});
const { session , headers } = callback ;
// Save session to your database
await sessionStorage . storeSession ( session );
Validate Requests
Validate authenticated requests: // Validate session token (for embedded apps)
const sessionId = await shopify . session . getCurrentId ({
isOnline: true ,
rawRequest: request ,
rawResponse: response ,
});
// Load session from storage
const session = await sessionStorage . loadSession ( sessionId );
Session Management
The Session class stores authentication data:
import { Session } from "@shopify/shopify-api" ;
// Create a session
const session = new Session ({
id: "offline_shop.myshopify.com" ,
shop: "shop.myshopify.com" ,
state: "state-value" ,
isOnline: false ,
});
// Session properties
session . id ; // Unique session identifier
session . shop ; // Shop domain
session . accessToken ; // OAuth access token
session . scope ; // Granted scopes
session . expires ; // Token expiration date
session . isOnline ; // Online vs offline token
session . onlineAccessInfo ; // User info for online tokens
API Clients
GraphQL Client
Make GraphQL requests to the Admin API:
import { GraphqlQueryError } from "@shopify/shopify-api" ;
// Create client
const client = new shopify . clients . Graphql ({ session });
// Make a request
try {
const response = await client . request (
`query getProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
}
}
}
}` ,
{
variables: { first: 10 },
}
);
const products = response . data . products . edges ;
} catch ( error ) {
if ( error instanceof GraphqlQueryError ) {
console . error ( "GraphQL errors:" , error . body ?. errors );
}
}
Execute a GraphQL query or mutation. Parameters:
operation (string): GraphQL query/mutation
options (object):
variables: Query variables
headers: Custom headers
retries: Number of retry attempts
Returns: Promise<{data, extensions}>
REST Client
Make REST API requests:
import { restResources } from "@shopify/shopify-api/rest/admin/2024-01" ;
const shopify = shopifyApi ({
// ... other config
restResources ,
});
// Create client
const client = new shopify . clients . Rest ({ session });
// Make requests
const response = await client . get ({
path: "products" ,
query: { limit: 10 },
});
const products = response . body . products ;
GET Request
POST Request
PUT Request
DELETE Request
const response = await client . get ({
path: "products/123" ,
});
REST Resources (Type-Safe)
Use typed REST resources for better developer experience:
import { restResources } from "@shopify/shopify-api/rest/admin/2024-01" ;
const shopify = shopifyApi ({
restResources ,
// ... other config
});
// Use typed resources
const products = await shopify . rest . Product . all ({
session ,
limit: 10 ,
});
const product = await shopify . rest . Product . find ({
session ,
id: 123 ,
});
const newProduct = new shopify . rest . Product ({ session });
newProduct . title = "My New Product" ;
newProduct . vendor = "My Vendor" ;
await newProduct . save ({ update: true });
Storefront API Client
Access the Storefront API:
const client = new shopify . clients . Storefront ({
domain: "shop.myshopify.com" ,
storefrontAccessToken: "your-storefront-token" ,
});
const response = await client . request (
`query {
products(first: 10) {
edges {
node {
id
title
}
}
}
}`
);
Webhooks
Register Webhooks
HTTP Webhooks
EventBridge Webhooks
PubSub Webhooks
import { DeliveryMethod } from "@shopify/shopify-api" ;
shopify . webhooks . addHandlers ({
PRODUCTS_CREATE: {
deliveryMethod: DeliveryMethod . Http ,
callbackUrl: "https://myapp.com/webhooks/products/create" ,
callback : async ( topic , shop , body , webhookId ) => {
const payload = JSON . parse ( body );
console . log ( `Product created: ${ payload . id } ` );
},
},
ORDERS_PAID: {
deliveryMethod: DeliveryMethod . Http ,
callbackUrl: "https://myapp.com/webhooks/orders/paid" ,
callback : async ( topic , shop , body ) => {
// Handle order paid webhook
},
},
});
// Register webhooks for a shop
await shopify . webhooks . register ({ session });
import { DeliveryMethod } from "@shopify/shopify-api" ;
shopify . webhooks . addHandlers ({
PRODUCTS_UPDATE: {
deliveryMethod: DeliveryMethod . EventBridge ,
arn: "arn:aws:events:us-east-1:123456789012:event-bus/shopify-webhooks" ,
},
});
import { DeliveryMethod } from "@shopify/shopify-api" ;
shopify . webhooks . addHandlers ({
CUSTOMERS_CREATE: {
deliveryMethod: DeliveryMethod . PubSub ,
pubSubProject: "my-project-id" ,
pubSubTopic: "shopify-webhooks" ,
},
});
Validate & Process Webhooks
import "@shopify/shopify-api/adapters/node" ;
// In your webhook handler endpoint
export async function handleWebhook ( request , response ) {
// Validate webhook
const isValid = await shopify . webhooks . validate ({
rawBody: await request . text (),
rawRequest: request ,
});
if ( ! isValid ) {
return response . status ( 401 ). send ( "Unauthorized" );
}
// Process webhook
await shopify . webhooks . process ({
rawBody: await request . text (),
rawRequest: request ,
});
return response . status ( 200 ). send ( "OK" );
}
Billing
Request Billing Approval
import { BillingInterval } from "@shopify/shopify-api" ;
const shopify = shopifyApi ({
// ... other config
billing: {
"My Plan" : {
amount: 10.0 ,
currencyCode: "USD" ,
interval: BillingInterval . Every30Days ,
},
},
});
// Request payment
const response = await shopify . billing . request ({
session ,
plan: "My Plan" ,
isTest: true , // Test mode
});
// Redirect merchant to confirmation URL
redirect ( response . confirmationUrl );
Check Billing Status
// Check if shop has active subscription
const hasActivePayment = await shopify . billing . check ({
session ,
plans: [ "My Plan" ],
isTest: true ,
});
if ( ! hasActivePayment ) {
// Request billing approval
}
Usage-Based Billing
// Create usage record
await shopify . billing . createUsageRecord ({
session ,
subscriptionLineItemId: "gid://shopify/AppSubscriptionLineItem/123" ,
price: 1.0 ,
description: "API call" ,
});
Utilities
Shop Validation
const shop = shopify . utils . sanitizeShop ( "example.myshopify.com" );
// Returns: "example.myshopify.com" or null if invalid
HMAC Validation
const isValid = shopify . utils . validateHmac ({
hmac: "received-hmac" ,
secret: shopify . config . apiSecretKey ,
query: request . query ,
});
Decode Session Token
const payload = await shopify . session . decodeSessionToken (
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
);
console . log ( payload . dest ); // Shop domain
console . log ( payload . sub ); // User ID
Runtime Adapters
The library supports multiple JavaScript runtimes:
Node.js
Cloudflare Workers
Web API (Deno, Bun)
import "@shopify/shopify-api/adapters/node" ;
import { shopifyApi } from "@shopify/shopify-api" ;
const shopify = shopifyApi ({ /* config */ });
import "@shopify/shopify-api/adapters/cf-worker" ;
import { shopifyApi } from "@shopify/shopify-api" ;
const shopify = shopifyApi ({ /* config */ });
import "@shopify/shopify-api/adapters/web-api" ;
import { shopifyApi } from "@shopify/shopify-api" ;
const shopify = shopifyApi ({ /* config */ });
Error Handling
import {
GraphqlQueryError ,
HttpResponseError ,
InvalidHmacError ,
InvalidJwtError ,
MissingRequiredArgument ,
SessionNotFound ,
} from "@shopify/shopify-api" ;
try {
await client . request ( query );
} catch ( error ) {
if ( error instanceof GraphqlQueryError ) {
console . error ( "GraphQL errors:" , error . body ?. errors );
} else if ( error instanceof HttpResponseError ) {
console . error ( "HTTP error:" , error . response . code );
} else if ( error instanceof InvalidJwtError ) {
console . error ( "Invalid session token" );
}
}
Always validate sessions and webhooks before processing requests to ensure security.
API Reference
The shopifyApi() function returns an object with these properties:
interface Shopify {
config : ConfigInterface ; // Configuration
clients : ShopifyClients ; // API clients
auth : ShopifyAuth ; // OAuth methods
session : ShopifySession ; // Session utilities
utils : ShopifyUtils ; // Helper functions
webhooks : ShopifyWebhooks ; // Webhook handling
billing : ShopifyBilling ; // Billing API
logger : ShopifyLogger ; // Logging
rest : ShopifyRestResources ; // REST resources
flow : ShopifyFlow ; // Shopify Flow
fulfillmentService : FulfillmentService ; // Fulfillment
}
Next Steps
Remix Integration Learn how to use with Remix
Express Integration Learn how to use with Express
Session Storage Configure session storage backends