Skip to main content
@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

apiKey
string
Your app’s API key (Client ID). Found in Partner Dashboard.
apiSecretKey
string
required
Your app’s API secret (Client Secret). Found in Partner Dashboard.
scopes
string[] | AuthScopes
OAuth scopes your app needs. Not required for Shopify managed installation.Examples: ["read_products", "write_orders"]
hostName
string
required
Your app’s hostname (without protocol).Example: "myapp.example.com"
hostScheme
'http' | 'https'
default:"https"
URL scheme for your app.
apiVersion
ApiVersion
required
Shopify API version to use.Example: ApiVersion.January24
isEmbeddedApp
boolean
required
Whether the app is embedded in Shopify Admin.
isCustomStoreApp
boolean
default:"false"
Whether this is a custom store app (private app).
adminApiAccessToken
string
App-wide access token for custom apps only.
restResources
ShopifyRestResources
REST resources for type-safe REST API access.
import { restResources } from "@shopify/shopify-api/rest/admin/2024-01";

Authentication

OAuth Flow

1

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,
});
2

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);
3

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);
  }
}
request
function
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;
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

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 });

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:
import "@shopify/shopify-api/adapters/node";
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

GitHub

View on GitHub

Build docs developers (and LLMs) love