Skip to navigation

Catalyst Client

The Catalyst Client is how a Catalyst storefront calls BigCommerce’s GraphQL Storefront API. Import the instance your project configures:

import { client } from '~/client';

The client builds request URLs, sets request headers, and parses JSON responses for you. It’s published as the @bigcommerce/catalyst-client npm package, and your project configures an instance of it in client/index.ts, using the store hash, storefront token, and channel ID from your environment variables.

Client configuration

client/index.ts creates the client with createClient(). You can change these options to adjust how every request is made:

OptionTypeDescription
storeHashstringRequired. Your store hash. Catalyst reads it from BIGCOMMERCE_STORE_HASH.
storefrontTokenstringRequired. The GraphQL Storefront API private token, sent as a bearer token. Catalyst reads it from BIGCOMMERCE_STOREFRONT_TOKEN.
channelIdstringRequired. The default channel. The client throws an error at startup if it’s missing. Catalyst reads it from BIGCOMMERCE_CHANNEL_ID.
getChannelId(defaultChannelId) => string | Promise<string>Resolves the channel for each request when fetch() isn’t passed a channelId. Catalyst uses it to pick the channel mapped to the current locale in channels.config.ts, falling back to the default channel.
beforeRequest(fetchOptions) => Partial<RequestInit> | undefined (sync or async)Runs before every request and returns extra fetch options, such as headers, to merge in. Catalyst uses it to add locale and shopper IP headers (see Request headers).
onError(error, queryType) => void (sync or async)Runs when a GraphQL error is about to be thrown (see Error handling). Catalyst uses it to sign the shopper out when a query fails with a BigCommerceAuthError.
loggerbooleanEnables request logging. Catalyst sets it from CLIENT_LOGGER.
platform, backendUserAgentExtensionsstringValues appended to the User-Agent header the client sends.

There’s no hook that runs after a response is received. To act on failures, use onError or catch the errors that fetch() throws.

Methods

  • fetch(): runs any query or mutation in the GraphQL Storefront API.

  • fetchSitemapIndex(channelId?: string): fetches the XML sitemap index (/xmlsitemap.php) for a channel and returns it as text. When you omit channelId, it uses the same channel resolution as fetch().

Fetch

The following sections describe the fetch() method.

Parameters

Parameter nameTypeRequired?Description
documentobject DocumentDecoration<TResult, TVariables>YesThe GraphQL query or mutation you want to execute. It must be in the form of a string or a GraphQL AST (Abstract Syntax Tree) that defines the query.

The DocumentDecoration interface supports types from @graphql-typed-document-node/core and TypedQueryDocumentNode. These ensure the types of variables and results match. The document could be a GraphQL query or mutation.
variablesobject TVariablesNoVariables to be passed to the GraphQL query or mutation.
customerAccessTokenstringNoThe customer’s access token for authenticated requests.

This token is required for operations that need customer authentication (for example, accessing the cart, checkout, orders, or customer data) and can be populated with the getSessionCustomerAccessToken() utility function. The token is added as an X-Bc-Customer-Access-Token header.
fetchOptionsobject FetcherRequestInitNoCustom options for the fetch request.

FetcherRequestInit extends the global RequestInit interface in JavaScript, which includes parameters such as method, headers, body, and options for caching and credentials.
channelIdstringNoAllows you to specify a different storefront channel for the request.

Defaults to the channel the client’s getChannelId option resolves. In Catalyst, that’s the channel mapped to the current locale in channels.config.ts, falling back to BIGCOMMERCE_CHANNEL_ID.
errorPolicynone | auth | ignore | allNo- none (default): The client throws any GraphQL errors returned from the API, as a BigCommerceGQLError or one of its subclasses. This is useful for ensuring you properly catch errors provided through the API.

- auth: The client throws only authorization errors, for example a missing or invalid Customer Access Token, as a BigCommerceAuthError. Other errors are returned with the data.

- ignore: The client ignores any errors and returns just the data.

- all (advanced): The client returns the full response with the data, including any errors returned from the API. This lets you customize what happens with the response.
validateCustomerAccessTokenbooleanNo- true (default): The client passes a header that tells the API to return any auth-related errors, for example a missing or invalid Customer Access Token.

- false: Use for requests that include customer-specific information but shouldn’t throw an error, for example a query for the guest or customer categories in the header.

Request headers

The fetch method automatically sets the following headers:

  • "Content-Type": "application/json"
  • "Authorization": "Bearer <storefrontToken>"
  • "User-Agent": <backendUserAgent>
  • "X-Bc-Customer-Access-Token": <customerAccessToken> (when customerAccessToken is provided)
  • "X-Bc-Error-On-Invalid-Customer-Access-Token": "true" (when validateCustomerAccessToken is true)
  • "X-BC-Trusted-Proxy-Secret": <secret> (when the BIGCOMMERCE_TRUSTED_PROXY_SECRET environment variable is set)

