> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shoppex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Headless commerce with Shoppex

> Run Shoppex as the commerce engine behind any frontend — your UI, our orders, payments, invoices, licenses, subscriptions, and fulfillment.

Shoppex works as a **commerce engine behind your own frontend**. You own the UI, routing, and brand experience. Shoppex owns the catalog, payments, invoices, subscriptions, license delivery, and fulfillment.

<Note>
  You do not need to use a Shoppex theme or a Shoppex storefront domain as the customer-facing surface. Everything here is reachable from a plain Next.js, Nuxt, SvelteKit, Astro, Remix, React Native, or native mobile app.
</Note>

## When to go headless

* **You already have a brand site** — you run a marketing site, landing pages, or an app. You want checkout, invoices, and licenses without redesigning around a theme.
* **You want custom UX** — your storefront is part of a larger product. Examples include a Discord bot UI, a SaaS paywall, a mobile app, or an internal admin tool. A hosted shop does not fit.
* **You want API-first automation** — you generate catalog entries, licenses, or orders programmatically and want the frontend to stay thin.
* **You ship to native clients** — you need commerce inside iOS, Android, or Electron apps where a hosted web checkout is not ideal.

## What you keep, what Shoppex runs

| You keep                          | Shoppex runs                                 |
| --------------------------------- | -------------------------------------------- |
| UI, routing, layout, auth surface | Catalog, pricing, invoices, orders           |
| Brand domain + SEO                | Payment session creation across PSPs         |
| Customer session / login form     | PSP handling + 3DS + crypto                  |
| Product pages and cart UI         | License keys, serial pools, dynamic delivery |
| Email + notification style        | Subscriptions, trials, renewals, dunning     |
| Anything you want to own          | Webhooks, fraud shield, blacklist, disputes  |

## Pick your integration shape

<CardGroup cols={2}>
  <Card title="Dev API" icon="server" href="/developers/api-overview">
    Server-to-server. Bearer API keys or OAuth2. Full control over catalog, orders, customers, licenses, subscriptions, webhooks.
  </Card>

  <Card title="Storefront SDK" icon="browser" href="/developers/storefront-sdk/overview">
    Browser-side reads plus hosted-checkout redirect. Good fit for SPAs and SSR storefronts.
  </Card>

  <Card title="Checkout Embed SDK" icon="window-maximize" href="/developers/embeds/overview">
    Drop-in modal checkout on any existing site with one script tag.
  </Card>

  <Card title="Headless Checkout SDK" icon="credit-card" href="/developers/headless/checkout">
    Build your own checkout UI with a publishable key while Shoppex handles payment sessions.
  </Card>
</CardGroup>

### Decision tree

<Steps>
  <Step title="Do you need to read catalog or orders from a backend?">
    Use the **Dev API** with `@shoppexio/sdk` (Node, Python, PHP) or plain HTTP.
  </Step>

  <Step title="Do you need product, cart, or page data in the browser?">
    Use the **Storefront SDK** (`@shoppexio/storefront`) for public read endpoints and hosted-checkout redirect.
  </Step>

  <Step title="Do you only need a buy button on an existing page?">
    Use the **Checkout Embed SDK** — drop one script tag, add `data-shoppex-*` attributes, done.
  </Step>

  <Step title="Do you need to build the checkout UI itself?">
    Use the **Headless Checkout SDK** (`@shoppexio/checkout-js/headless`) with a dashboard-generated publishable key and allowed origins.
  </Step>

  <Step title="Do you mix all three?">
    That is the normal case. Dev API for server workflows, Storefront SDK for browser reads, Embed SDK for buy buttons.
  </Step>
</Steps>

<Note>
  If you are unsure which to pick, start with the [Next.js quickstart](/developers/headless/quickstart-nextjs). It builds a custom storefront in Next.js 16 in under 15 minutes. For a working foundation instead of building from scratch, use the [Storefront Starter](/developers/headless/storefront-starter).
</Note>

## Reference setups

Three shapes cover almost every headless build. Every one of them uses the same three pipes: reads through the Storefront SDK or Dev API, checkout through a hosted session or the Embed SDK, and signed webhooks back to your server.

### Setup A — pure SPA (React / Vue / Svelte / Astro Islands)

Best when your frontend is static or client-rendered and your only backend is your webhook receiver.

| Piece          | Responsibility                                                                  |
| -------------- | ------------------------------------------------------------------------------- |
| Browser SPA    | UI, product grid, cart UI, buy button with `@shoppexio/storefront` or Embed SDK |
| Webhook worker | Verify `X-Shoppex-Signature-V2`, run fulfillment, save order state              |
| Shoppex        | Catalog, PSP handling, invoice, license delivery, webhook delivery              |

Pick this for landing pages, marketing sites, and lightweight storefronts where you do not want to run a full origin server.

Do not ship `shx_*` API keys in the SPA bundle. Server-side reads need a small backend, either a worker or a Route Handler. If you need to transform data before it reaches the browser, use Setup B.

### Setup B — Next.js SSR (or Nuxt / SvelteKit / Remix)

Best when you want SEO, per-request personalization, and a single deployable unit.

| Piece             | Responsibility                                                    |
| ----------------- | ----------------------------------------------------------------- |
| Server Components | Catalog reads, personalization, pricing overrides, session lookup |
| Server Actions    | Create payment session, return redirect URL                       |
| Route Handlers    | Verify and handle signed webhooks                                 |
| Shoppex           | Everything payment, invoice, license, subscription                |

Pick this for any storefront where SEO matters, where you have a login, or where you serve per-customer content. The [Next.js quickstart](/developers/headless/quickstart-nextjs) builds exactly this shape.

