Wholesale-only access with new Customer Accounts (non-B2B) — recommended approach?

I’m looking for guidance on the recommended pattern for implementing a wholesale-only storefront using Shopify’s new Customer Accounts, without relying on Shopify Plus B2B features. We are on Shopify Plus but we currently do not use the B2B features.

Context:

  • Single Shopify store

  • Two clients:

    • Headless site built with Hydrogen

    • React Native mobile app

  • Both currently use the Storefront API to log the customer in.

  • This is a private wholesale store, not open to the public

Legacy behavior (what we used to do):

  • Customers applied via a form

  • We reviewed and approved them manually

  • We created the customer in Shopify

  • Only approved customers could log in (no public signup)

Problem with new Customer Accounts:

  • Shopify now controls authentication (OAuth / hosted login)

  • There is no way to fully disable self-service signup

  • We can’t prevent account creation before authentication

Questions:

  1. What is the recommended pattern for wholesale-only access with new Customer Accounts?

  2. Are there better alternatives to using tags for authorization (e.g. metafields)?

  3. Is there any supported way to restrict or suppress account creation, or is post-login enforcement the only option?

  4. For headless setups (Hydrogen + mobile apps), is it considered best practice to:

    • enforce authorization in Hydrogen loaders (server-side), and

    • optionally proxy through a backend for mobile?

Goal:
Maintain a strict approval-first wholesale model where only vetted customers can access the storefront, while staying aligned with Shopify’s supported patterns going forward.

Appreciate any guidance or confirmation of best practices here.

Here’s what I’ve seen similar merchants do:

For B2B-only stores

  • [Storefront] Pre-login Account button hidden via custom code (Hydrogen or Liquid).
  • [Storefront] A form application that is either handled by a Flow or manual. It creates the customer if approved.
  • [Account] Once approved, customers can log in via a hidden link that you share through email. This would be the regular login link.
  • Cons:
    • Regular customers could just go to the hidden link and go through the login flow as usual because Shopify allows it, but this would rarely happen in a B2B-only scenario.

For B2B and B2C stores.

  • [Storefront] Pre-login button enabled
  • [Account] Anyone can create an account - B2B customers still need to fill a form to be tagged as B2B (Either native B2B, assigned to a company, or through customer tags or customer metafields)
  • [Account] Within the new customer accounts, custom UI Extensions that render conditionally would enrich the experience for both B2B and B2C customers.
  • [Storefront] You can always access the logged in customer and create custom pages to create complex experiences if needed within the storefront, Hydrogen or Liquid. And lock these pages based on customer attributes.

So, in short, if you want new customer accounts, there isn’t a way today to bullet proof the account creation, but you can filter out those accounts that don’t meet the criteria to be considered “approved” via customer attributes.


You can create Customer Account extensions following this guide: Customer account UI extensions.
Or install an app like Hubble: Customer Accounts - Use dynamic content to increase retention, loyalty, and sales. | Shopify App Store.

1 Like

Hey @j_riv, @muchisx is on the right track above. With new Customer Accounts, there’s no way to prevent account creation at the authentication step. Signup and signin are intentionally unified, so post-login enforcement is the supported pattern.

I had a look into the available options and since you’re already headless on Hydrogen and on Plus, you have two solid options depending on how much infrastructure you want to stand up.

The lighter approach is post-login enforcement using customer metafields. After a customer authenticates through the Customer Account API OAuth flow, query their metafields in your Remix loaders. A boolean metafield like custom.wholesale_approved gives you a clean gate, and if the customer isn’t approved you redirect them to a “pending approval” page before any wholesale content loads. This is fully server-side so there’s no client-side workaround.

One thing to watch for is that the metafield definition’s customerAccount access needs to be set to READ via the Admin API, otherwise the metafield won’t be visible when queried through the Customer Account API. Tags are also readable from that API, but metafields are the better choice because they’re typed, structured, and less likely to be accidentally modified by other apps or automations.

For your React Native app, the same logic applies. Proxy your Storefront API calls through a backend that checks the customer’s approval metafield before returning storefront data.

The stronger approach, and the one closest to your legacy behavior, is connecting your own identity provider through the Plus third-party IdP feature. This replaces Shopify’s default sign-in entirely with your own OIDC-compliant provider (Auth0, Okta, etc.). You control who exists in the IdP, so if a user isn’t there they can’t sign in and no customer record is created in Shopify. A first-time successful authentication will still create a customer record automatically, so the IdP is the gate rather than an absolute block on record creation. The tradeoff is standing up and maintaining the IdP, and only the email and sub claim sync to Shopify automatically.

The Customer Account API with Hydrogen tutorial covers the OAuth setup and server-side querying for either approach. Let me know which direction fits better or if you run into anything during implementation.

1 Like

Thank you for the quick reply.

Thanks for the detailed response, lots to think about here.

One thing I’ve run into while exploring the Customer Account API is that it doesn’t seem to expose the same order data as the Storefront API. Specifically, I rely on product and variant data from line items, as well as product-level and variant-level metafields when rendering my orders page. I haven’t been able to find equivalents for those in the Customer Account API’s order queries.

In the meantime, I noticed that context.customerAccount.getAccessToken() in Hydrogen returns a token that appears to work with my existing Storefront API requests, including the customer and order queries I was already using. My current implementation is actually functioning as expected with this token.

That said, the Shopify docs seem to suggest that using a Customer Account API-issued token to access customer data via the Storefront API isn’t a supported pattern. So I’m not sure if this is a gap in the docs, intentional interoperability, or something that will be blocked down the line.

Is this expected behavior? And if the Storefront API customer queries are eventually deprecated, is there a roadmap for the Customer Account API to support richer line item data (product/variant fields and metafields) on orders?

Thanks for the thoughtful questions! Your current approach is working as designed, so you should keep using it.

As of API version 2025-01, Customer Account API access tokens are accepted directly by the Storefront API. The storefrontCustomerAccessTokenCreate deprecation changelog covers the migration path, which says to obtain a token via the CA API OAuth flow and then “use this access token directly with the Storefront API.” The publicly documented mechanism is the @inContext buyer identity directive for cart operations, but the broader token compatibility you’re seeing with the customer query is also intentional and part of the same migration. The docs haven’t caught up to reflect every SFAPI surface that accepts the new token yet, but what you’re doing with context.customerAccount.getAccessToken() in Hydrogen is consistent with how the platform works going forward.

On the deprecation concern, the legacy customer accounts announcement says “The Storefront API customer mutations will be deprecated, with more details coming soon.” That targets the legacy mutations (customerAccessTokenCreate, customerCreate, etc.), not the customer query itself. The customer query was updated to accept Customer Account API tokens as part of the migration to the new auth system, so it’s on the new path rather than the legacy one.

On the order data gap, the Customer Account API’s LineItem type has no variant or product connection and doesn’t support metafields on line items. You get product ID, variant ID, title, SKU, and pricing, but you can’t traverse to product or variant metafields from there. The Storefront API’s OrderLineItem does give you the variant connection to the full ProductVariant object (with metafields and a product connection that also has metafields), so the chain lineItem -> variant -> metafield and lineItem -> variant -> product -> metafield works through the SFAPI but not the CA API. No public roadmap for expanding the CA API schema here. Your approach of authenticating via CA API OAuth and querying order data through the Storefront API is the right way to bridge that.

Hope this helps!

1 Like

Hey @Donal-Shopify, this is really helpful and I appreciate you taking the time to clarify all of this.

One last question, are the Storefront API customer address mutations (customerAddressCreate, customerAddressUpdate, customerAddressDelete) also slated for deprecation along with the other legacy customer mutations?

Yeah, they are. The Storefront API customerAddressCreate, customerAddressUpdate, and customerAddressDelete mutations all depend on the legacy customerAccessToken flow (password-based auth). Since legacy customer accounts are now deprecated as of February 2026, the full set of SFAPI customer-scoped mutations that rely on that auth model are on the path to sunset.

The mutations still work today and aren’t flagged as deprecated in the schema, so there’s no urgency, but you should plan for the migration. Keep an eye on the Dev changelog for further updates in terms of timeline!

@Donal-Shopify Thank you.

1 Like