Skip to navigation

GraphQL Storefront API: Customers

BigCommerce’s GraphQL Storefront API Customers powers access to customer objects such as the ability to update a customer, get a customer address book, reset a password, and more. Developers can use GraphQL Storefront API to create an end-to-end shopper experience and manage some customer account use cases.

Customer mutations and queries can do the following:

  • Register a customer
  • Update a customer
  • Add a customer address
  • Update a customer address
  • Delete a customer address
  • Change a customer password
  • Request a password reset
  • Reset a password
  • Get a customer address book
  • Create a vault access token
  • Create a vault initialization
  • Get the stored instruments manifest
  • Get the payments service base URL
  • Get a customer’s stored payment instruments
  • Update a customer’s stored payment instrument
  • Delete a customer’s stored payment instrument

When you register, change, or reset a password, you can validate it using the password complexity requirements under the CustomersSettings node before submitting the desired password to the BigCommerce platform.

Tokens

To make requests, create a store-level or app-level API account with one or more of the following token creation OAuth scopes:

UI NamePermissionParameterDescription
Storefront API tokensmodifystore_storefront-apiCreate payment access tokens, process payments
Storefront API customer impersonation tokensmodifystore_storefront_api_customer_impersonationCreate GraphQL Storefront API bearer tokens that allow customer impersonation

No additional scopes are required to use the GraphQL Storefront API. For more information, see token creation OAuth scopes.

To authenticate calls to the GraphQL Storefront API, your application can generate a bearer token. This can be done by using either the Create a storefront token or the Create a customer impersonation token REST endpoint. On a Stencil storefront, you can also access a token directly from the page context. Learn more about Using auto-generated tokens in Stencil themes.

For more information, see Creating a token in the GraphQL Storefront API Overview and Dynamic tokens in the Authentication and Example Requests article.

reCAPTCHA

Captcha is not required when the reCAPTCHA is disabled in the control panel. Be sure to use a valid user verification response reCAPTCHA token if reCAPTCHA is enabled.

Customer impersonation tokens do not require the use of reCAPTCHA even when the reCAPTCHA setting is enabled. You can bypass the reCAPTCHA and it will still function. Note, if reCAPTCHA is provided it must be valid, otherwise it will be rejected.

Example queries and mutations

Register a customer

Register a customer using the form field configuration set up in the control panel for both the account signup and address fields.

Example mutation: Register a customer
mutation {
customer {
registerCustomer(
reCaptchaV2: { token: "" }
input: {
firstName: "John"
lastName: "Smith"
email: "jon@example.com"
password: "Password123!"
phone: "123-456-7890"
company: "BC"
address: {
firstName: "John"
lastName: "Smith"
address1: "123 Main Street"
address2: "Suite 200"
city: "Austin"
company: "Acme Corporation"
countryCode: "US"
stateOrProvince: "TX"
phone: "555-123-4567"
postalCode: "78701"
}
formFields: {
checkboxes: [{ fieldEntityId: 1, fieldValueEntityIds: [1, 2, 3] }]
multipleChoices: [{ fieldEntityId: 1, fieldValueEntityId: 2 }]
numbers: [{ fieldEntityId: 1, number: 1.0 }]
texts: [{ fieldEntityId: 1, text: "Customer notes" }]
passwords: [{ fieldEntityId: 1, password: "SecurePassword123!" }]
}
}
) {
customer {
firstName
lastName
}
errors {
__typename
... on ValidationError {
message
}
... on CustomerRegistrationError {
message
}
... on EmailAlreadyInUseError {
message
}
... on AccountCreationDisabledError {
message
}
}
}
}
}

Update a customer

Update customer information, except for password and address. Use either resetPassword, or changePassword to reset or update the user password.

Example mutation: Customer update
mutation {
customer {
updateCustomer(
reCaptchaV2: { token: "" }
input: {
firstName: "John"
lastName: "Smith"
email: "john@test.com"
phone: "123-456-7890"
company: "BC"
formFields: {
# optional
checkboxes: [{ fieldEntityId: 1, fieldValueEntityIds: [1, 2, 3] }]
multipleChoices: [{ fieldEntityId: 1, fieldValueEntityId: 2 }]
numbers: [{ fieldEntityId: 1, number: 1.0 }]
texts: [{ fieldEntityId: 1, text: "Customer notes" }]
passwords: [{ fieldEntityId: 1, password: "SecurePassword123!" }]
}
}
) {
customer {
firstName
lastName
}
errors {
__typename
... on ValidationError {
message
}
... on CustomerDoesNotExistError {
message
}
... on EmailAlreadyInUseError {
message
}
}
}
}
}

