> 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.

# End-to-End Guide: Headless checkout flow with the GraphQL Storefront API

The BigCommerce GraphQL Storefront API lets server-side and browser-side clients manage product, cart, and checkout objects to build storefront features. The GraphQL Storefront API can solve the same use cases as our REST Management API's cart and checkout features, but makes it easier to build headless storefront applications. Developers using the GraphQL Storefront API can spend less time focusing on API interactions and more time building the shopper experience.

This end-to-end guide describes how to work with shopper interactions on headless storefronts. These steps let you build shopping experiences where the purchase funnel is mainly powered by the GraphQL Storefront API, from catalog browsing through checkout. The examples walk you through critical capabilities that fit many headless use cases.

> **Note**
>
> You can use the GraphQL Storefront API playground to run the example queries in this guide. To access your store's GraphQL Storefront API playground, [sign in to your store](https://login.bigcommerce.com/login), and navigate to **Settings > API > Storefront API Playground**.

## Prerequisites

To complete the guide, you need the following:

* [BigCommerce sandbox store](https://start.bigcommerce.com/developer-sandbox/)
* Familiarity with creating a channel and a site

## Accessing the GraphQL Storefront API

You can make requests to the GraphQL Storefront API in a server-to-server context. This guide describes creating and using a customer access token to authenticate and use the GraphQL Storefront API.

### Create a customer access token

A customer access token is unique to an individual user's account. To generate a customer access token, enter your GraphQL variables (user email and password) and run the [login mutation](/developer/docs/storefront/guides/graphql-storefront-api/customer-context#login-mutation).

#### Request

**`GraphQL variables`**

```json title="GraphQL variables" 
{
  "email": "user@email.com", 
  "pass": "password"
}
```

**`Create a customer access token`**

```graphql title="Create a customer access token"
# Create a customer access token
POST https:{{storeDomain}}/graphql
Authorization: Bearer {{STOREFRONT_TOKEN}}
Accept: application/json
Content-Type: application/json

mutation Login($email: String!, $pass: String!) {
  login(email: $email, password: $pass) {
   result
   customer {
     entityId
     email
   }
   customerAccessToken {
     value
     expiresAt
 }
}
}
```

#### Response

**`Example login mutation: Create a customer access token`**

```json title="Example login mutation: Create a customer access token" showLineNumbers={false}
{
    "data": {
        "login": {
            "result": "success",
            "customer": {
                "entityId": 21,
                "email": "user@email.com"
            },
            "customerAccessToken": {
                "value": "53ea9099d5484cdedddbf8f59a73bc284afefd7943c4dbe578db52435e0c0de7_1721406629",
                "expiresAt": "2024-07-19T16:30:29Z"
            }
        }
    }
}
```

In a tool like [Postman](https://postman.com/) or [Altair](https://altairgraphql.dev/), add the customer access token to the **Headers** tab as follows. For more information, see Using a [Customer Access Token](/developer/docs/storefront/guides/graphql-storefront-api/customer-context#using-a-customer-access-token).

**`Authorization header with customer access token`**

```json title="Authorization header with customer access token" showLineNumbers={false}
{
  "X-Bc-Customer-Access-Token": "{{customer access token}}",
  "Authorization": "Bearer {{STOREFRONT_TOKEN}}"
}
```

## Querying product data

The GraphQL Storefront API lets you retrieve product data from a store. The following example demonstrates how to query a simple product using the GraphQL Storefront API. Pricing and visibility response values can vary based on the customer. For more information and examples, see the [Guide to working with products](/developer/docs/storefront/guides/graphql-storefront-api/products-and-catalog/products).

> **Note**
>
> When possible, use the following best practices for queries to the GraphQL Storefront API.
>
> * Query fewer than 50 resources at a time.
> * Limit query complexity.
> * Limit pagination.
> * Employ security practices and limit scope.
> * Cache data to avoid repeat fetching of data that hasn't changed.

#### Request

**`Get a product`**

```http title="Get a product"
GET https://store.example.com/graphql
Authorization: Bearer {{STOREFRONT_TOKEN}}
Accept: application/json
X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

# This query retrieves one product.
query SingleProduct ($entityId: Int) {
  site {
    product(entityId: $entityId) {
      id
      entityId
      name
      sku
      description
      prices {
        price {
          value
          currencyCode
        }
      }
    }
  }
}
```

#### Response

**`Get a product`**

```http title="Get a product"
  {
"data": {
    "site": {
        "product": {
            "id": "UHJvZHVjdDoxNTk=",
            "entityId": 159,
            "name": "computer",
            "sku": "CMP-1-223",
            "description": "<p><span>High speed Computer</span></p>",
            "prices": {
                "price": {
                    "value": 739.03,
                    "currencyCode": "USD"
                }
            }
        }
    }
}
}   
```

## Creating a cart

BigCommerce's GraphQL Storefront API provides the same cart and checkout objects as the REST Storefront API. Pricing and visibility response values can vary based on the customer. The following example shows how to create a new cart by adding a simple product.

> **Note**
>
> Make note of one of the cart's `entityId` displayed in the response. You will need to use it in later steps.

#### Request

**`Create a cart (simple)`**

```graphql title="Create a cart (simple)"
POST https://store.example.com/graphql
Accept: application/json
Authorization: Bearer {{STOREFRONT_TOKEN}}
X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

# Creates a new cart, adding a simple product.

mutation createCartSimple($createCartInput: CreateCartInput!) {
  cart {
    createCart(input: $createCartInput) {
      cart {
        entityId
        lineItems {
          physicalItems {
            name
            quantity
          }
          digitalItems {
            name
            quantity
          }
          giftCertificates {
            name
          }
          customItems {
            name
            quantity
          }
        }
      }
    }
  }
}
```

#### Input variables

**`Create a cart (simple)`**

```json title="Create a cart (simple)" 
  {
    "createCartInput": {
      "lineItems": [
        {
          "quantity": 1,
          "productEntityId": 111
        }
      ]
    }
  }
```

#### Response

**`Create a cart (simple)`**

```json title="Create a cart (simple)"
  {
    "data": {
      "cart": {
        "createCart": {
          "cart": {
            "entityId": "bb916deb-ddd6-4586-b65b-b8385e0e7a9d",
            "lineItems": {
              "physicalItems": [
                {
                  "name": "[Sample] Smith Journal 13",
                  "quantity": 1
                }
              ],
              "digitalItems": [],
              "giftCertificates": [],
              "customItems": []
            }
          }
        }
      }
    }
  }
```

## Add cart line items

To add a new line item to the existing cart, add the cart ID to the input variables or the mutation will fail.

#### Request

**`Add cart line items`**

```http title="Add cart line items"
  POST https://store.example.com/graphql
  Authorization: Bearer {{STOREFRONT_TOKEN}}
  X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

  mutation addCartLineItems($addCartLineItemsInput: AddCartLineItemsInput!) {
    cart {
      addCartLineItems(input: $addCartLineItemsInput) {
        cart {
          entityId
        }
      }
    }
  }
```

#### Input variables

**`Add cart line items`**

```json title="Add cart line items" 
  {
    "addCartLineItemsInput": {
      "cartEntityId": "bb916deb-ddd6-4586-b65b-b8385e0e7a9d",
      "data": {
        "lineItems": [
          {
            "quantity": 1,
            "productEntityId": 107
          }
        ]
      }
    }
  }
```

#### Response

**`Add cart line items`**

```json title="Add cart line items"
  {
    "data": {
      "cart": {
        "addCartLineItems": {
          "cart": {
            "entityId": "bb916deb-ddd6-4586-b65b-b8385e0e7a9d"
          }
        }
      }
    }
  }
```

## Get a checkout

The following query example shows how to display the contents of a checkout.

> **Note**
>
> You can access cart and checkout details in the same request as other information. The cart ID is the same as a checkout ID.

#### Request

**`Get checkout`**

```graphql title="Get checkout"
GET https://store.example.com/graphql
Authorization: Bearer {{STOREFRONT_TOKEN}}
X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

query getCheckout($entityId: Int) {
  site {
    checkout(entityId: $entityId) {
      entityId
      billingAddress {
        ...CheckoutBillingAddressFields
      }
      shippingConsignments {
        ...CheckoutShippingConsignmentFields
      }
      order {
        entityId
      }
      shippingCostTotal {
        ...MoneyFields
      }
      giftWrappingCostTotal {
        ...MoneyFields
      }
      handlingCostTotal {
        ...MoneyFields
      }
      taxTotal {
        ...MoneyFields
      }
      taxes {
        ...CheckoutTaxFields
      }
      subtotal {
        ...MoneyFields
      }
      grandTotal {
        ...MoneyFields
      }
      createdAt {
        utc
      }
      updatedAt {
        utc
      }
      customerMessage
      outstandingBalance {
        ...MoneyFields
      }
      coupons {
        ...CheckoutCouponFields
      }
      promotions {
        ...CheckoutPromotionFields
      }
    }
  }
}

fragment CheckoutConsignmentAddressFields on CheckoutConsignmentAddress {
  ...CheckoutAddressFields
}

fragment CheckoutBillingAddressFields on CheckoutBillingAddress {
  entityId
  ...CheckoutAddressFields
}

fragment CheckoutAddressFields on CheckoutAddress {
  firstName
  lastName
  email
  company
  address1
  address2
  city
  stateOrProvince
  stateOrProvinceCode
  countryCode
  postalCode
  phone
  customFields {
    entityId
    ... on CheckoutAddressCheckboxesCustomField {
      valueEntityIds
    }
    ... on CheckoutAddressDateCustomField {
      date {
        utc
      }
    }
    ... on CheckoutAddressMultipleChoiceCustomField {
      valueEntityId
    }
    ... on CheckoutAddressNumberCustomField {
      number
    }
    ... on CheckoutAddressPasswordCustomField {
      password
    }
    ... on CheckoutAddressTextFieldCustomField {
      text
    }
  }
}

fragment CheckoutShippingConsignmentFields on CheckoutShippingConsignment {
  entityId
  address {
    ...CheckoutConsignmentAddressFields
  }
  availableShippingOptions {
    ...CheckoutAvailableShippingOptionFields
  }
  selectedShippingOption {
    ...CheckoutSelectedShippingOptionFields
  }
  coupons {
    ...CheckoutCouponFields
  }
  shippingCost {
    ...MoneyFields
  }
  handlingCost {
    ...MoneyFields
  }
  lineItemIds
}

fragment CheckoutAvailableShippingOptionFields on CheckoutAvailableShippingOption {
  entityId
  description
  type
  imageUrl
  cost {
    ...MoneyFields
  }
  transitTime
  isRecommended
}

fragment CheckoutSelectedShippingOptionFields on CheckoutSelectedShippingOption {
  entityId
  description
  type
  imageUrl
  cost {
    ...MoneyFields
  }
  transitTime
}

fragment MoneyFields on Money {
  value
  currencyCode
}

fragment CheckoutCouponFields on CheckoutCoupon {
  entityId
  code
  couponType
  discountedAmount {
    ...MoneyFields
  }
}

fragment CheckoutTaxFields on CheckoutTax {
  name
  amount {
    ...MoneyFields
  }
}

fragment CheckoutPromotionFields on CheckoutPromotion {
  banners {
    entityId
    type
    locations
    text
  }
}
```

#### Response

**`Get checkout`**

```json title="Get checkout"   
{
  "data": {
    "site": {
      "checkout": {
        "entityId": "bb916deb-ddd6-4586-b65b-b8385e0e7a9d",
        "billingAddress": null,
        "shippingConsignments": [],
        "order": null,
        "shippingCostTotal": {
          "value": 0,
          "currencyCode": "USD"
        },
        "giftWrappingCostTotal": {
          "value": 0,
          "currencyCode": "USD"
        },
        "handlingCostTotal": {
          "value": 0,
          "currencyCode": "USD"
        },
        "taxTotal": {
          "value": 0,
          "currencyCode": "USD"
        },
        "taxes": [
          {
            "name": "Tax",
            "amount": {
              "value": 0,
              "currencyCode": "USD"
            }
          }
        ],
        "subtotal": {
          "value": 59.95,
          "currencyCode": "USD"
        },
        "grandTotal": {
          "value": 59.95,
          "currencyCode": "USD"
        },
        "createdAt": {
          "utc": "2023-06-01T17:45:23Z"
        },
        "updatedAt": {
          "utc": "2023-06-01T19:07:15Z"
        },
        "customerMessage": "",
        "outstandingBalance": {
          "value": 59.95,
          "currencyCode": "USD"
        },
        "coupons": [],
        "promotions": []
      }
    }
  }
}
```

## Add a checkout billing address

This mutation adds a billing address to an existing checkout.

#### Request

**`Add a checkout billing address`**

```graphql title="Add a checkout billing address"
  POST https://store.example.com/graphql
  Authorization: Bearer {{STOREFRONT_TOKEN}}
  X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

  mutation addCheckoutBillingAddress($addCheckoutBillingAddressInput: AddCheckoutBillingAddressInput!) {
    checkout {
      addCheckoutBillingAddress(input: $addCheckoutBillingAddressInput) {
        checkout {
          entityId
        }
      }
    }
  }   
```

#### Input variables

**`Add a checkout billing address`**

```json title="Add a checkout billing address" 
  {
    "addCheckoutBillingAddressInput": {
      "checkoutEntityId": "812ece1a-da23-46eb-ab6b-c2ee210aae54",
      "data": {
        "address": {
          "firstName": "Joe",
          "lastName": "Blogs",
          "email": "joe@example.com",
          "company": "BlogIndustries",
          "address1": "123 Yar st",
          "address2": "",
          "city": "RWC",
          "stateOrProvince": "CA",
          "stateOrProvinceCode": "CA",
          "countryCode": "US",
          "postalCode": "94061",
          "phone": "6501231212",
          "shouldSaveAddress": false
        }
      }
    }
  }
```

#### Response

**`Add a checkout billing address`**

```json title="Add a checkout billing address"
  {
    "data": {
      "checkout": {
        "addCheckoutBillingAddress": {
          "checkout": {
            "entityId": "812ece1a-da23-46eb-ab6b-c2ee210aae54"
          }
        }
      }
    }
  }
```

## Add a checkout shipping consignment

This mutation adds a shipping consignment to an existing checkout.

> **Note**
>
> Make a note of a shipping consignment's `entityId` and the desired shipping option's `entityId` returned from your request. You will need to use these in later steps.

#### Request

**`Add a checkout shipping consignment`**

```graphql title="Add a checkout shipping consignment"
POST https://store.example.com/graphql
Authorization: Bearer {{STOREFRONT_TOKEN}}
X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

mutation addCheckoutShippingConsignments($addCheckoutShippingConsignmentsInput: AddCheckoutShippingConsignmentsInput!) {
  checkout {
    addCheckoutShippingConsignments(input: $addCheckoutShippingConsignmentsInput) {
      checkout {
        entityId
        shippingConsignments {
          entityId
          availableShippingOptions {
            entityId
          }
          selectedShippingOption {
            entityId
          }
        }
      }
    }
  }
}
```

#### Input variables

**`Add a checkout shipping consignment`**

```json title="Add a checkout shipping consignment" 
{
  "addCheckoutShippingConsignmentsInput": {
    "checkoutEntityId": "812ece1a-da23-46eb-ab6b-c2ee210aae54",
    "data": {
      "consignments": [
        {
          "address": {
            "firstName": "Joe",
            "lastName": "Blogs",
            "email": "joe@example.com",
            "company": "BlogIndustries",
            "address1": "123 Yar st",
            "city": "RWC",
            "stateOrProvince": "CA",
            "stateOrProvinceCode": "CA",
            "countryCode": "US",
            "postalCode": "94061",
            "phone": "6501231212",
            "shouldSaveAddress": false
          },
          "lineItems": [
            {
              "lineItemEntityId": "0a281902-d548-4d2e-a930-dc2aae9bfc39",
              "quantity": 1
            }
          ]
        }
      ]
    }
  }
}
```

#### Response

**`Add a checkout shipping consignment`**

```json title="Add a checkout shipping consignment"
  {
    "data": {
      "checkout": {
        "addCheckoutShippingConsignments": {
          "checkout": {
            "entityId": "812ece1a-da23-46eb-ab6b-c2ee210aae54",
            "shippingConsignments": [
              {
                "entityId": "6478f628f1d8f",
                "availableShippingOptions": [
                  {
                    "entityId": "9ba45e71fe66e1cd757f022dcae331b0"
                  },
                  {
                    "entityId": "d8fb74f7cd682de8ae35a7fdd1e26f56"
                  }
                ],
                "selectedShippingOption": null
              }
            ]
          }
        }
      }
    }
  }
```

## Select checkout shipping option

This mutation adds a selected shipping to an existing checkout.

#### Request

**`Select checkout shipping option`**

```graphql title="Select checkout shipping option"
POST https://store.example.com/graphql
Authorization: Bearer {{STOREFRONT_TOKEN}}
X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

mutation selectCheckoutShippingOption($selectCheckoutShippingOptionInput: SelectCheckoutShippingOptionInput!) {
    checkout {
      selectCheckoutShippingOption(input: $selectCheckoutShippingOptionInput) {
        checkout {
          entityId
        }
      }
    }
  }
```

#### Input variables

**`Select checkout shipping option`**

```json title="Select checkout shipping option" 
  {
    "selectCheckoutShippingOptionInput": {
      "checkoutEntityId": "acd6f2ca-85c1-4b5f-8dab-d7d80521ecc5",
      "consignmentEntityId": "6478ff925d33a",
      "data": {
        "shippingOptionEntityId": "9ba45e71fe66e1cd757f022dcae331b0"
      }
    }
  }
```

#### Response

**`Select checkout shipping option`**

```json title="Select checkout shipping option"
  {
    "data": {
      "checkout": {
        "selectCheckoutShippingOption": {
          "checkout": {
            "entityId": "acd6f2ca-85c1-4b5f-8dab-d7d80521ecc5"
          }  
        }
      }
    }
  }
```

## Complete checkout

Completing a checkout creates an incomplete order until you process the payment. For PCI compliance-related reasons, the GraphQL Storefront API does not handle payments. You must use the [Payments API](/developer/api-reference/rest/admin/payments) to process payments. The payments workflow includes the following three steps:

1. [Fetch available payment methods](/developer/api-reference/rest/admin/payments/methods/get-payment-methods)
2. Create a payment access token by either requesting one with the following mutation or using the [REST Payments API](/developer/api-reference/rest/admin/payments/tokens/create-payment-access-token)
3. [Capture payment](/developer/api-reference/rest/admin/payments#process-payments)

#### Request

**`Complete checkout`**

```graphql title="Complete checkout"
  POST https://store.example.com/graphql
  Authorization: Bearer {{STOREFRONT_TOKEN}}
  X-Bc-Customer-Access-Token: {{CUSTOMER_ACCESS_TOKEN}}

  mutation completeCheckout($completeCheckoutInput: CompleteCheckoutInput!) {
      checkout {
        completeCheckout(input:$completeCheckoutInput) {
          orderEntityId
          paymentAccessToken
        }
      }
    }
```

#### Input variables

**`Complete checkout`**

```json title="Complete checkout"
  {
    "completeCheckoutInput": {
      "checkoutEntityId": "812ece1a-da23-46eb-ab6b-c2ee210aae54"
    }
  }
```

#### Response

**`Complete checkout`**

```json title="Complete checkout"
  {
    "data": {
      "checkout": {
        "completeCheckout": {
          "orderEntityId": 106,
          "paymentAccessToken": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2ODU3MjQwMzQsIm5iZiI6MTY4NTcyMDQzNCwiaXNzIjoicGF5bWVudHMuYmlnY29tbWVyY2UuY29tIiwic3ViIjoidmpid3FiYWJwMSIsImp0aSI6IjAzODU3ODk2LTdkY2YtNDIzNi04OTQ5LWU0MjcyYWU3ZGZjMSIsImlhdCI6MTY4NTcyMDQzNCwiZGF0YSI6eyJzdG9yZV9pZCI6IjEwMDI4ODA3NDYiLCJvcmRlcl9pZCI6IjEwNiIsImFtb3VudGd85rUwMCwiY3VycmVuY3kiOiJVU0QifX0.iiJ96cYKtk2-oLRXvZHs1lWUl9v8JkEkCdHShbyfEK4"
        }
      }
    }
  }
```

## Resources

### GraphQL Storefront API

* [Storefront tokens](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#tokens)
* [Customer access tokens](/developer/docs/storefront/guides/graphql-storefront-api/customer-context#customer-access-tokens)
* [Querying within a BigCommerce storefront](/developer/docs/storefront/guides/graphql-storefront-api#querying-within-a-bigcommerce-storefront)
* [Create a cart using a simple product](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#create-a-cart-using-a-simple-product)
* [Add cart line items](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#add-cart-line-items)
* [Add checkout billing address](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#add-checkout-billing-address)
* [Add a checkout shipping consignment](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#add-a-checkout-shipping-consignment)
* [Select checkout shipping option](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#select-checkout-shipping-option)
* [Complete checkout](/developer/docs/admin/checkout-and-cart/custom-checkouts/graphql-storefront#complete-checkout)

### REST Management API

* [Guide: End-to-end headless flow](/developer/docs/storefront/headless/end-to-end-guides/rest-management)
* [Carts](/developer/api-reference/rest/admin/management/carts)
* [Checkouts](/developer/api-reference/rest/admin/management/checkouts)