Catalyst’s beforeRequest hook in client/index.ts also adds:

  • "Accept-Language": <locale> (when the current locale is known)
  • "X-Forwarded-For" and "True-Client-IP", set to the shopper’s IP address, and "X-Correlation-ID". These are added only to uncached requests (cache: 'no-store' or cache: 'no-cache'), because request headers are part of the Next.js Data Cache key, and per-request values would make every cached lookup miss.

Headers you pass in fetchOptions.headers override any of these.

Retries

Queries that fail with a 502, 503, or 504 response, or with a network error such as a dropped connection, are retried up to two more times, after 100 ms and then 300 ms. Each retry logs a warning. Mutations are never retried, because they aren’t safe to repeat.

Return value

The fetch method returns a promise that resolves to a response object containing the requested data. The response follows the structure defined in the GraphQL query.

  • Return Type: Promise<BigCommerceResponse<TResult>>

    The BigCommerceResponse type wraps the actual data returned from the API, where TResult represents the expected shape of the response data.

    Inside BigCommerceResponse, the data field holds the actual data returned by the GraphQL API, which matches the structure of the query or mutation you executed.

  • Errors: the method throws when the HTTP request fails, or when the API returns GraphQL errors that the errorPolicy says to throw. See Error handling.

Examples

Get customer orders (authenticated request)

import { client } from '~/client';
import { graphql } from '~/client/graphql';
import { revalidate } from '~/client/revalidate-target';
import { getSessionCustomerAccessToken } from '~/auth';
const GET_CUSTOMER_ORDERS = graphql(`
query getCustomerOrders {
customer {
orders {
edges {
node {
entityId
orderNumber
status
}
}
}
}
}
`);
const customerAccessToken = await getSessionCustomerAccessToken();
const response = await client.fetch({
document: GET_CUSTOMER_ORDERS,
customerAccessToken,
fetchOptions: customerAccessToken ? { cache: 'no-store' } : { next: { revalidate } },
});

Get product reviews (unauthenticated request)

import { client } from '~/client';
import { graphql } from '~/client/graphql'; // A utility function for handling GraphQL queries
const GET_PRODUCT_REVIEWS_QUERY = graphql(`
query getProductReviews($productIds: [Int!]) {
site {
products(entityIds: $productIds) {
edges {
node {
reviews {
edges {
node {
author {
name
}
title
text
}
}
}
}
}
}
}
}
`);
const response = await client.fetch({
document: GET_PRODUCT_REVIEWS_QUERY, // GraphQL query
variables: { productIds: [101, 202] }, // Query variables
fetchOptions: { cache: 'no-store' }, // Optional fetch options
});
console.log(response.data);

The example output in the console:

{
"site": {
"products": {
"edges": [
{
"node": {
"reviews": {
"edges": [
{
"node": {
"author": {
"name": "John Doe"
},
"title": "Great product",
"text": "This product exceeded my expectations!"
}
},
{
"node": {
"author": {
"name": "Jane Smith"
},
"title": "Good value",
"text": "Worth the price, very satisfied."
}
}
]
}
}
}
]
}
}
}

To flatten edges and node wrappers, use the removeEdgesAndNodes() utility exported by @bigcommerce/catalyst-client.

Error handling

fetch() checks the HTTP response for you and throws if something goes wrong, so wrap calls in try/catch rather than inspecting the response. @bigcommerce/catalyst-client exports these error classes:

Error classThrown when
BigCommerceAPIErrorThe HTTP request fails (a non-2xx response). Includes the HTTP status and any graphqlErrors from the response body.
InvalidStorefrontTokenErrorThe API returns 401 and the configured storefront token isn’t a JWT, which usually means an outdated token type. Extends BigCommerceAPIError.
BigCommerceGQLErrorThe API returns GraphQL errors and errorPolicy is none. The errors property holds the GraphQL errors.
BigCommerceAuthErrorA GraphQL error is an authorization error. Extends BigCommerceGQLError, and has a code property.
MissingCustomerAccessTokenErrorThe request needed a Customer Access Token and none was sent. Extends BigCommerceAuthError.
InvalidCustomerAccessTokenErrorThe Customer Access Token sent is invalid or expired. Extends BigCommerceAuthError.
import { BigCommerceAPIError, BigCommerceGQLError } from '@bigcommerce/catalyst-client';
try {
const response = await client.fetch({ document: GET_PRODUCT_REVIEWS_QUERY, variables });
return response.data;
} catch (error) {
if (error instanceof BigCommerceAPIError) {
// HTTP failure: inspect error.status
} else if (error instanceof BigCommerceGQLError) {
// GraphQL errors: inspect error.errors
}
throw error;
}

Before throwing a GraphQL error, the client calls its onError hook. By default, Catalyst’s hook redirects the shopper to sign out when a query fails with a BigCommerceAuthError, so an expired customer session is cleared automatically.

Logging

You can log the request’s operation name, type, and execution time to the console, along with the query complexity.

Logging is on by default outside production, and off in production. To change this, set the CLIENT_LOGGER environment variable to true or false. When logging is enabled, the fetch method invokes the requestLogger() function internally to capture and log the information.