Headless commerce API

Use Bazaar as the backend for your own storefront (e.g. a Next.js site on Vercel): real catalog & live inventory, a server-side cart, embedded Stripe checkout, order status, and admin writes — all over REST + JSON. Prices and stock are always computed server-side; orders are only marked paid by Stripe's webhook.

Base URL is your Bazaar platform URL, e.g. https://app.buildbazaar.io. Create keys in Dashboard → Settings → API keys.

Authentication

Two key types, sent as a bearer token. Publishable keys (pk_…) are safe in browser code and power the storefront API (catalog, cart, checkout, order status). Secret keys (sk_…) must stay on your server and power the admin API. The full key is shown once at creation.

curl https://app.buildbazaar.io/api/storefront/products \
  -H "Authorization: Bearer pk_your_publishable_key"

CORS & origins

Storefront (publishable) endpoints are browser-callable. Add your site's origins to the key's allowlist in the dashboard; requests from other origins are blocked (an empty allowlist allows any origin, since publishable keys are public by design). Admin (secret) endpoints are server-to-server only and send no CORS headers — never call them from a browser.

Rate limits

Limits are per API key, per endpoint group, in a fixed 60-second window (e.g. catalog 120/min, checkout 10/min). Exceeding a limit returns 429 with a Retry-After header. Every response is { "ok": true, "data": … } or { "ok": false, "error": "code" }.

Storefront API

Publishable key. The cart is keyed by a returned cartId (no cookies).

MethodPathDescription
GET/api/storefront/productsList products (live inventory). ?limit&cursor&collection
GET/api/storefront/products/{slug}Product detail + variants
GET/api/storefront/collectionsList collections
GET/api/storefront/collections/{slug}Collection + its products
POST/api/storefront/cartsCreate a cart → { cartId }
GET/api/storefront/carts/{cartId}Cart with lines + totals
POST/api/storefront/carts/{cartId}/itemsAdd item { productId, variantId?, quantity }
PATCH/api/storefront/carts/{cartId}/items/{itemId}Update quantity (0 removes)
POST/api/storefront/carts/{cartId}/discountApply { code }
POST/api/storefront/checkout/payment-intentStart embedded checkout
POST/api/storefront/subscriptionsStart a subscribe & save subscription → { clientSecret }
GET/api/storefront/orders/{accessToken}Order status by token
GET/api/storefront/products/{slug}/reviewsApproved reviews for a product
POST/api/storefront/products/{slug}/reviewsSubmit a review (lands as pending)
POST/api/storefront/uploadsUpload an image (multipart file) → { url }

Embedded checkout

  1. Build a cart with the cart endpoints; keep the cartId.
  2. POST /checkout/payment-intent with the cart, email, and shipping address.
  3. Mount Stripe Elements with the returned clientSecret + publishableKey and call stripe.confirmPayment — card entry stays on your site.
  4. Stripe's webhook finalizes the order (paid, inventory, customer). Poll GET /orders/{accessToken} for status.
POST /api/storefront/checkout/payment-intent
{ "cartId": "…", "email": "a@b.com",
  "shippingAddress": { "line1": "1 Main St", "city": "NYC", "country": "US" } }

→ { "ok": true, "data": {
     "clientSecret": "pi_…_secret_…",
     "publishableKey": "pk_test_… (Stripe)",
     "orderId": "…", "accessToken": "…",
     "breakdown": { "totalCents": 4200, "currency": "USD" } } }

Note: embedded checkout doesn't support stores with automatic tax enabled yet (Stripe Tax runs in hosted Checkout only). Such stores get a 422 tax_not_supported_embedded. Use hosted checkout, or disable store tax, until Stripe Tax for embedded ships.

Full Next.js + Stripe Elements example: examples/headless-next/ in the repo.

Admin API

Secret key, server-side only. Manage products, stock, and orders.

MethodPathDescription
GET/api/admin/productsList products. ?status&limit&cursor
POST/api/admin/productsCreate a product
GET/api/admin/products/{id}Product + variants + images
PATCH/api/admin/products/{id}Update product fields
DELETE/api/admin/products/{id}Delete a product
POST/api/admin/products/{id}/inventoryAdjust stock { variantId?, set?|delta? }
GET/api/admin/ordersList orders. ?status&limit&cursor
GET/api/admin/orders/{id}Order + items
POST/api/admin/orders/{id}/fulfillmentSet fulfillment + tracking
GET/api/admin/reviewsList reviews. ?status&productId&limit&cursor
PATCH/api/admin/reviews/{id}Moderate a review { status: approved|rejected }
DELETE/api/admin/reviews/{id}Delete a review
curl -X POST https://app.buildbazaar.io/api/admin/products/PID/inventory \
  -H "Authorization: Bearer sk_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{ "delta": -3 }'