From 497040f46c492cf452aea647ecf8330399665e28 Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Wed, 28 Jan 2026 12:17:07 +0100 Subject: [PATCH 01/10] PAPI-3173 - Introduce private token authentication and deprecate simple/storefront tokens for S2S requests --- .../authentication/graphql-storefront.mdx | 66 ++++++++++++- docs/storefront/graphql/index.mdx | 8 +- docs/storefront/headless/channels.mdx | 2 +- docs/storefront/headless/customers.mdx | 2 +- reference/storefront_tokens.v3.yml | 95 ++++++++++++++++++- 5 files changed, 160 insertions(+), 13 deletions(-) diff --git a/docs/start/authentication/graphql-storefront.mdx b/docs/start/authentication/graphql-storefront.mdx index ab8a460f5..a5609f4e1 100644 --- a/docs/start/authentication/graphql-storefront.mdx +++ b/docs/start/authentication/graphql-storefront.mdx @@ -1,6 +1,6 @@ # Authenticating requests to the GraphQL Storefront API -Authenticate GraphQL Storefront API requests using bearer tokens passed with the `Authorization` header. You can authenticate using two different kinds of tokens: [storefront tokens](#storefront-tokens) or [customer impersonation tokens](#customer-impersonation-tokens). +Authenticate GraphQL Storefront API requests using bearer tokens passed with the `Authorization` header. You can authenticate using three different kinds of tokens: [storefront tokens](#storefront-tokens), [private tokens](#private-tokens), or [customer impersonation tokens](#customer-impersonation-tokens). ```http filename="Example request configuration" showLineNumbers copy POST https://your_store.example.com/graphql @@ -15,7 +15,11 @@ Content-Type: application/json ## Storefront tokens -Storefront tokens are most appropriate to use directly from the web browser, but you can use them in server-to-server communications. If you're creating a token for an application that will make server-to-server or proxied requests to the GraphQL Storefront API, or you work with customer data, use a [customer impersonation token](#customer-impersonation-tokens). If you only wish to query information from an anonymous shopper's perspective, use a storefront token. +Storefront tokens are designed for use directly from the web browser. They support CORS via `allowed_cors_origins` and are intended for browser-based applications. For server-to-server integrations, use [private tokens](#private-tokens) instead. If you need to work with customer data, use a [customer impersonation token](#customer-impersonation-tokens). If you only wish to query information from an anonymous shopper's perspective in a browser context, use a storefront token. + + +**Deprecation notice:** A deprecation date will be introduced soon. After this date, new storefront tokens created will not be usable statelessly in server-to-server contexts. Existing storefront tokens created before the deprecation date will continue to work in server-to-server contexts. We will contact merchants about migrating to private tokens. If you're planning a server-to-server integration, you should use [private tokens](#private-tokens) now. + ### Storefront token security @@ -23,7 +27,7 @@ Generally speaking, vanilla storefront tokens are not considered sensitive, and It is possible to create a long-lived token that does not expire. For greater security, we recommend creating shorter-lived tokens and rotating them periodically. -For security reasons, GraphQL Storefront API tokens are scoped to particular [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) origins, so you must supply the origin or origins on which you intend to use the token. If you have more than two origins, you will need multiple tokens. If you do not supply any CORS origins, the API will reject requests originating from web browsers, although you can still use it in other contexts. GraphQL server-to-server requests do not require `allowed_cors_origins`. +For security reasons, GraphQL Storefront API tokens are scoped to particular [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) origins, so you must supply the origin or origins on which you intend to use the token. If you have more than two origins, you will need multiple tokens. ### Create a storefront token @@ -68,7 +72,7 @@ content-type: application/json #### Customer access tokens -A customer access token is unique to an individual user's account because it represents an authenticated storefront session for GraphQL requests. You can obtain and use a customer access token only for server-to-server requests. Therefore, you must use the customer access token with a regular storefront token. A customer access token becomes invalid on all devices when you log out of a single device. +A customer access token is unique to an individual user's account because it represents an authenticated storefront session for GraphQL requests. You can obtain and use a customer access token only for server-to-server requests. Therefore, you must use the customer access token with a storefront token or private token. A customer access token becomes invalid on all devices when you log out of a single device. Do not use this token for browser-side or client-side requests. @@ -86,7 +90,7 @@ There are two options to obtain a customer access token. Enter your user email and password to use the login mutation. When using the login mutation in a server-to-server context, the mutation will return a customer access token in response to login actions as part of the GraphQL body instead of a cookie header. From there, you can store the customer access token in the presentation layer's session management system and send it with future GraphQL requests. If the login mutation request is from a browser, we will not return the customer access token in the body, and will instead set a cookie. -* Use the [Create a Token](/docs/rest-authentication/tokens#create-a-token) endpoint to generate the storefront bearer token needed to run the login mutation call. +* Use the [Create a Token](/docs/rest-authentication/tokens#create-a-token) endpoint to generate the storefront token or private token needed to run the login mutation call. * If you request a customer access token in wrong communication context, you will receive the following error: ***Customer access token was requested in the body, but it's only returned for server-to-server requests. For browser requests it's set as an httpOnly cookie instead.*** @@ -280,6 +284,57 @@ query CustomerAttributes { On Stencil storefronts, you can access a token at render time and pass the token to client-side code using the `{{settings.storefront_api.token}}` Handlebars property. This auto-generated token has an expiry period of 24-48 hours and will rotate before expiration. +## Private tokens + +Private tokens are designed for server-to-server integrations. They are always stateless (no session required) and provide better performance for server-to-server use cases. + +### Private token characteristics + +- **Server-to-server only:** The API rejects private token-authenticated requests that originate from web browsers +- **Always stateless:** No session or cookie validation required +- **Required for server-to-server:** Private tokens are required for all server-to-server integrations. Storefront tokens cannot be used statelessly in server-to-server contexts. + + +Private tokens are the recommended choice for new server-to-server integrations that don't require customer impersonation. They provide better performance and are designed specifically for stateless server-to-server use cases. + + +### Create a private token + +Use the [Create a private token](/docs/rest-authentication/tokens#create-a-private-token) REST endpoint to create private tokens. Add the [storefront API tokens creation scope](/docs/start/authentication/api-accounts#token-creation-scopes) to the [store-level or app-level API account](/docs/start/authentication/api-accounts) you use to generate tokens. + + + + +```http filename="Example request: Create a private token" showLineNumbers copy +POST https://api.bigcommerce.com/stores/{{STORE_HASH}}/v3/storefront/api-token-private +x-auth-token: {{access_token}} +accept: application/json +content-type: application/json + +{ + "channel_ids": [1, 2, 3], // array of integers (must be a valid channel IDs on the store) + "expires_at": 1602288000 // when the token will expire, as an integer unix timestamp (in seconds) +} +``` + + + +```json filename="Example response: Create a private token" showLineNumbers copy +{ + "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9...", + "meta": { + // ... + } +} +``` + + + +### Private token security + +Private tokens are sensitive and should **never** be exposed publicly. Treat them with the same care as other application secrets, such as API account access tokens. Store them securely on your server and never include them in client-side code or expose them in browser contexts. + +If your token is compromised, you can use the [Revoke a token](/docs/rest-authentication/tokens#revoke-a-token) endpoint. Only use this in emergencies; do not revoke tokens unnecessarily. Instead, use a shorter expiration and allow them to expire naturally. ## Customer impersonation tokens @@ -466,6 +521,7 @@ If you're signed out, the system reverts to a "guest" version of the cart, allow ### Endpoints * [Create a storefront token](/docs/rest-authentication/tokens#create-a-token) +* [Create a private token](/docs/rest-authentication/tokens#create-a-private-token) * [Create a customer impersonation token](/docs/rest-authentication/tokens/customer-impersonation-token) * [Revoke a token](/docs/rest-authentication/tokens#revoke-a-token) * [Customer Login API](/docs/rest-authentication/customer-login) diff --git a/docs/storefront/graphql/index.mdx b/docs/storefront/graphql/index.mdx index 844fd93ab..8899aafb2 100644 --- a/docs/storefront/graphql/index.mdx +++ b/docs/storefront/graphql/index.mdx @@ -691,12 +691,16 @@ Use a normal GraphQL Storefront API token. You can use an anonymous `fetch` or ` ### I want to run requests from a server, and I don't need customer impersonation abilities -Use normal GraphQL Storefront API tokens. According to the [Principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), you should not create a token that has permissions you do not need. +For server-to-server integrations, you must use [private tokens](/docs/start/authentication/graphql-storefront#private-tokens). Private tokens are designed specifically for stateless server-to-server use cases and provide better performance. According to the [Principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), you should not create a token that has permissions you do not need. + + +**Important:** A deprecation date will be introduced soon. After this date, new storefront tokens created will not be usable statelessly in server-to-server contexts. Existing storefront tokens created before the deprecation date will continue to work. If you're planning a server-to-server integration, you should use [private tokens](/docs/start/authentication/graphql-storefront#private-tokens) now. + ### I want to run requests from a server, and I need to support customer login -The recommended option is to use a regular storefront token with a customer access token. You can exchange customer credentials for a customer access token using the login mutation and send the token on future requests using the `X-Bc-Customer-Access-Token` header. The other possible but least preferred option is to use a customer impersonation token and store it securely on your server like other secrets. When you need to run requests in the context of a particular customer (for example, if they've logged in to your application), send their BigCommerce Customer ID along with the request as the `X-Bc-Customer-Id` header. This option provides less security but is available to use. +The recommended option is to use a [private token](/docs/start/authentication/graphql-storefront#private-tokens) with a customer access token. You can exchange customer credentials for a customer access token using the login mutation and send the token on future requests using the `X-Bc-Customer-Access-Token` header. The other possible but least preferred option is to use a customer impersonation token and store it securely on your server like other secrets. When you need to run requests in the context of a particular customer (for example, if they've logged in to your application), send their BigCommerce Customer ID along with the request as the `X-Bc-Customer-Id` header. This option provides less security but is available to use. ### I want a list of GraphQL error messages diff --git a/docs/storefront/headless/channels.mdx b/docs/storefront/headless/channels.mdx index 4e413be43..2c0f2815d 100644 --- a/docs/storefront/headless/channels.mdx +++ b/docs/storefront/headless/channels.mdx @@ -41,7 +41,7 @@ Optionally, you can add a 3P SSL certificate for the checkout domain by sending ### Create tokens for the GraphQL Storefront API -After setting up the channel, you're almost ready to authenticate cross-origin requests to the GraphQL Storefront API. You can [Create customer impersonation tokens](/docs/rest-authentication/tokens/customer-impersonation-token#create-a-token) for most headless or server-to-server interactions, or [Storefront tokens](/docs/rest-authentication/tokens#create-a-token) for static frontend site interactions. Use your new channel ID and, where required, supply your channel site as an allowed_cors_origin; otherwise, your requests will be rejected. +After setting up the channel, you're almost ready to authenticate cross-origin requests to the GraphQL Storefront API. For server-to-server interactions, use [private tokens](/docs/rest-authentication/tokens#create-a-private-token). For customer impersonation in server-to-server contexts, use [customer impersonation tokens](/docs/rest-authentication/tokens/customer-impersonation-token#create-a-token). For browser-based applications, use [Storefront tokens](/docs/rest-authentication/tokens#create-a-token). Use your new channel ID and, where required, supply your channel site as an allowed_cors_origin for storefront tokens; otherwise, your requests will be rejected. After you have a token, you're ready to get started using the [GraphQL Storefront API](/docs/storefront/graphql). diff --git a/docs/storefront/headless/customers.mdx b/docs/storefront/headless/customers.mdx index edc2093f9..9b30fe8f1 100644 --- a/docs/storefront/headless/customers.mdx +++ b/docs/storefront/headless/customers.mdx @@ -19,7 +19,7 @@ When you sign in a customer using the login mutation, subsequent queries to the ### Headless and server-side sign-in -To make queries from the perspective of a particular customer using headless or server-side code, use [customer access tokens](/docs/start/authentication/graphql-storefront#customer-access-tokens) and [storefront tokens](/docs/start/authentication/graphql-storefront#storefront-tokens). Then, use the customer access token in the `X-Bc-Customer-Access-Token` header. +To make queries from the perspective of a particular customer using headless or server-side code, use [customer access tokens](/docs/start/authentication/graphql-storefront#customer-access-tokens) with [private tokens](/docs/start/authentication/graphql-storefront#private-tokens). Then, use the customer access token in the `X-Bc-Customer-Access-Token` header. We recommend using the login mutation and customer access token because this combination is more secure. In addition, there is a seamless redirection and synchronization between headless storefronts and hosted checkouts, which allow for transferring session details, such as customer and cart data, across various contexts. diff --git a/reference/storefront_tokens.v3.yml b/reference/storefront_tokens.v3.yml index deb3f8007..5a179dd15 100644 --- a/reference/storefront_tokens.v3.yml +++ b/reference/storefront_tokens.v3.yml @@ -8,7 +8,17 @@ info: ## Storefront tokens - This type of token is the most appropriate to use from a web browser when you're serving a static site that only supports anonymous shopping. If you're creating a token for backend implementation, you wish to support signing in customers, or you're developing a frontend app that proxies requests, such as a NextJS app, use a [customer impersonation token](#customer-impersonation-tokens). + Storefront tokens are designed for use from a web browser when you're serving a static site that only supports anonymous shopping. Storefront tokens support CORS via `allowed_cors_origins` and are intended for browser-based applications. For server-to-server integrations, you must use [private tokens](#private-tokens) instead. + + > #### Deprecation notice + > A deprecation date will be introduced soon. After this date, new storefront tokens created will not be usable statelessly in server-to-server contexts. Existing storefront tokens created before the deprecation date will continue to work. If you're planning a server-to-server integration, you should use private tokens now. + + ## Private tokens + + Private tokens are designed for server-to-server integrations. They are always stateless (no session required) and provide better performance for server-to-server use cases. Private tokens are created using a separate endpoint (`/storefront/api-token-private`). The API will reject private token-authenticated requests that originate from web browsers. + + > #### Warning + > Private tokens are sensitive and should never be exposed publicly. Treat them with the same care as other application secrets. ## Customer impersonation tokens @@ -40,6 +50,7 @@ security: - X-Auth-Token: [] tags: - name: API Token + - name: Private API Token - name: Customer Impersonation Token paths: '/storefront/api-token': @@ -50,7 +61,9 @@ paths: - API Token summary: Create a Token description: |- - Creates a Storefront API token. + Creates a Storefront API token. This endpoint creates storefront tokens that support CORS via `allowed_cors_origins` and are intended for browser-based applications. + + For server-to-server integrations, you must use the [private token endpoint](#operation/createPrivateToken) instead. **Required Scopes** * `Manage` `Storefront API Tokens` @@ -67,13 +80,13 @@ paths: - $ref: '#/components/schemas/TokenPostSimple' - $ref: '#/components/schemas/TokenPostImpersonation' examples: - Single Channel: + Storefront Token (Single Channel): value: allowed_cors_origins: - 'https://www.yourstorefront.com' channel_id: 1 expires_at: 1885635176 - Multi Channel: + Storefront Token (Multi Channel): value: allowed_cors_origins: - 'https://www.yourstorefront.com' @@ -122,6 +135,80 @@ paths: '422': description: Invalid JWT Token provided or missing JWT token header content: {} + '/storefront/api-token-private': + parameters: + - $ref: '#/components/parameters/Accept' + post: + tags: + - Private API Token + summary: Create a Private API Token + description: |- + Creates a private token for server-to-server integrations. Private tokens are always stateless (no session required) and provide better performance for server-to-server use cases. The API will reject private token-authenticated requests that originate from web browsers. + + **Required Scopes** + * `Manage` `Storefront API Tokens` + + > NOTE: While neither `channel_id` nor `channel_ids` is labelled as required, one must be included in the request body. Including neither will throw an error, and including both will result in unexpected behaviors. + operationId: createPrivateToken + parameters: + - $ref: '#/components/parameters/ContentType' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TokenPostImpersonation' + examples: + Private Token (Single Channel): + value: + channel_id: 1 + expires_at: 1885635176 + Private Token (Multi Channel): + value: + channel_ids: [1,12] + expires_at: 1885635176 + required: false + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/Token_Full' + '401': + description: Unauthorized - the v3 Auth client ID or token in the request are not a valid combination for this store. + content: {} + '403': + description: Missing scope - the v3 Auth token is valid but does not have proper permissions to access this endpoint. + content: {} + '422': + description: Invalid JSON request body - missing or invalid data. + content: {} + delete: + tags: + - Private Token + summary: Revoke a Private Token + description: Revoke access for a private token. Only revoke compromised tokens under emergency situations. Let uncompromised short-lived tokens expire naturally, as you do not need to revoke these. + operationId: revokePrivateToken + parameters: + - name: Sf-Api-Token + in: header + description: An existing private JWT token that you want to revoke. + required: true + schema: + type: string + responses: + '200': + description: A private token revocation has been scheduled. + content: {} + '401': + description: Unauthorized - the v3 Auth client ID or token in the request are not a valid combination for this store. + content: {} + '403': + description: Missing scope - the v3 Auth token is valid but does not have proper permissions to access this endpoint. + content: {} + '422': + description: Invalid JWT Token provided or missing JWT token header + content: {} '/storefront/api-token-customer-impersonation': parameters: - $ref: '#/components/parameters/Accept' From f279ad3760ab7659134c822c3b1f9002348b92a1 Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Wed, 28 Jan 2026 15:03:21 +0100 Subject: [PATCH 02/10] PAPI-3173 - Introduce private token authentication and deprecate simple/storefront tokens for S2S requests --- reference/storefront_tokens.v3.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/storefront_tokens.v3.yml b/reference/storefront_tokens.v3.yml index 5a179dd15..caf0927c4 100644 --- a/reference/storefront_tokens.v3.yml +++ b/reference/storefront_tokens.v3.yml @@ -185,8 +185,8 @@ paths: content: {} delete: tags: - - Private Token - summary: Revoke a Private Token + - Private API Token + summary: Revoke a Private API Token description: Revoke access for a private token. Only revoke compromised tokens under emergency situations. Let uncompromised short-lived tokens expire naturally, as you do not need to revoke these. operationId: revokePrivateToken parameters: From 093a24a7de46c05d2b06f5bcba7a7b09359f5c8a Mon Sep 17 00:00:00 2001 From: Krzysztof Maziarka Date: Thu, 29 Jan 2026 14:01:06 +0100 Subject: [PATCH 03/10] Update docs/start/authentication/graphql-storefront.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/start/authentication/graphql-storefront.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/authentication/graphql-storefront.mdx b/docs/start/authentication/graphql-storefront.mdx index a5609f4e1..534b539f9 100644 --- a/docs/start/authentication/graphql-storefront.mdx +++ b/docs/start/authentication/graphql-storefront.mdx @@ -312,7 +312,7 @@ accept: application/json content-type: application/json { - "channel_ids": [1, 2, 3], // array of integers (must be a valid channel IDs on the store) + "channel_ids": [1, 2, 3], // array of integers (must be valid channel IDs on the store) "expires_at": 1602288000 // when the token will expire, as an integer unix timestamp (in seconds) } ``` From 6413e3c274eb9fc9dd0d48ff026ad4ce36242f63 Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Thu, 29 Jan 2026 14:02:23 +0100 Subject: [PATCH 04/10] PAPI-3173 - Update storefront_tokens.v3.yml to clarify token revocation descriptions and remove private token revocation endpoint --- reference/storefront_tokens.v3.yml | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/reference/storefront_tokens.v3.yml b/reference/storefront_tokens.v3.yml index caf0927c4..2156e19f9 100644 --- a/reference/storefront_tokens.v3.yml +++ b/reference/storefront_tokens.v3.yml @@ -113,7 +113,7 @@ paths: tags: - API Token summary: Revoke a Token - description: Revoke access for a Storefront API token. Only revoke compromised tokens under emergency situations. Let uncompromised short-lived tokens expire naturally, as you do not need to revoke these. + description: Revoke access for a storefront API token or a private API token. Only revoke compromised tokens under emergency situations. Let uncompromised short-lived tokens expire naturally, as you do not need to revoke these. operationId: revokeToken parameters: - name: Sf-Api-Token @@ -124,7 +124,7 @@ paths: type: string responses: '200': - description: A storefront API token revocation has been scheduled. + description: A storefront API token or private API token revocation has been scheduled. content: {} '401': description: Unauthorized - the v3 Auth client ID or token in the request are not a valid combination for this store. @@ -183,32 +183,6 @@ paths: '422': description: Invalid JSON request body - missing or invalid data. content: {} - delete: - tags: - - Private API Token - summary: Revoke a Private API Token - description: Revoke access for a private token. Only revoke compromised tokens under emergency situations. Let uncompromised short-lived tokens expire naturally, as you do not need to revoke these. - operationId: revokePrivateToken - parameters: - - name: Sf-Api-Token - in: header - description: An existing private JWT token that you want to revoke. - required: true - schema: - type: string - responses: - '200': - description: A private token revocation has been scheduled. - content: {} - '401': - description: Unauthorized - the v3 Auth client ID or token in the request are not a valid combination for this store. - content: {} - '403': - description: Missing scope - the v3 Auth token is valid but does not have proper permissions to access this endpoint. - content: {} - '422': - description: Invalid JWT Token provided or missing JWT token header - content: {} '/storefront/api-token-customer-impersonation': parameters: - $ref: '#/components/parameters/Accept' From fe657847336b840a1b5fe29892f3b4aa4e27123a Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Fri, 30 Jan 2026 12:53:19 +0100 Subject: [PATCH 05/10] PAPI-3173 - Update customers.mdx to correct code block syntax and improve clarity in JWT payload examples --- docs/storefront/headless/customers.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/storefront/headless/customers.mdx b/docs/storefront/headless/customers.mdx index 9b30fe8f1..20ad8f6fa 100644 --- a/docs/storefront/headless/customers.mdx +++ b/docs/storefront/headless/customers.mdx @@ -27,7 +27,7 @@ We recommend using the login mutation and customer access token because this com If using the customer access token, then you just need to use the `createCartRedirectUrls` mutation and use the redirectUrl provided there. It will be a session sync link that will copy data from the headless storefront to the BigCommerce-hosted page. This approach simplifies session synchronization and offers consistent login states. -```js "Generate redirectUrl example" showLineNumbers copy +```graphql "Generate redirectUrl example" showLineNumbers copy mutation createRedirectUrl($input: CreateCartRedirectUrlsInput!) { cart { createCartRedirectUrls(input: $input) { @@ -43,15 +43,15 @@ The other option is when a customer signs in to your headless storefront and you You can sign a customer in to an embedded checkout by using the session-sync URL from the [createCartRedirectUrls mutation](https://developer.bigcommerce.com/graphql-storefront/reference#definition-CartMutations). -```js filename="Example JWT payload" showLineNumbers copy +```json filename="Example JWT payload" showLineNumbers copy { - "iss": {{CLIENT_ID}}, + "iss": "{{CLIENT_ID}}", "iat": 1535393113, - "jti": {{UUID}}, + "jti": "{{UUID}}", "operation": "customer_login", - "store_hash": {{STORE_HASH}}, - "customer_id": {{CUSTOMER_ID}}, - "channel_id": {{CHANNEL_ID}}, + "store_hash": "{{STORE_HASH}}", + "customer_id": "{{CUSTOMER_ID}}", + "channel_id": "{{CHANNEL_ID}}", "redirect_to": "/cart.php?embedded=1&action=loadInCheckout&id=bc218c65-7a32-4ab7-8082-68730c074d02&token=aa958e2b7922035bf3339215d95d145ebd9193deb36ae847caa780aa2e003e4b", "request_ip": "111.222.333.444" } From 705e3856aa099bfd23a345ae25f79ec46c525377 Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Fri, 30 Jan 2026 13:07:56 +0100 Subject: [PATCH 06/10] PAPI-3173 - Update GraphQL storefront API token examples to reflect correct JSON structure by nesting the token under a "data" key --- docs/start/authentication/graphql-storefront.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/start/authentication/graphql-storefront.mdx b/docs/start/authentication/graphql-storefront.mdx index 534b539f9..122b78ef8 100644 --- a/docs/start/authentication/graphql-storefront.mdx +++ b/docs/start/authentication/graphql-storefront.mdx @@ -61,10 +61,10 @@ content-type: application/json ```json filename="Example response: Create a storefront API token" showLineNumbers copy { - "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9...", - "meta": { - // ... - } + "data": { + "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9..." + }, + "meta": {} } ``` @@ -321,10 +321,10 @@ content-type: application/json ```json filename="Example response: Create a private token" showLineNumbers copy { - "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9...", - "meta": { - // ... - } + "data": { + "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9..." + }, + "meta": {} } ``` From 5c6e2e336d1fccc58db98a3d582e744b037c5317 Mon Sep 17 00:00:00 2001 From: "krzysztof.maziarka" Date: Fri, 30 Jan 2026 13:10:50 +0100 Subject: [PATCH 07/10] PAPI-3173 - Update GraphQL storefront API examples to include placeholder comments in the "meta" field for improved clarity --- .../start/authentication/graphql-storefront.mdx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/start/authentication/graphql-storefront.mdx b/docs/start/authentication/graphql-storefront.mdx index 122b78ef8..f8684bd37 100644 --- a/docs/start/authentication/graphql-storefront.mdx +++ b/docs/start/authentication/graphql-storefront.mdx @@ -64,7 +64,9 @@ content-type: application/json "data": { "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9..." }, - "meta": {} + "meta": { + // ... + } } ``` @@ -324,7 +326,9 @@ content-type: application/json "data": { "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9..." }, - "meta": {} + "meta": { + // ... + } } ``` @@ -380,11 +384,12 @@ Content-Type: application/json ```json filename="Example response: Create a customer impersonation token" showLineNumbers copy { - "data": - { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + "data": { + "token": "...eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9..." }, - "meta": {} + "meta": { + // ... + } } ``` From 16898d70066bb60da6499f12f3419becc9b9dfd6 Mon Sep 17 00:00:00 2001 From: Krzysztof Maziarka Date: Fri, 30 Jan 2026 13:30:56 +0100 Subject: [PATCH 08/10] Update docs/start/authentication/graphql-storefront.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/start/authentication/graphql-storefront.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/authentication/graphql-storefront.mdx b/docs/start/authentication/graphql-storefront.mdx index f8684bd37..d4d451726 100644 --- a/docs/start/authentication/graphql-storefront.mdx +++ b/docs/start/authentication/graphql-storefront.mdx @@ -294,7 +294,7 @@ Private tokens are designed for server-to-server integrations. They are always s - **Server-to-server only:** The API rejects private token-authenticated requests that originate from web browsers - **Always stateless:** No session or cookie validation required -- **Required for server-to-server:** Private tokens are required for all server-to-server integrations. Storefront tokens cannot be used statelessly in server-to-server contexts. +- **Required for server-to-server:** Private tokens are required for server-to-server integrations without customer impersonation. Storefront tokens cannot be used statelessly in server-to-server contexts. Private tokens are the recommended choice for new server-to-server integrations that don't require customer impersonation. They provide better performance and are designed specifically for stateless server-to-server use cases. From 2a3b6f51c0fa39d601cfb0cc923d6dcc792bf1d5 Mon Sep 17 00:00:00 2001 From: Krzysztof Maziarka Date: Fri, 30 Jan 2026 13:31:12 +0100 Subject: [PATCH 09/10] Update docs/storefront/headless/customers.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/storefront/headless/customers.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/storefront/headless/customers.mdx b/docs/storefront/headless/customers.mdx index 20ad8f6fa..cb4ebacd6 100644 --- a/docs/storefront/headless/customers.mdx +++ b/docs/storefront/headless/customers.mdx @@ -50,8 +50,8 @@ You can sign a customer in to an embedded checkout by using the session-sync URL "jti": "{{UUID}}", "operation": "customer_login", "store_hash": "{{STORE_HASH}}", - "customer_id": "{{CUSTOMER_ID}}", - "channel_id": "{{CHANNEL_ID}}", + "customer_id": {{CUSTOMER_ID}}, + "channel_id": {{CHANNEL_ID}}, "redirect_to": "/cart.php?embedded=1&action=loadInCheckout&id=bc218c65-7a32-4ab7-8082-68730c074d02&token=aa958e2b7922035bf3339215d95d145ebd9193deb36ae847caa780aa2e003e4b", "request_ip": "111.222.333.444" } From c8290a1a6f1d3de16830d4fde18fc9882ef87c11 Mon Sep 17 00:00:00 2001 From: Krzysztof Maziarka Date: Fri, 30 Jan 2026 13:31:48 +0100 Subject: [PATCH 10/10] Update reference/storefront_tokens.v3.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- reference/storefront_tokens.v3.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/storefront_tokens.v3.yml b/reference/storefront_tokens.v3.yml index 2156e19f9..e97ab16df 100644 --- a/reference/storefront_tokens.v3.yml +++ b/reference/storefront_tokens.v3.yml @@ -11,7 +11,7 @@ info: Storefront tokens are designed for use from a web browser when you're serving a static site that only supports anonymous shopping. Storefront tokens support CORS via `allowed_cors_origins` and are intended for browser-based applications. For server-to-server integrations, you must use [private tokens](#private-tokens) instead. > #### Deprecation notice - > A deprecation date will be introduced soon. After this date, new storefront tokens created will not be usable statelessly in server-to-server contexts. Existing storefront tokens created before the deprecation date will continue to work. If you're planning a server-to-server integration, you should use private tokens now. + > A deprecation date will be introduced soon. After this date, new storefront tokens created will not be usable statelessly in server-to-server contexts. Existing storefront tokens created before the deprecation date will continue to work in server-to-server contexts. If you're planning a server-to-server integration, you should use private tokens now. ## Private tokens