Server Actions and Route Handlers must be the only place you touch `SHOPPEX_API_KEY`. Wrap your SDK client in `import 'server-only'`. Next.js 16 request APIs are async, so use `await cookies()`, `await headers()`, `await params`, and `await searchParams`. Use constant-time signature comparison (`timingSafeEqual`) in your webhook route.

### Setup C — mobile and backend-for-frontend

Best for native iOS, Android, React Native, or Electron apps, and for any client that must not hold long-lived API keys.

| Piece      | Responsibility                                                                           |
| ---------- | ---------------------------------------------------------------------------------------- |
| Native app | Your UI, your auth, deep-link handler for the return URL                                 |
| BFF        | Exchange user session for scoped Shoppex calls, create payment sessions, run fulfillment |
| Shoppex    | Everything commerce                                                                      |

The app sends its own session token to your BFF, the BFF creates the payment with the Dev API, and the app opens the hosted checkout URL in the system browser. Shoppex redirects the buyer back to your app and sends the signed webhook to your BFF, so your backend holds the final source of truth.

Use a universal link or app link as `return_url` so the operating system hands control back to your app cleanly. Never bundle the `shx_*` key in the app binary — always route through your BFF.

<Warning>
  For Apple App Store apps selling digital goods consumed in-app, App Store review rules can require In-App Purchase instead of a web checkout. Check the current rules before you ship.
</Warning>

### Data flow per checkout stage

| Stage                            | Who acts                                                                | Event                                                                                                |
| -------------------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Browse                           | Your frontend reads from Shoppex (Storefront SDK or Dev API proxy)      | —                                                                                                    |
| Add to cart                      | Your frontend (local state)                                             | —                                                                                                    |
| Checkout start (ad-hoc amount)   | Your server calls `POST /dev/v1/payments`                               | —                                                                                                    |
| Checkout start (catalog product) | Your server calls `POST /dev/v1/orders` with `items[].product_id`       | —                                                                                                    |
| Payment UI                       | Shoppex hosted checkout / Embed SDK                                     | —                                                                                                    |
| Payment success                  | Shoppex sends webhooks                                                  | `order:paid`, and `subscription:created` / `subscription:renewed` when the product is a subscription |
| Fulfillment                      | Your webhook handler grants access, sends license, sets up subscription | —                                                                                                    |
| Return                           | Customer hits your `return_url`                                         | —                                                                                                    |

<Note>
  Server-side cart state is not required for any of these setups today. Carts live in your frontend (local state, cookie, or your own database) until you create the payment session.
</Note>

## Authentication

| Surface                    | Token type                                            | Where it lives                               |
| -------------------------- | ----------------------------------------------------- | -------------------------------------------- |
| Dev API (server-to-server) | API key `shx_*` or OAuth2 access token                | Your server env / secret manager             |
| Storefront SDK (browser)   | None for public reads — shop slug identifies the shop | Browser bundle                               |
| Checkout Embed SDK         | None — shop id + product id in markup                 | Browser bundle                               |
| Customer portal OTP        | Email + one-time code verified server-side by Shoppex | Your login UI calls the public OTP endpoints |

Which side holds the key depends on the setup. In Setup A it is the worker or small backend, in Setup B the Server Components and Route Handlers, and in Setup C the BFF only.

Customer OTP (`/v1/customer/auth/otp/request` and `/verify`) works as a drop-in auth for Setup A. Setup B and C usually keep their own auth and use Shoppex for commerce only. For headless frontends, pass an optional `redirect_url` on `/v1/customer/auth/otp/request`. The URL is validated against the shop's allowed callback hosts (`<slug>.myshoppex.io` or any enabled custom domain) and returned on a successful `/verify` response. Invalid or disallowed hosts are rejected with `400`.

<Warning>
  Never ship `shx_*` API keys to the browser. They authenticate as your shop and can read or mutate anything in scope. Keep them on the server.
</Warning>

<Note>
  Package names are intentionally separate: use `@shoppexio/storefront` in customer-facing browser and headless code, and use `@shoppexio/sdk` only in trusted backend code that talks to the Developer API.
</Note>

See [Authentication](/developers/authentication) for API keys, OAuth2 authorization code flow, scopes, and key rotation.

## Webhooks and idempotency

Your backend receives signed events after state changes:

* `order:created`, `order:paid`, `order:cancelled`, `order:disputed`
* `product:created`, `product:edited`, `product:stock`, `product:dynamic`
* `subscription:created`, `subscription:renewed`, `subscription:cancelled`, `subscription:trial:started`, `subscription:trial:ended`, `subscription:upcoming`
* `query:created`, `query:replied`, `feedback:received`, `affiliate:payout_requested`

Order and subscription events also have `:product` variants (for example `order:paid:product`) when you need full product payloads. For paid purchases that reduce stock, handle `order:paid:product`. Use `product:stock` for direct catalog stock edits. New handlers must verify the timestamped `X-Shoppex-Signature-V2` header.

All three setups share the same reliability rules:

* Send `Idempotency-Key` on every mutating Dev API call. A UUID v4 is fine. Shoppex stores the response for 24 hours and replays it on retry.
* Make webhook handlers idempotent. Shoppex retries on non-2xx. Use the event's `data.uniqid` and `event` tuple as your deduplication key.
* Acknowledge webhooks fast. Queue heavy fulfillment work and return 2xx within a few seconds.

See [Webhooks](/developers/webhooks) for the event catalog, signing, retries, and the dynamic delivery contract for `DYNAMIC` products.
