Skip to main content
Build a custom storefront on Next.js 16 (App Router) that:
  1. Lists products from your Shoppex catalog on the server.
  2. Starts a checkout session from a Server Action.
  3. Redirects the customer to Shoppex hosted checkout.
  4. Receives a signed webhook when the order is paid and runs your own fulfillment.
Time budget: 15 minutes. You need a Shoppex shop and an API key (shx_*).
If you do not have an API key yet, open Dashboard → Settings → Developer API, click Generate New API Key, pick scopes products.read payments.write webhooks.read, and copy the key (it is shown once).

1. Set Up the Project

Add your API key to .env.local:
SHOPPEX_API_KEY must only exist on the server. Never prefix it with NEXT_PUBLIC_.
Create a tiny server-only client wrapper at lib/shoppex.ts:

2. List Products on the Server

app/products/page.tsx reads the catalog on every request. Because this is a Server Component, your API key never leaves the server.

3. Start Checkout from a Server Action

A product page with a Server Action that creates a payment and redirects to hosted checkout. The API key stays on the server; the browser only ever sees the resulting checkout_url. app/products/[id]/page.tsx:
return_url is where Shoppex sends the customer after a successful payment. cancel_url is where they go if they abandon checkout.If you prefer the Stripe-style alias, POST /dev/v1/checkout/sessions is available too. The published JS SDK does not wrap that route yet, so the quickstart uses POST /dev/v1/payments, which already has first-class SDK support.
This quickstart uses POST /dev/v1/payments because it is the smallest ad-hoc checkout example (title + amount). That path does not link checkout to the catalog product you fetched above.If the product is a subscription, or you need serial/file/DYNAMIC delivery, use POST /dev/v1/orders with items: [{ product_id: product.uniqid, quantity: 1 }] instead. See Subscriptions and SaaS Paywall.

4. Verify the Signed Webhook

Create a webhook endpoint in the Shoppex dashboard (Settings → Webhooks → Add Endpoint) pointing at https://your-site.com/api/webhooks/shoppex, subscribe to order:paid, and copy the signing secret into SHOPPEX_WEBHOOK_SECRET. app/api/webhooks/shoppex/route.ts:
Always verify the signature with constant-time comparison. The timingSafeEqual call above is what prevents timing-side-channel attacks. Never compare signatures with ===.
Return 2xx within a few seconds. Shoppex retries failed deliveries with backoff — do your real fulfillment work in a background job and ack the webhook immediately if fulfillment takes longer than a couple of seconds.

5. Local Testing

Run the app and point a tunnel at it so the webhook is reachable:
Set the webhook URL in the Shoppex dashboard to the ngrok URL + /api/webhooks/shoppex. In the dashboard, click Send Test Event on your webhook to verify the signature check passes.

What You Built

Your frontend, your routing, your brand. Shoppex handled the PSP selection, 3DS, the hosted checkout page, the payment confirmation, the event delivery, and will also handle refunds, disputes, and subscriptions when you add them.

Next Steps

Webhook Event Catalog

Every event Shoppex emits, with sample payloads.

Architecture Reference

Three reference setups including mobile + backend-for-frontend.

Checkout Embed SDK

Prefer a modal over a redirect? Swap the Server Action for a buy button.

Dev API Reference

Subscriptions, licenses, coupons, customers, and more.