Add a customer address

The BigCommerce platform can support and store plenty of addresses per customer. Use the addCustomerAddress to include multiple addresses to the customer account. Similar to registerCustomer, add CustomerAddress using the form field configuration set up in the control panel for address fields.

Example mutation: Add a customer address
mutation {
customer {
addCustomerAddress(
reCaptchaV2: { token: "" }
input: {
firstName: "John"
lastName: "Smith"
address1: "1234 Fake Street"
address2: ""
city: "Austin"
company: "BC"
countryCode: "US"
stateOrProvince: "TX"
phone: "123-456-7890"
postalCode: "78610"
formFields: {
checkboxes: [{ fieldEntityId: 1, fieldValueEntityIds: [1, 2, 3] }]
multipleChoices: [{ fieldEntityId: 1, fieldValueEntityId: 2 }]
numbers: [{ fieldEntityId: 1, number: 1.0 }]
texts: [{ fieldEntityId: 1, text: "Customer notes" }]
passwords: [{ fieldEntityId: 1, password: "SecurePassword123!" }]
}
}
) {
errors {
__typename
... on ValidationError {
message
}
... on CustomerNotLoggedInError {
message
}
... on CustomerAddressCreationError {
message
}
}
}
}
}

Update a customer address

Use this updateCustomerAddress mutation when a customer needs to make changes to an address associated with their account.

Example mutation: Update a customer address
mutation {
customer {
updateCustomerAddress(
reCaptchaV2: { token: "" },
input: {
addressEntityId: 1,
data: {
firstName: "John",
lastName: "Smith",
address1: "123 Main Street",
address2: "Suite 200",
city: "Austin",
company: "Acme Corporation",
countryCode: "US",
stateOrProvince: "TX",
phone: "555-123-4567",
postalCode: "78701",
formFields: {
checkboxes: [
{
fieldEntityId: 1,
fieldValueEntityIds: [1,2,3]
}
],
multipleChoices: [
{
fieldEntityId: 1,
fieldValueEntityId: 2
}
],
numbers: [
{
fieldEntityId: 1,
number: 1.0
}
],
texts: [
{
fieldEntityId: 1,
text: "Customer notes"
}
],
passwords: [
{
fieldEntityId: 1,
password: "SecurePassword123!"
}
],
}
}
}
) {
errors {
__typename
... on ValidationError {
message
}
... on CustomerNotLoggedInError {
message
}
... on AddressDoesNotExistError {
message
}
... on CustomerAddressUpdateError {
message
}
}
}
}
}

Delete a customer address

Use this delete mutation when a customer needs to delete an address associated with their account.

Example mutation: Delete a customer address
mutation {
customer {
deleteCustomerAddress(
reCaptchaV2: { token: "" }
input: { addressEntityId: 1 }
) {
errors {
__typename
... on CustomerNotLoggedInError {
message
}
... on CustomerAddressDeletionError {
message
}
}
}
}
}

Change a customer password

Use the changePassword mutation in cases where the customer needs to update their password. The user must know their current password in order to complete the change.

Example mutation: Change a user password
mutation {
customer {
changePassword(
input: { currentPassword: "Password1!", newPassword: "Password2!" }
) {
errors {
... on ValidationError {
path
message
}
... on CustomerPasswordError {
message
}
... on CustomerDoesNotExistError {
message
}
... on CustomerNotLoggedInError {
message
}
}
}
}
}

Request a password reset

A customer can request a password reset using the requestResetPassword mutation example as seen below.

Example mutation: Request a password reset
mutation {
customer {
requestResetPassword(
reCaptchaV2: { token: "" }
input: { email: "john@test.com" }
) {
errors {
... on ValidationError {
message
}
}
}
}
}

Reset a password

When a customer needs a password reset, use the resetPassword example mutation to complete the reset.

Example mutation: Reset a password
mutation {
customer {
resetPassword(
input: {
customerEntityId: 1 # Provided in the link contained in the reset password email
token: "" # Provided in the link contained in the reset password email
newPassword: "NewPassword1234"
}
) {
errors {
... on ValidationError {
message
}
... on ChangePasswordError {
message
}
}
}
}
}

Get a customer address book

Use this query to view all the addresses a customer has added to their account.

