The base GraphQL client provides low-level GraphQL functionality used by both Admin and Storefront API clients.
createGraphQLClient()
Creates a generic GraphQL client with support for queries, mutations, and streaming responses.
import { createGraphQLClient } from '@shopify/graphql-client' ;
const client = createGraphQLClient ({
url: 'https://my-store.myshopify.com/api/2025-10/graphql.json' ,
headers: {
'Content-Type' : 'application/json' ,
'X-Shopify-Access-Token' : 'your-access-token' ,
},
});
Parameters
The complete GraphQL API endpoint URL
HTTP headers to include with every request. Must include authentication headers. headers : {
'Content-Type' : 'application/json' ,
'X-Shopify-Access-Token' : 'token' ,
}
Number of retry attempts for failed requests
customFetchApi
CustomFetchApi
default: "fetch"
Custom fetch implementation. Useful for adding middleware or using in non-browser environments. type CustomFetchApi = (
url : string ,
init ?: {
method ?: string ;
headers ?: HeadersInit ;
body ?: string ;
signal ?: AbortSignal ;
keepalive ?: boolean ;
}
) => Promise < Response >;
Logger function for debugging and monitoring. Receives log events for HTTP responses, retries, and deprecation notices. type Logger = ( logContent : LogContentTypes ) => void ;
Returns
GraphQL client instance with the following properties: Read-only configuration object:
url: The GraphQL endpoint URL
headers: Default headers for all requests
retries: Number of retry attempts
Low-level fetch method that returns a raw Response object fetch ( operation : string , options ?: RequestOptions ): Promise < Response >
GraphQL request method that returns parsed response data request < TData >(
operation : string ,
options ?: RequestOptions
): Promise < ClientResponse < TData >>
Streaming request method for @defer operations requestStream < TData >(
operation : string ,
options ?: RequestOptions
): Promise < ClientStreamIterator < TData >>
Client Methods
fetch()
Executes a GraphQL operation and returns the raw Response object.
const response = await client . fetch (
`query { shop { name } }` ,
{
variables: {},
headers: { 'X-Custom' : 'value' },
}
);
const data = await response . json ();
GraphQL query or mutation string
Request options: Additional headers to merge with default headers
Override the default endpoint URL for this request
Override the default retry count for this request
AbortSignal for request cancellation
Keep connection alive for subsequent requests
request()
Executes a GraphQL operation and returns parsed response data with error handling.
const { data , errors , extensions } = await client . request (
`query getShop {
shop {
name
email
}
}`
);
if ( errors ) {
console . error ( 'GraphQL errors:' , errors . graphQLErrors );
} else {
console . log ( 'Shop:' , data . shop . name );
}
Do not use request() for operations with @defer directives. Use requestStream() instead.
Returns : Promise<ClientResponse<TData>>
The GraphQL response data
Error information if the request failed: Array of GraphQL errors from the response
Raw Response object for additional debugging
GraphQL extensions from the response (e.g., query cost information)
requestStream()
Executes a GraphQL operation with @defer directives and returns an async iterator for streaming responses.
const stream = await client . requestStream (
`query {
shop { name }
products(first: 100) @defer {
edges { node { id title } }
}
}`
);
for await ( const chunk of stream ) {
console . log ( 'Received chunk:' , chunk . data );
console . log ( 'Has more data:' , chunk . hasNext );
if ( chunk . errors ) {
console . error ( 'Chunk errors:' , chunk . errors );
}
}
Only use requestStream() for operations containing @defer directives. For regular operations, use request() instead.
Returns : Promise<ClientStreamIterator<TData>>
The async iterator yields ClientStreamResponse<TData> objects:
Accumulated GraphQL response data from all chunks received so far
true if more data chunks are expected, false when the stream is complete
Error information if the request or stream failed
GraphQL extensions from the response
Example Usage
Basic Setup
Simple Query
With Variables
Streaming with @defer
Error Handling
Custom Fetch
With Logger
Abort Request
import { createGraphQLClient } from '@shopify/graphql-client' ;
const client = createGraphQLClient ({
url: 'https://my-store.myshopify.com/admin/api/2025-10/graphql.json' ,
headers: {
'Content-Type' : 'application/json' ,
'X-Shopify-Access-Token' : process . env . ACCESS_TOKEN ,
},
retries: 2 ,
});
Types
interface ClientOptions {
headers : Record < string , string | string []>;
url : string ;
customFetchApi ?: CustomFetchApi ;
retries ?: number ;
logger ?: Logger ;
}
interface ClientConfig {
readonly headers : Record < string , string | string []>;
readonly url : string ;
readonly retries : number ;
}
interface RequestOptions {
variables ?: Record < string , any >;
url ?: string ;
headers ?: Record < string , string | string []>;
retries ?: number ;
keepalive ?: boolean ;
signal ?: AbortSignal ;
}
interface ClientResponse < TData = any > {
data ?: TData ;
errors ?: ResponseErrors ;
extensions ?: Record < string , any >;
headers ?: Headers ;
}
interface ClientStreamResponse < TData = any > extends ClientResponse < TData > {
hasNext : boolean ;
}
interface ResponseErrors {
networkStatusCode ?: number ;
message ?: string ;
graphQLErrors ?: any [];
response ?: Response ;
}
type Logger = ( logContent : LogContentTypes ) => void ;
type LogContentTypes =
| HTTPResponseLog
| HTTPRetryLog
| HTTPResponseGraphQLDeprecationNotice ;
Retry Behavior
The client automatically retries requests for certain HTTP status codes:
429 - Too Many Requests (rate limiting)
503 - Service Unavailable
Retries use exponential backoff with the following behavior:
First retry: immediate
Subsequent retries: wait time increases exponentially
Retry-After header is respected when present
const client = createGraphQLClient ({
url: API_URL ,
headers: HEADERS ,
retries: 3 , // Retry up to 3 times
});
Logging
The logger receives three types of events:
HTTP-Response
{
type : 'HTTP-Response' ,
content : {
requestParams : [ url , init ],
response : Response ,
}
}
HTTP-Retry
{
type : 'HTTP-Retry' ,
content : {
requestParams : [ url , init ],
lastResponse ?: Response ,
retryAttempt : number ,
maxRetries : number ,
}
}
HTTP-Response-GraphQL-Deprecation-Notice
{
type : 'HTTP-Response-GraphQL-Deprecation-Notice' ,
content : {
requestParams : [ url , init ],
deprecationNotice : string ,
}
}