Storefront API
The public API behind every Joomni storefront. Use it to build your own website or app on top of a Joomni store — no API key needed.
Overview
What it is
Every Joomni storefront reads its catalogue and places its orders through these endpoints. They return only what a shopper may see, so they need no key: you pick the store with one header. The Next.js Commerce starter is built entirely on them.
| Storefront API | REST API (v1) | |
|---|---|---|
| Who it is for | Your own website or app, used by shoppers | Your own systems: ERP, courier, spreadsheet |
| Authentication | None. The x-subdomain header picks the store | Secret jk_live_… key with scopes |
| What it can do | Read the published catalogue, quote shipping, check a code, place a guest order, track it | Read and change products, orders, stock and leads |
| Prices on orders | Always taken from your catalogue | Recorded as you send them |
| Base URL | https://api.joomni.com/storefront | https://api.joomni.com/api/v1 |
x-subdomain header picks the storejk_live_… key with scopeshttps://api.joomni.com/storefronthttps://api.joomni.com/api/v1Safe by design
Quick start
Your first call
Use your store's subdomain — mystore for mystore.joomni.com.
- 1
Pick the store
Sendx-subdomain: mystoreon every request. An unknown or inactive store answers404. - 2
Read the envelope
Most endpoints wrap their answer as{ data }. The shipping quote and discount check answer unwrapped. - 3
Call from a server
Fetch from your server (or server components) and cache catalogue reads; they change only when you edit the store.
Endpoints
Store and catalogue
Only active products and published collections are returned. Drafts and archived products answer 404.
Store
Name, currency, SEO, and which payment methods checkout offers.
- GET
/storefront/storestoreName,currency,locale,logo,seoTitle,seoDescription;paymentSettings.codandpaymentSettings.customQr(enabled, fee, instructions);customerAccounts.mode(OPTIONAL,REQUIREDorGUEST_ONLY).
Products and collections
Paged lists and single records, with variants.
- GET
/storefront/productspage,limit,search,collectionId. Answers{ data: Product[], meta }, newest first, each product with itsvariants. - GET
/storefront/products/:handleOne product by handle (or id), with
variantsand thecollectionsit belongs to. - GET
/storefront/collectionspage,limit. Published collections. - GET
/storefront/collections/:handle{ collection, products }. For a manual collection, page its products through/storefront/products?collectionId=instead; that list includes variants. Automatic (tag-rule) collections use theproductshere.
Menus
The header and footer menus you build under Website › Navigation.
- GET
/storefront/navigationEvery menu by handle; stores start with
main-menuandfooter. Each item haslabel,url(already resolved to the current product or collection handle) andchildren. - GET
/storefront/navigation/:handleOne menu.
Endpoints
Checkout
Quote, check, place. Nothing you compute here is trusted: the same calculations run again when the order is placed.
Shipping and discounts
For the order summary while the shopper fills in checkout.
- POST
/api/shipping/calculateNote the
/apiprefix. Body:storeId(from/storefront/store),items(productId,quantity,price) andaddress(province,city,country,zip). Answers{ total }, or{ unavailable: true }when no shipping zone covers the address. - POST
/storefront/discounts/validateBody:
codeandcart(subtotal,items,shipping). Answers{ valid, discount, amount }, or400with the reason (expired, minimum not met, used up).
Orders
Place a guest order, then follow it with its tracking token.
- POST
/storefront/ordersPlaces an order, takes the stock and emails the buyer and you. Answers the order with its
trackingToken.401 LOGIN_REQUIREDwhen the store only takes orders from signed-in customers. - GET
/storefront/orders/track/:tokenStatus, items, totals,
shipmentswith tracking numbers, andpayment: the Scan & Pay QR and amount due while the order is unpaid (otherwisenull). - POST
/storefront/orders/track/:token/paymentScan & Pay: the buyer reports
transactionId(and optionalpayerName). You confirm it in the dashboard. Limited to 5 requests a minute.
Payments
Taking payment
Storefront orders are paid by the methods your checkout completes today.
| paymentMethod | When it is accepted | What happens next |
|---|---|---|
COD | Cash on delivery is on, or no method is on at all | The order is placed unpaid. If COD confirmation is on, it waits for your call before dispatch. |
CUSTOM_QR | Scan & Pay is on | Show the QR from the tracking endpoint; the buyer pays and reports the transaction ID; you mark the order paid. |
CODCUSTOM_QRGood practice
Rules for a healthy integration
- Cache catalogue reads and refresh them with product webhooks or a timer.
- Never show a total as final before the order is placed; the response holds the real one.
- Treat the
trackingTokenas the buyer's key to their order: don't index or log it. - Handle 404 on a product: it may have been unpublished since your page was cached.
- Ignore fields you don’t know; new ones may be added at any time.
- Customer sign-in endpoints exist but aren’t part of this public contract yet.
Want a working example? The Next.js Commerce starter calls every endpoint on this page from src/lib/joomni/storefront.ts.