Example query: Get a customer address book
query {
customer {
firstName
lastName
formFields {
entityId
name
}
addresses {
collectionInfo {
totalItems
}
edges {
node {
entityId
firstName
lastName
address1
city
stateOrProvince
postalCode
formFields {
entityId
name
}
}
}
}
}
}

Create a vault access token

Use the createVaultAccessToken mutation, nested under the storedPaymentInstruments field on the customer mutation type, to mint a short-lived token that authorizes saving a new payment instrument to the customer’s account. The mutation takes no input — the customer it applies to is derived from the customer access token on the request.

This mutation is in alpha and is gated per store. It is marked deprecated in the schema to signal that status, and its shape may change without notice. Do not use it in production.

This field requires a valid customer JWT, the same as storedPaymentInstruments. Use a customer impersonation token, or a token retrieved while a customer is logged in to the storefront.

The vault access token is issued by BigCommerce and is spent against BigCommerce’s own vault endpoints — it is not a payment provider credential, and it carries no provider-specific meaning. The same token works identically regardless of which provider backs the form, so a headless storefront that supports several providers mints and handles it the same way for all of them.

On a headless storefront, the typical sequence is:

  1. Mint the token server-side. Call createVaultAccessToken from your server once per shopper session, using the shopper’s customer access token. Minting server-side keeps the customer access token off the client.
  2. Pass it to the client. Hand the returned vaultAccessToken to the client-side account payments experience — the UI where the shopper manages the payment methods saved to their account — which renders the provider’s form and collects the instrument details.
  3. Spend it on save. That client sends the token as the Authorization header when it saves the instrument to BigCommerce.

The result’s expiresAt field is the token’s expiry as a DateTime. Treat the token as session-scoped: check expiresAt before reusing a token you minted earlier, and mint a fresh one rather than retrying with an expired token. Because the token authorizes writes to the customer’s saved instruments, do not log it, persist it, or expose it anywhere beyond the client that consumes it.

This mutation is gated and is not enabled for every store. When it is not enabled, it resolves successfully and returns the same result shape with vaultAccessToken and expiresAt set to null and an empty errors array — the response is indistinguishable in shape from a failure that reports no errors.

Because of this, do not treat an empty errors array as proof that a token was issued. Check that vaultAccessToken is non-null before using it, and handle the null case as “vaulting unavailable on this store” rather than as a transient error to retry.

To summarize the three outcomes:

OutcomevaultAccessTokenexpiresAterrors
Token issuedPopulatedPopulatedEmpty
Not enabled for this storenullnullEmpty
Request failednullnullPopulated
Example mutation: Create a vault access token
mutation {
customer {
storedPaymentInstruments {
createVaultAccessToken {
vaultAccessToken
expiresAt
errors {
__typename
message
}
}
}
}
}

Create a vault initialization

Use the createVaultInitialization mutation, nested under the storedPaymentInstruments field on the customer mutation type, to start a vaulting flow for a specific payment method. Where createVaultAccessToken is provider-agnostic, this mutation is provider-specific: it returns the initialization token and client configuration your storefront needs to drive that provider’s SDK.

This mutation is in alpha and is gated per store. It is marked deprecated in the schema to signal that status, and its shape may change without notice. Do not use it in production.

This field requires a valid customer JWT, the same as storedPaymentInstruments. Use a customer impersonation token, or a token retrieved while a customer is logged in to the storefront.

Pass the payment method you are vaulting against in the required input.paymentMethodId field, using the provider’s method identifier — for example, squarev2.credit_card.

The result contains:

  • token — the initialization token returned by the provider. It is populated only when the provider was called, so it is null for providers whose SDK does not require one.
  • clientConfiguration — a ClientConfiguration union carrying the client-safe values needed to initialize the provider’s SDK. Select the member matching the provider with an inline fragment: ... on SquareV2ClientConfiguration exposes applicationId, locationId, and environment (PRODUCTION, SANDBOX, or UNSPECIFIED); ... on StripeOcsClientConfiguration exposes publishableKey and connectedAccountId, the latter absent for merchants without a connected account.
  • errors — failures encountered while creating the initialization.

Everything returned here is client-safe by design, so it is the configuration you hand to the browser. The vault access token is not: keep minting that server-side as described above.

This mutation is gated and is not enabled for every store. When it is not enabled, it resolves successfully and returns null for both token and clientConfiguration with an empty errors array. As with createVaultAccessToken, do not treat an empty errors array as proof the flow is available — check clientConfiguration for a non-null value before initializing the provider SDK, and handle null as “vaulting unavailable on this store.”

