Skip to main content
The Admin API Client provides a lightweight interface for interacting with Shopify’s Admin API. It supports both GraphQL and REST endpoints with built-in authentication, retries, and type safety.

Installation

npm install @shopify/admin-api-client

GraphQL Client

Basic Setup

Create a client instance with your store credentials:
import {createAdminApiClient} from '@shopify/admin-api-client';

const client = createAdminApiClient({
  storeDomain: 'your-shop-name.myshopify.com',
  apiVersion: '2025-01',
  accessToken: 'your-admin-api-access-token',
});

Configuration Options

storeDomain
string
required
Your shop’s myshopify.com domain (e.g., shop.myshopify.com)
apiVersion
string
required
The Admin API version to use (e.g., 2025-01)
accessToken
string
required
Admin API access token for authentication
userAgentPrefix
string
Custom prefix for the User-Agent header
retries
number
default:"0"
Number of retry attempts for failed requests (max: 3)
customFetchApi
function
Custom fetch implementation for Node.js environments
logger
function
Logger function for debugging and monitoring

Making GraphQL Requests

Using request()

The request() method returns a normalized response with data and errors:
const operation = `
  query ProductQuery($id: ID!) {
    product(id: $id) {
      id
      title
      handle
      description
    }
  }
`;

const {data, errors, extensions} = await client.request(operation, {
  variables: {
    id: 'gid://shopify/Product/7608002183224',
  },
});

if (errors) {
  console.error('Error:', errors.message);
} else {
  console.log('Product:', data.product.title);
}

Using fetch()

The fetch() method returns the raw Response object:
const shopQuery = `
  query {
    shop {
      name
      email
    }
  }
`;

const response = await client.fetch(shopQuery);

if (response.ok) {
  const {data, errors, extensions} = await response.json();
  console.log('Shop name:', data.shop.name);
}

Response Types

ClientResponse

The request() method returns a ClientResponse object:
data
TData | any
The GraphQL response data. Type is TData if provided, otherwise any
errors
ResponseErrors
API or network errors (does not include UserErrors)
extensions
Record<string, any>
Additional response metadata, including cost information

ResponseErrors

networkStatusCode
number
HTTP response status code
message
string
Error message description
graphQLErrors
any[]
Array of GraphQL errors from the API
response
Response
Raw Response object from fetch

Advanced Usage

Dynamic API Versions

Override the API version per request:
const {data} = await client.request(operation, {
  variables: {id: 'gid://shopify/Product/123'},
  apiVersion: '2024-10',
});

Custom Headers

Add custom headers to individual requests:
const {data} = await client.request(operation, {
  variables: {id: 'gid://shopify/Product/123'},
  headers: {
    'X-GraphQL-Cost-Include-Fields': '1',
  },
});

Request-Level Retries

Override retry count for specific requests:
const {data} = await client.request(operation, {
  variables: {handle: 'sample-product'},
  retries: 2,
});

Client Methods

config
AdminApiClientConfig
Client configuration including store domain, API version, and headers
getHeaders
(customHeaders?) => Record<string, string>
Returns merged default and custom headers
getApiUrl
(apiVersion?) => string
Returns the GraphQL API URL for the specified version
fetch
(operation, options?) => Promise<Response>
Makes a raw fetch request and returns the Response
request
<TData>(operation, options?) => Promise<ClientResponse<TData>>
Makes a request and returns a normalized response object

REST Client

Basic Setup

Create a REST API client:
import {createAdminRestApiClient} from '@shopify/admin-api-client';

const client = createAdminRestApiClient({
  storeDomain: 'your-shop-name.myshopify.com',
  apiVersion: '2025-01',
  accessToken: 'your-admin-api-access-token',
});

Configuration Options

storeDomain
string
required
Your shop’s myshopify.com domain
apiVersion
string
required
The Admin API version to use
accessToken
string
required
Admin API access token
retries
number
default:"0"
Number of retry attempts (max: 3)
scheme
'http' | 'https'
default:"'https'"
HTTP scheme for requests
formatPaths
boolean
default:"true"
Auto-format paths (e.g., products/123/admin/api/2025-01/products/123.json)

Making REST Requests

const response = await client.get('products/1234567890');

if (response.ok) {
  const body = await response.json();
  console.log('Product:', body.product);
}

Query Parameters

Add query parameters using the searchParams option:
const response = await client.get('products', {
  searchParams: {
    limit: 10,
    status: 'active',
    fields: ['id', 'title', 'handle'],
  },
});
Arrays and objects are automatically formatted:
// Becomes: ?array[]=a&array[]=b&hash[key]=value
searchParams: {
  array: ['a', 'b'],
  hash: {key: 'value'},
}

Custom Headers

Add custom headers to REST requests:
const response = await client.get('products/123', {
  headers: {
    'X-Custom-Header': 'value',
  },
});

Type Safety

Use the API Codegen Preset to generate TypeScript types:
1

Install codegen preset

npm install --save-dev @shopify/api-codegen-preset
2

Create .graphqlrc.ts

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: '2025-01',
      outputDir: './types',
    }),
  },
};
3

Tag your queries

const {data} = await client.request<ShopQuery>(
  `#graphql
  query Shop {
    shop {
      name
      email
    }
  }`,
);

// data.shop is fully typed
console.log(data?.shop.name);
4

Run codegen

npm run graphql-codegen

Error Handling

GraphQL Errors

const {data, errors} = await client.request(operation);

if (errors) {
  if (errors.networkStatusCode === 401) {
    console.error('Unauthorized');
  } else if (errors.graphQLErrors) {
    errors.graphQLErrors.forEach((error) => {
      console.error(`Field error: ${error.message}`);
      console.error(`Path: ${error.path}`);
    });
  }
}

REST Errors

const response = await client.get('products/invalid');

if (!response.ok) {
  const error = await response.json();
  console.error('Error:', error.errors);
}

Logging

Monitor requests and retries with a custom logger:
const client = createAdminApiClient({
  storeDomain: 'shop.myshopify.com',
  apiVersion: '2025-01',
  accessToken: 'token',
  logger: (log) => {
    if (log.type === 'HTTP-Response') {
      console.log('Response received:', log.content.response.status);
    } else if (log.type === 'HTTP-Retry') {
      console.log(`Retry ${log.content.retryAttempt}/${log.content.maxRetries}`);
    }
  },
});

Log Types

HTTP-Response
HTTPResponseLog
Sent when an HTTP response is received
{
  type: 'HTTP-Response',
  content: {
    requestParams: [url, init],
    response: Response
  }
}
HTTP-Retry
HTTPRetryLog
Sent when the client retries a request
{
  type: 'HTTP-Retry',
  content: {
    requestParams: [url, init],
    lastResponse: Response,
    retryAttempt: number,
    maxRetries: number
  }
}
Unsupported_Api_Version
UnsupportedApiVersionLog
Sent when an unsupported API version is used
{
  type: 'Unsupported_Api_Version',
  content: {
    apiVersion: string,
    supportedApiVersions: string[]
  }
}

Best Practices

Server-Side Only: The Admin API client should only be used in server-side environments. Never expose your Admin API access token in client-side code.
Rate Limiting: The Admin API has rate limits. Use the retries option and monitor the extensions.cost field in responses to manage your request quota.
Use GraphQL: For most use cases, prefer the GraphQL API over REST. It’s more efficient and provides better type safety with codegen.

Next Steps

API Codegen Preset

Generate TypeScript types for your queries

Admin API Reference

Explore the Admin API schema

Build docs developers (and LLMs) love