> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Catalyst Client

> Reference for the Catalyst Client, which wraps the GraphQL Storefront API — configuration options, the fetch and fetchSitemapIndex methods, request headers, retries, error classes, and logging.

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

```ts showLineNumbers={false}
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`](https://github.com/bigcommerce/catalyst/tree/canary/packages/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](/developer/docs/storefront/catalyst/reference/environment-variables).

## Client configuration

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

| Option                                   | Type                                                                  | Description                                                                                                                                                                                                      |
| ---------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `storeHash`                              | string                                                                | **Required.** Your store hash. Catalyst reads it from `BIGCOMMERCE_STORE_HASH`.                                                                                                                                  |
| `storefrontToken`                        | string                                                                | **Required.** The GraphQL Storefront API private token, sent as a bearer token. Catalyst reads it from `BIGCOMMERCE_STOREFRONT_TOKEN`.                                                                           |
| `channelId`                              | string                                                                | **Required.** 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](#request-headers)).                        |
| `onError`                                | `(error, queryType) => void` (sync or async)                          | Runs when a GraphQL error is about to be thrown (see [Error handling](#error-handling)). Catalyst uses it to sign the shopper out when a query fails with a `BigCommerceAuthError`.                              |
| `logger`                                 | boolean                                                               | Enables [request logging](#logging). Catalyst sets it from `CLIENT_LOGGER`.                                                                                                                                      |
| `platform`, `backendUserAgentExtensions` | string                                                                | Values 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](/developer/docs/storefront/guides/graphql-storefront-api/overview).

* `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 name                | Type                                             | Required? | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ----------------------------- | ------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document`                    | object `DocumentDecoration<TResult, TVariables>` | Yes       | The 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.                                                                                                                                                                                                                                                                    |
| `variables`                   | object `TVariables`                              | No        | Variables to be passed to the GraphQL query or mutation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `customerAccessToken`         | string                                           | No        | The 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.                                                                                                                                                                                                                                                                                                        |
| `fetchOptions`                | object `FetcherRequestInit`                      | No        | Custom 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.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `channelId`                   | string                                           | No        | Allows 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`.                                                                                                                                                                                                                                                                                                                                                                                   |
| `errorPolicy`                 | `none` \| `auth` \| `ignore` \| `all`            | No        | - `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. |
| `validateCustomerAccessToken` | boolean                                          | No        | - `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`](/developer/docs/storefront/catalyst/reference/environment-variables#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](#error-handling).

### Examples

#### Get customer orders (authenticated request)

```ts showLineNumbers={false}
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)

```ts showLineNumbers={false}
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:

```json showLineNumbers={false}
{
  "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 class                       | Thrown when                                                                                                                                       |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BigCommerceAPIError`             | The HTTP request fails (a non-`2xx` response). Includes the HTTP `status` and any `graphqlErrors` from the response body.                         |
| `InvalidStorefrontTokenError`     | The API returns `401` and the configured storefront token isn't a JWT, which usually means an outdated token type. Extends `BigCommerceAPIError`. |
| `BigCommerceGQLError`             | The API returns GraphQL errors and `errorPolicy` is `none`. The `errors` property holds the GraphQL errors.                                       |
| `BigCommerceAuthError`            | A GraphQL error is an authorization error. Extends `BigCommerceGQLError`, and has a `code` property.                                              |
| `MissingCustomerAccessTokenError` | The request needed a Customer Access Token and none was sent. Extends `BigCommerceAuthError`.                                                     |
| `InvalidCustomerAccessTokenError` | The Customer Access Token sent is invalid or expired. Extends `BigCommerceAuthError`.                                                             |

```ts showLineNumbers={false}
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](/developer/docs/storefront/guides/graphql-storefront-api).

Logging is on by default outside production, and off in production. To change this, set the [`CLIENT_LOGGER` environment variable](/developer/docs/storefront/catalyst/reference/environment-variables#client_logger) to `true` or `false`. When logging is enabled, the `fetch` method invokes the `requestLogger()` function internally to capture and log the information.