Because token is legitimately null for some providers, clientConfiguration is the more reliable signal of the two.

Example mutation: Create a vault initialization
mutation {
customer {
storedPaymentInstruments {
createVaultInitialization(input: { paymentMethodId: "squarev2.credit_card" }) {
token
clientConfiguration {
__typename
... on SquareV2ClientConfiguration {
applicationId
locationId
environment
}
... on StripeOcsClientConfiguration {
publishableKey
connectedAccountId
}
}
errors {
__typename
message
}
}
}
}
}

Get the stored instruments manifest

Use the storedInstrumentsManifest field on the site query to get the JavaScript bundle your storefront loads to render the stored instruments UI — the interface where a shopper manages the payment methods saved to their account. The manifest resolves to the bundle for the environment the store runs in, so you do not hardcode asset URLs.

This field is in alpha and is gated per store. It is marked deprecated in the schema to signal that status, and its shape may change without notice. Do not use it in production.

Unlike the vaulting mutations above, this field hangs off site rather than customer, so it does not require a customer JWT. It describes store-level assets, not shopper data.

The manifest contains:

  • baseUrl — the base URL of the manifest CDN for the current environment.
  • version — the manifest version.
  • appVersion — the application version of the deployed manifest, as a git SHA.
  • scripts — the bundle files to load, in the order given. Each entry has a src URL and an integrity value, which is the Subresource Integrity hash for that file.

Set each script’s integrity attribute to the value returned alongside it, and preserve the array order when injecting the tags — the bundle expects to execute in sequence.

This field is gated and is not enabled for every store. When it is not enabled, storedInstrumentsManifest resolves to null. Check for null before attempting to load the UI, and treat it as “stored instruments unavailable on this store” rather than a transient error.

Example query: Get the stored instruments manifest
query {
site {
storedInstrumentsManifest {
baseUrl
version
appVersion
scripts {
src
integrity
}
}
}
}

Get the payments service base URL

Use the paymentBaseUrl field on site.settings.url to get the base URL of the payments service backing the storefront, for example https://payments.bigcommerce.com. The stored instruments UI sends its requests there, authorized with the vault access token, when it saves an instrument.

This field is in alpha. It is marked deprecated in the schema to signal that status, and its shape may change without notice. Do not use it in production.

Read the host from this field rather than hardcoding one, so the same storefront code resolves to the correct payments service for whichever environment the store runs in. Like storedInstrumentsManifest, it is a site field and does not require a customer JWT.

Example query: Get the payments service base URL
query {
site {
settings {
url {
paymentBaseUrl
}
}
}
}

Get a customer’s stored payment instruments

Use the storedPaymentInstruments field on the Customer type to list the payment instruments a customer has saved, such as cards, PayPal accounts, and bank accounts.

This field requires a valid customer JWT. Use a customer impersonation token, or a token retrieved while a customer is logged in to the storefront. For unauthenticated requests, the parent customer query resolves to null, so no instruments are returned.

The connection returns one StoredPaymentInstrument per edge. Each instrument’s details field is a StoredPaymentInstrumentDetails union — use inline fragments (... on StoredCard, ... on StoredPaypalAccount, ... on StoredBankAccount) to select the type-specific fields. The connection also exposes defaultStoredPaymentInstrumentToken, the token of the customer’s default instrument when one is set.

The connection follows the Relay cursor connection spec. Page through results with the first/after (forward) or last/before (backward) arguments, and read pageInfo to determine whether more pages are available and which cursors to request next. Each edge’s cursor is the value to pass to after (or before) to continue paging from that instrument.

To narrow the result set to specific payment methods, pass the filters argument with one or more paymentMethodIds (for example, ["braintree.credit_card", "braintree.paypal"]). An empty or omitted list returns all instruments.

The example below requests the first 10 instruments after a given cursor, filtered to cards and PayPal accounts, and selects the full set of fields available on each instrument type.

Example query: Get a customer's stored payment instruments
query {
customer {
storedPaymentInstruments(
first: 10
after: "eyJ0b2tlbiI6ImExYjJjM2Q0ZTUifQ=="
filters: { paymentMethodIds: ["braintree.credit_card", "braintree.paypal"] }
) {
defaultStoredPaymentInstrumentToken
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
token
paymentMethodId
details {
__typename
... on StoredCard {
brand
last4
issuerIdentificationNumber
expires {
month
year
}
billingAddress {
firstName
lastName
email
company
address1
address2
city
stateOrProvince
stateOrProvinceCode
postalCode
countryCode
phone
}
}
... on StoredPaypalAccount {
email
}
... on StoredBankAccount {
maskedAccountNumber
issuer
}
}
}
}
}
}
}

