Storefront API
Keys, CORS, caching, errors and limits for the public Storefront API.
The Storefront API is what your own storefront, app or agent uses to read your catalog and sell: products with live stock, collections and categories, search, carts with discount codes and gift cards, checkout, buyer accounts with their orders, keys and downloads, and support tickets. Every operation runs the same code as your ShopFast store, so prices, stock, taxes, discounts and fraud checks always match.
curl https://api.shopfa.st/v1/shops/your-store/products?limit=12 \
-H "ShopFast-Storefront-Key: sfpk_live_…"
The reference lists every operation. The JavaScript SDK wraps them with types.
Base URL
https://api.shopfa.st/v1/shops/{shop}, where {shop} is your store’s handle (your-store) or its st_ id. The store
is part of the URL so a shared cache can never mix two stores up.
Keys
Create keys in Settings → Headless & MCP → Storefront keys.
Publishable sfpk_… |
Private sfsk_… |
|
|---|---|---|
| Where | Browsers, mobile apps, anywhere public | Your server only (Next.js server components, a backend) |
| Seen | Any time in the dashboard: it is public by design | Once, when you create it |
| Origins | Optionally limited to your sites | Refused from browsers |
| Buyer address | The caller’s | Your server can pass ShopFast-Buyer-IP |
Send the key in ShopFast-Storefront-Key (or Authorization: Bearer sfpk_…). A key works only with its own store.
Revoking a key stops it within a minute everywhere.
Why private keys pass the buyer’s address: limits and fraud checks are per buyer. Without ShopFast-Buyer-IP, every
buyer of a server-rendered site would look like your server.
A key’s allowed origins also register your sites, for either kind of key: checkout sends buyers back only to them (a
cart’s returnUrl and cancelUrl), and the embedded checkout opens only on them. See
Headless checkout.
Buyers
Sign a buyer in with an emailed code (POST /customer/code, then POST /customer/session) and send their token in
ShopFast-Customer-Token on later calls. Read Buyer accounts.
CORS
Browsers may call the API from any origin with a publishable key, or only from the origins you list on the key. Answers
that are the same for everyone carry Access-Control-Allow-Origin: *; personal answers (carts, accounts, orders) name
your origin. No cookies are involved: credentials are always headers.
Caching
Catalog reads are made to be cached:
Cache-Control: public, max-age=0, s-maxage=60, stale-while-revalidate=600ETag: send it back inIf-None-Matchand get304 Not Modifiedwith no body.Cache-Tag: the same tags your store’s pages use (s:<store>,p:<product>,c:<store>:<collection>,pg:<store>:<page>). When you change something, ShopFast drops exactly those.
Catalog answers are served from ShopFast’s edge, close to your buyers, and refresh within seconds of a change. They are the same for every caller, like your store’s own pages, so the edge does not check the key again for an answer it already holds.
Live stock (GET /products/{handle}/availability) is never cached. Carts, buyer accounts, orders and tickets are
private, no-store, and so is everything while your store is closed, in maintenance or behind a store password.
To keep your own cache fresh, subscribe to the storefront.updated webhook.
Errors
Every error is RFC 9457 problem JSON:
{ "type": "https://shopfa.st/problems/origin-not-allowed", "title": "Origin not allowed", "status": 403, "detail": "This key only works from https://shop.example.com.", "fields": [] }
| Status | When |
|---|---|
| 401 | No key, an unknown or revoked key, or a key from another store |
| 403 | A private key from a browser, or an origin the key does not allow |
| 404 | No such product, collection, category or page (a renamed product answers 301 to its new handle) |
| 422 | The input failed validation; fields says where |
| 429 | Too many requests; wait Retry-After seconds |
Retries
Send Idempotency-Key with a write (a cart, a code, a checkout, a ticket) and a retry after a timeout runs it once:
the same request with the same key gets the first answer again, with Idempotent-Replayed: true. Keys are kept 24
hours per storefront key and signed-in buyer. See Idempotency for the rules.
curl -X POST https://api.shopfa.st/v1/shops/your-store/carts \
-H "ShopFast-Storefront-Key: sfpk_live_…" -H "Content-Type: application/json" \
-H "Idempotency-Key: 9b2f0c4e-cart" \
-d '{"lines":[{"productId":"prd_…","quantity":1}]}'
Limits
600 reads and 120 writes a minute per key and buyer address, on top of the store’s own limits on sign-in codes, discount codes and checkouts.
Stability
Operations under /v1 only ever gain fields and operations. A change that would break you gets a new version. The
SDK’s schema snapshot is checked on every change to ShopFast, so a breaking change cannot slip in.