Retail & E-commerce// definition

The public storefront token: what a shopper-side key can read

In short

A public storefront token is a deliberately narrow read key: published products, published prices, availability, and writes limited to the cart it created. It cannot return cost price, unpublished products, another shopper's order or customer records. Its safety comes from scope rather than secrecy, because it ships inside the browser bundle by design.

Key takeaways

  • A storefront credential is public by design. It is in the bundle, in the browser network tab, and in anything that fetches your JavaScript.
  • Its safety is scope, not secrecy: published catalogue read, plus writes confined to the cart it created.
  • A leak buys an attacker a tidier scrape of data already on your pages — not orders, customers, cost or stock by location.
  • Published-but-unlinked is not private. A storefront key enumerates it in 1 query, so soft launches must be unpublished or channel-excluded.
  • Rotating a public key is a deploy, not a secret rotation, and every cached page carrying the old one has to be replaced.

A public storefront token is the credential a shopper-side application uses to read your catalogue and build a cart. It grants published products, published prices, availability and media, plus a narrow write surface: create a cart, change its lines, hand it to checkout. It does not grant cost price, unpublished products, customer records or anybody else's order.

The important property is that it is not a secret. It travels in a JavaScript bundle to every browser that loads the storefront, so it is visible in the network tab, in source maps, and to anything that fetches your pages. That is intended. CORS does not change it either: an origin restriction constrains browsers, not the 3 lines of script a scraper runs from a server.

Two credential classes, and the line between them

Nearly every hosted commerce platform issues at least 2 families of credential: a public one for the shopper surface and a privileged one for the back office. Confusing them is the single most damaging configuration error in a headless build, because the privileged key is the one that reads every order you have ever taken.

Data or actionPublic storefront credentialBack-office credential
Published products, prices, mediaYes — this is its entire jobYes
Unpublished, draft or channel-excluded productsNoYes
Cost price, margin, supplier fieldsNoYes
Inventory detail by locationAggregated or a boolean at bestYes, per location
Another shopper's cart or orderNo — only the cart whose id it holdsYes, any order
Customer records and contact detailsNoYes
Create a cart, add a line, start checkoutYes, scoped to that cartYes
Change a price, publish a product, adjust stockNoYes
Where it may liveIn the browser bundle, by designServer-side only, never in a bundle
What each credential class can return

The one write path the public credential does have is the cart, and that write path is also the reason a storefront cannot be entirely static. A cart is an identity token attached to a server-held document, which is the one object a storefront can never serve from cache.

What a leaked storefront key actually gets someone

Mostly, convenience. Everything the key returns is already on your public pages, so the realistic outcome of a leak is a tidier scrape than crawling HTML — competitor price monitoring at a lower cost to them, and a share of your request budget spent on somebody else's crawler. A nuisance and an operational cost, not a breach.

  • It does not read orders. Order history and customer identity sit behind a shopper session or a back-office credential, never behind the public key.
  • It does not read cost. Margin, supplier and landed-cost fields are back-office data and should not exist in the storefront schema at all.
  • It does not read contract or account-specific prices. Those need identity, and rendering them on a cached storefront is a separate problem — rendering contract pricing without leaking it.
  • It does spend your quota. Request budgets are per key, so a scraper on your public credential competes with real shoppers — see what runs out first in a storefront API budget.

Operating a key you cannot keep secret

Three consequences follow from the key being public, and all 3 are operational rather than cryptographic. Rotation is a deploy: the old key stays live in every cached bundle and every page an edge cache is still serving, so both keys have to work until the caches turn over — which means knowing the four caches between your product page and the shopper.

Second, abuse control belongs at the edge rather than in the credential: rate limiting by address, blocking crawlers, a CDN in front of catalogue reads. Third, the schema is the real permission boundary. Where the storefront API is GraphQL, introspection makes its shape discoverable in 1 request, so a field that must never be public has to be removed from the schema rather than left unqueried.

A storefront key is not a secret you failed to protect. It is a permission you chose, published in a bundle, and it should read exactly like one.

The surfaces that are not your storefront

The same credential class increasingly serves things that are not a browser: comparison surfaces, shopping assistants and agents fetching a catalogue on a shopper's behalf. The scope usually still fits; the traffic shape does not, because an agent may read 40 products to answer 1 question. Where an agent moves from reading to buying, the boundary shifts to a different object: what a checkout session is when an agent buys.

Whether you hold one of these credentials at all is an architecture decision, because a themed storefront on a hosted platform never exposes it the same way — that trade is headless or themed: what genuinely changes. The wider picture is storefront architecture and platform choice, within software for retail and ecommerce. Where agents read the same surface, that is AI agents and automation work, under AI agents in production.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Is it safe to put a storefront API token in client-side JavaScript?

Yes — that is what it is for, provided it is genuinely the public credential and not a back-office one. The check is not whether the key is hidden but what it returns: query it for an unpublished product, a cost field and an order, and confirm all 3 fail. If any succeeds, you have the wrong credential in the bundle and the fix is a new key, not obfuscation.

Should we rotate a public storefront token, and how often?

Rotate on personnel or vendor change rather than on a schedule, because rotation costs a deploy and a cache turnover rather than a secret update. Both keys need to work at once until every cached bundle and edge-cached page carrying the old one is replaced, so plan a migration window at least as long as your longest TTL.

Can a storefront token read stock levels?

It can usually read whether something is buyable, and rarely the exact count by location. Most platforms expose availability as a boolean or a coarse figure on the storefront surface precisely because per-location counts are competitively sensitive. If your build needs true per-location stock on the shopper side, that is a deliberate exposure to design, not a default to accept.

What stops someone using our storefront key to place fake orders?

The cart write path is scoped to a cart the caller created, and turning a cart into an order needs a payment step the key cannot complete alone. What it does allow is bulk cart creation, which costs quota and distorts abandoned-cart reporting, so rate limiting and bot filtering at the edge are still worth doing even though no order can be forged.

  • headless commerce
  • API credentials
  • storefront architecture
  • security
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation