Customer Account API with Headless

Environment

  • App Type: Confidential (Headless)

  • Store: Development store with password protection enabled

  • API: Customer Account API (GraphQL)

  • Authentication: OAuth 2.0 with PKCE

Issue Description

I’ve successfully implemented the OAuth flow for the Customer Account API and am receiving valid access tokens. However, when I attempt to call the Customer Account API GraphQL endpoint, I receive a 302 redirect to /password instead of the expected API response.

OAuth Flow (Working Successfully :white_check_mark:)

  1. Authorization request to: https://shopify.com/authentication/{shop_id}/oauth/authorize

  2. Token exchange to: https://shopify.com/authentication/{shop_id}/oauth/token

  3. Successfully receiving:

    • access_token (544 characters, starting with shcat_)

    • refresh_token

    • id_token

    • Scopes: openid email customer-account-api:full

Token Exchange Request (Confidential Client)

POST https://shopify.com/authentication/{shop_id}/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {base64(client_id:client_secret)}

grant_type=authorization_code
client_id={client_id}
redirect_uri={redirect_uri}
code={authorization_code}
code_verifier={pkce_verifier}

GraphQL API Request (Failing :cross_mark:)

Endpoint: https://{shop}.myshopify.com/customer/api/graphql

Postman Request:

Method: POST
URL: https://{shop}.myshopify.com/customer/api/graphql

Headers:
  Authorization: {access_token}
  Content-Type: application/json

Body (raw JSON):
{
  "query": "query { customer { id firstName lastName } }"
}

Response:

HTTP/2 302 Found
Location: https://{shop}.myshopify.com/password

What I’ve Verified

  1. :white_check_mark: Access token format is correct (starts with shcat_, 544 characters)

  2. :white_check_mark: Token exchange uses Basic Auth header as required for Confidential clients

  3. :white_check_mark: Discovery endpoint works: /.well-known/customer-account-api returns the GraphQL URL

  4. :white_check_mark: Scopes match the supported scopes from /.well-known/openid-configuration

  5. :white_check_mark: Authorization header contains only the access token (no “Bearer” prefix, per Shopify docs)

  6. :white_check_mark: Tested in both Postman and backend server implementation (Go) - same result

Questions

  1. Does password protection on a development store block Customer Account API access even with valid access tokens?

  2. Is there a configuration setting to allow API access on password-protected dev stores?

  3. Should I remove password protection for API testing, or is there something I’m missing in my implementation?

Additional Context

  • The OAuth flow completes successfully without any errors

  • The access token is valid (not expired)

  • This is a backend server implementation using the Confidential client type

  • Same behavior occurs in both automated requests and manual Postman testing

Any guidance would be greatly appreciated!

brother i’m in the same boat as you. i confirmed the other day with shopify support that this doesn’t work on a password protected dev store.

i’m testing this on a store with a paid plan but now the graphql endpoint is returning 404…

if there’s anyone else out there struggling with this particular problem don’t use the graphql endpoint that the discovery endpoint gives you. try using this instead:

https://shopify.com/{shop_id}/account/customer/api/{api_version}/graphql

this was a ballache to search for but thankfully came across this blogpost here:

Thank you very much! This seems to work. I have been in contact with Shopify support and I will make sure to escalate this issue to their technical teams. Their docs are not correct and their own discovery endpoints are returning incorrect data. A lot of wasted dev hours on bad documentation from their end.