Update a customer’s stored payment instrument

Use the updateStoredPaymentInstrument mutation on the customer mutation type to update the billing address and/or promote a stored payment instrument to be the customer’s default. Instrument data itself, such as the card number, expiry, or brand, is immutable and cannot be changed through this mutation.

This field requires a valid customer JWT, the same as storedPaymentInstruments. Use a customer impersonation token, or a token retrieved while a customer is logged in to the storefront.

Both this mutation and deleteStoredPaymentInstrument act on an existing instrument’s token. Get an instrument’s token from the storedPaymentInstruments query before calling either mutation.

setAsDefault is promote-only: pass true to make this instrument the customer’s default. Omitting the field or passing false leaves the current default unchanged — there is no way to unset a default without promoting a different instrument in its place.

Billing address updates are supported only for card instruments whose payment method allows editing. Passing billingAddress for any other instrument returns an error.

On billingAddress, firstName, address1, city, and countryCode are required. lastName, email, company, address2, stateOrProvince, stateOrProvinceCode, postalCode, and phone are optional.

The result’s defaultStoredPaymentInstrumentToken is populated only when the request sets setAsDefault: true, in which case it echoes the token of the instrument just promoted. Billing-only updates, and requests where setAsDefault is omitted or false, return null for this field — even if the customer already has a different default instrument set.

Example mutation: Update a customer's stored payment instrument
mutation {
customer {
updateStoredPaymentInstrument(
input: {
token: "a1b2c3d4e5"
setAsDefault: true
billingAddress: {
firstName: "John"
lastName: "Smith"
address1: "123 Main Street"
city: "Austin"
countryCode: "US"
}
}
) {
storedPaymentInstrument {
token
paymentMethodId
details {
__typename
... on StoredCard {
brand
last4
billingAddress {
firstName
lastName
email
company
address1
address2
city
stateOrProvince
stateOrProvinceCode
postalCode
countryCode
phone
}
}
}
}
defaultStoredPaymentInstrumentToken
errors {
__typename
message
}
}
}
}

Delete a customer’s stored payment instrument

Use the deleteStoredPaymentInstrument mutation on the customer mutation type to delete a stored payment instrument. Deleting an instrument removes it from BigCommerce and unvaults the associated token at the payment provider.

This field requires a valid customer JWT, the same as storedPaymentInstruments. Use a customer impersonation token, or a token retrieved while a customer is logged in to the storefront.

Get the instrument’s token from the storedPaymentInstruments query before calling this mutation.

The mutation result contains only an errors list — there is no data payload on success. An empty errors array indicates the instrument was deleted.

Deleting the customer’s current default instrument automatically promotes another remaining instrument to be the new default.

Example mutation: Delete a customer's stored payment instrument
mutation {
customer {
deleteStoredPaymentInstrument(input: { token: "a1b2c3d4e5" }) {
errors {
__typename
message
}
}
}
}

Error handling

createVaultAccessToken, createVaultInitialization, updateStoredPaymentInstrument, and deleteStoredPaymentInstrument can fail in two different ways. Expected, request-specific failures — an unsupported payment method, a token that doesn’t belong to the customer, or a vault access token that could not be issued — are returned in the mutation’s own errors array, as shown in the examples above. Authentication failures and unmapped or transient upstream errors are returned as top-level GraphQL errors instead, with data.customer set to null. Check both places when handling responses.

A missing or expired customer JWT returns a top-level error:

Example: top-level GraphQL error (missing customer token)
{
"data": {
"customer": null
},
"errors": [
{
"message": "A customer access token is required for this operation, but it was not provided.",
"path": ["customer"],
"locations": [{ "line": 1, "column": 9 }],
"extensions": {
"code": "MISSING_CUSTOMER_ACCESS_TOKEN"
}
}
]
}

Transient or unmapped upstream failures also surface as a top-level error, but without an extensions.code:

Example: top-level GraphQL error (unmapped or transient failure)
{
"data": {
"customer": null
},
"errors": [
{
"message": "Internal server error"
}
]
}

Join our Developer community to share your feedback with us in the BigCommerceDevs Slack.

Resources

Documentation

API reference

Storefront tokens

REST management API: customers

Community