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
Your shop’s myshopify.com domain (e.g., shop.myshopify.com)
The Admin API version to use (e.g., 2025-01)
Admin API access token for authentication
Custom prefix for the User-Agent header
Number of retry attempts for failed requests (max: 3)
Custom fetch implementation for Node.js environments
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:
The GraphQL response data. Type is TData if provided, otherwise any
API or network errors (does not include UserErrors)
Additional response metadata, including cost information
ResponseErrors
HTTP response status code
Error message description
Array of GraphQL errors from the API
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' ,
});
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
Client configuration including store domain, API version, and headers
Returns merged default and custom headers
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
Your shop’s myshopify.com domain
The Admin API version to use
Number of retry attempts (max: 3)
scheme
'http' | 'https'
default: "'https'"
HTTP scheme for requests
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 );
}
const response = await client . post ( 'products' , {
data: {
product: {
title: 'New Product' ,
product_type: 'Shoes' ,
},
},
});
if ( response . ok ) {
const body = await response . json ();
console . log ( 'Created:' , body . product . id );
}
const response = await client . put ( 'products/1234567890' , {
data: {
product: {
title: 'Updated Title' ,
},
},
});
if ( response . ok ) {
const body = await response . json ();
console . log ( 'Updated:' , body . product );
}
const response = await client . delete ( 'products/1234567890' );
if ( response . ok ) {
console . log ( 'Product deleted' );
}
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' },
}
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:
Install codegen preset
npm install --save-dev @shopify/api-codegen-preset
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' ,
}),
} ,
} ;
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 );
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
Sent when an HTTP response is received {
type : 'HTTP-Response' ,
content : {
requestParams : [ url , init ],
response : Response
}
}
Sent when the client retries a request {
type : 'HTTP-Retry' ,
content : {
requestParams : [ url , init ],
lastResponse : Response ,
retryAttempt : number ,
maxRetries : number
}
}
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