Background
My company is migrating from legacy customer accounts to the current Customer Account API for our headless Next.js storefront. We already use @shopify/admin-api-client and @shopify/storefront-api-client — both have been great to work with. The sane configuration defaults and automatic type generation via @shopify/api-codegen-preset have made them really convenient.
When planning the customer account migration, I noticed there's no equivalent client for the Customer Account API. @shopify/api-codegen-preset already references @shopify/customer-api-client as the module name for ApiType.Customer, so the package name and type infrastructure are clearly already planned — it just hasn't been implemented yet.
What I built
Rather than roll our own one-off solution, I decided to build the missing client modeled after the existing ones so it could be upstreamed and others could benefit from it too.
The new @shopify/customer-api-client package provides:
OAuth helpers — covering the full flow for both client types:
getAuthorizationUrl() — generates the authorization URL; includes PKCE for public clients (browser/mobile), omits it for confidential clients (server-side with clientSecret)
exchangeCode() — exchanges the authorization code for a token set
refreshToken() — refreshes an expired access token using the stored refresh token
getLogoutUrl() — returns the end-session URL
GraphQL client — authenticated requests using per-user customer access tokens:
fetch() / request() — delegates to @shopify/graphql-client with Authorization: {token} injected per-request (no Bearer prefix, per the Customer Account API docs)
Endpoint discovery — the GraphQL API URL and OAuth endpoints are discovered lazily at construction time via:
GET /.well-known/openid-configuration → OAuth endpoints
GET /.well-known/customer-account-api → { graphql_api } (which may be a merchant's custom vanity domain)
The client follows the same factory function pattern as @shopify/storefront-api-client and reuses @shopify/graphql-client for HTTP, retries, and logging.
I should note that while the implementation has full unit test coverage, we're still in the middle of our own migration so it hasn't been battle-tested in production yet. Happy to flag that clearly in any PR description.
I have a working implementation ready at athletic-greens/shopify-app-js — add-customer-api-client if maintainers are interested. Happy to adjust the design based on any feedback before opening a PR.
Background
My company is migrating from legacy customer accounts to the current Customer Account API for our headless Next.js storefront. We already use
@shopify/admin-api-clientand@shopify/storefront-api-client— both have been great to work with. The sane configuration defaults and automatic type generation via@shopify/api-codegen-presethave made them really convenient.When planning the customer account migration, I noticed there's no equivalent client for the Customer Account API.
@shopify/api-codegen-presetalready references@shopify/customer-api-clientas the module name forApiType.Customer, so the package name and type infrastructure are clearly already planned — it just hasn't been implemented yet.What I built
Rather than roll our own one-off solution, I decided to build the missing client modeled after the existing ones so it could be upstreamed and others could benefit from it too.
The new
@shopify/customer-api-clientpackage provides:OAuth helpers — covering the full flow for both client types:
getAuthorizationUrl()— generates the authorization URL; includes PKCE for public clients (browser/mobile), omits it for confidential clients (server-side withclientSecret)exchangeCode()— exchanges the authorization code for a token setrefreshToken()— refreshes an expired access token using the stored refresh tokengetLogoutUrl()— returns the end-session URLGraphQL client — authenticated requests using per-user customer access tokens:
fetch()/request()— delegates to@shopify/graphql-clientwithAuthorization: {token}injected per-request (no Bearer prefix, per the Customer Account API docs)Endpoint discovery — the GraphQL API URL and OAuth endpoints are discovered lazily at construction time via:
GET /.well-known/openid-configuration→ OAuth endpointsGET /.well-known/customer-account-api→{ graphql_api }(which may be a merchant's custom vanity domain)The client follows the same factory function pattern as
@shopify/storefront-api-clientand reuses@shopify/graphql-clientfor HTTP, retries, and logging.I should note that while the implementation has full unit test coverage, we're still in the middle of our own migration so it hasn't been battle-tested in production yet. Happy to flag that clearly in any PR description.
I have a working implementation ready at athletic-greens/shopify-app-js — add-customer-api-client if maintainers are interested. Happy to adjust the design based on any feedback before opening a PR.