Skip to main content
The Headless Checkout SDK is for merchants who want a fully custom checkout page on their own domain. You own the layout, fields, and buyer experience. Shoppex still creates the invoice, starts the payment session, handles 3DS or redirects, receives webhooks, and fulfills the order. Use this when the hosted checkout page or modal embed is not flexible enough.
Headless checkout requires an active Business plan.
Under Settings → Developer → Headless → Order Links & Emails, configure where Shoppex order emails send your buyers. These settings apply to new orders created through the Headless Checkout API after this feature was introduced. Existing orders and hosted checkout orders keep their current behavior. Set Order Page URL to an HTTPS URL on one of your allowed sites, for example https://yourstore.com/orders/{invoice_id}. Shoppex replaces {invoice_id} with the public invoice reference. Leave the field empty to keep hosted checkout links. Your page must authenticate the buyer and support payment, order details, and delivery access. An invoice reference alone is not authentication. Shoppex does not forward hosted completion grants or invoice secrets to your URL. Order Created, Payment Completed, and Payment Issues independently control automatic headless order emails. Existing store-wide and customer preferences still apply. Shoppex continues to handle payment and fulfillment. Changing the order link does not require disabling any emails. If you choose to disable completion emails, buyers must be able to access purchases through your checkout or customer account. Requested resends and gift-recipient delivery remain available. Merchant notifications, sign-in emails, review requests, and marketing/recovery campaigns are separate from these settings. These settings do not change payment-provider return URLs. Configure return_url and cancel_url on the checkout session as before.

What you need

  • A storefront or app page on your own domain.
  • An active Business plan.
  • A headless checkout publishable key from the dashboard.
  • At least one allowed site: the site that will call the browser API.
  • @shoppexio/checkout-js installed in your frontend app.

Dashboard setup

1

Generate a publishable key

Open Dashboard -> Settings -> Developer -> Headless and click Generate key. Copy the pk_live_... key immediately. The full key is shown only once.
2

Add your storefront site

Open Dashboard -> Store -> Embed Hub -> Elements and add the exact site that hosts your checkout page under Allowed sites, for example https://yourstore.com.
3

Add local development sites

For local testing, add the exact local site too, for example http://localhost:3000.
Headless and Elements share one list of allowed sites. The Headless settings page shows it; you change it in the Embed Hub. A team member who adds or removes a site needs both the store design and the API key write permission. A site is only the scheme, host, and optional port. Do not include a path. Use https://; plain http:// works only for localhost and 127.0.0.1. Wildcards such as https://*.vyy.gg are not allowed. If your site works on both https://vyy.gg and https://www.vyy.gg, add both. You cannot remove the site that hosts your Order Page URL. Change or clear that URL first.
Never put a secret shx_... API key in browser code. Headless checkout uses pk_live_... or pk_test_... publishable keys only.

Install

React example

ShoppexPoweredBy is required unless Shoppex has manually assigned the hidden White Label plan to the merchant. The SDK checks that the badge is visible before payment confirmation whenever the server returns attribution.required: true. The server owns this directive; the browser cannot disable it.

API shape

The browser SDK sends the publishable key in the x-shoppex-publishable-key header. Shoppex also checks the request Origin header against your allowed origins. The SDK can:
  • create a checkout session
  • read the current session status
  • apply or remove coupons
  • set tips
  • select add-ons
  • save buyer email, marketing preference, billing address, and method-specific terms acceptance
  • save product custom fields and delivery instructions
  • start a gateway payment session
  • complete zero-total checkouts
  • request and verify Customer Balance OTPs, then apply full or partial balance payments
  • submit browser-bound proof for manual payment methods
  • capture/finalize PayPal and SumUp payments
  • fetch delivery after the payment is complete
The session response includes line items, totals, authoritative gateway fee previews, payment-method presentation and requirements, buyer identity state, Customer Balance availability, product custom-field definitions, delivery instructions, shop branding, terms, and delivery state. Render against the gateway kind, not the provider name, so your UI works across card, redirect, crypto, balance, and manual payment flows.

Buyer details and payment requirements

Each entry in session.gateways_available contains:
  • fee_preview: the server-calculated fee for that method
  • presentation: merchant label, button label, icon, and provider-attribution preference
  • requirements: whether method terms and a billing address must be saved
presentation.hide_provider_attribution only controls the payment provider’s attribution. It does not change the server-owned ShoppexPoweredBy requirement. Persist the details before starting the gateway:
Each line item’s custom_fields_config describes the fields to render. A field with type: 'select' also carries options: render a dropdown or radio group, and save one of those labels exactly as listed. Any other answer is refused with 400 and error_code: 'custom_field_option_invalid'. EU consumer law (Consumer Rights Directive Art. 16(m)) lets a buyer of digital content waive the 14-day right of withdrawal in exchange for immediate delivery. Shops opt in under Settings → Checkout → EU Withdrawal Consent. When they have, the session carries the server’s verdict for this buyer:
required is true only for EU buyers (or an unknown country) with at least one immediately delivered digital line item; renewals and non-EU buyers are never asked. While required is true and recorded_at is null, every startPaymentSession() is refused with 409 withdrawal_consent_required. Render text verbatim as an unchecked checkbox and record the proof once the buyer ticks it. The proof is first-write-wins and returns the refreshed view:
With React, useCheckoutSession() exposes recordWithdrawalConsent() and updates the session in place. useStripePaymentSession() starts its attempt as soon as the session id arrives; if that start is refused because the consent is outstanding, the hook re-issues it by itself once the proof is recorded. Other gateways start on your call, so start them after the consent.

Free and Customer Balance checkout

balance.eligible is the server’s store-credit verdict for this wallet and order. When it is true, the wallet and amount rules accept payWithBalance without an amount. It pays the remaining total, or the whole balance as a partial payment when allow_partial_payment is true. The session’s other requirements, such as a saved shipping address or withdrawal consent, still apply. When it is false, ineligible_reason says why: With subscription_partial_leaves_uncollectible_remainder, balance.max_amount is the largest part of the balance the server accepts. It leaves exactly the card minimum for another payment method. Offer it as an explicit amount: payWithBalance(session.id, verified.session_token, verified.balance.max_amount). max_amount is null with every other reason, and also when the remaining total is itself below the card minimum, because then no part payment is collectible. Customer Balance uses the same wallet, policy, attempt, reconciliation, stock-hold, and completion-access services as Hosted Checkout.

Crypto progress and underpayments

Call getSession() or the React refresh() action to read the authoritative payment projection. session.payment_detail includes the exact decimal strings needed for a crypto progress or underpayment UI:
The detail contains expected, received, remaining, crypto_currency, buyer_actionable, buyer_action_reason, provider_status, credited_fiat, received_fiat_estimate, fiat_currency, confirmations, and confirmations_needed when those values are available. credited_fiat is the amount the provider applied to the invoice. received_fiat_estimate is only a display estimate for crypto observed on-chain and must never be counted as paid. Keep the amount values as strings. Do not recalculate the remainder with JavaScript floating-point numbers.

Embed provider adapters

Stripe uses useStripePaymentSession. The framework-agnostic Headless export also includes:
These helpers mount provider-owned fields into your element and call the same Shoppex session/finalize endpoints as Hosted Checkout. Square and NMI perform their tokenized second session call; SumUp finalizes after the widget succeeds; PayPal captures the approved order. NMI includes Kount and 3D Secure when the merchant gateway requires them.

Manual payment proof

When a manual payment session has require_proof: true, use proof_type to render a note input, image input, or both. Then submit the proof with the completion grant returned by the start call:
The SDK registers completion access before uploading. A publishable key alone cannot submit proof for another buyer’s invoice.

Troubleshooting

Generate key fails

Check these first:
  • The shop has an active Business plan.
  • You are using the shop owner account or a team member with permission to manage webhooks/developer settings.
  • Your dashboard session is fresh. Refresh the page or log out and back in.
If it still fails, open browser DevTools -> Network and inspect:
Common responses:

Add site fails

Use a full https:// site, or http:// for localhost. These are valid:
These are refused:
The dashboard removes paths before saving (https://vyy.gg/checkout is saved as https://vyy.gg). The backend refuses everything else with a reason. If the UI only shows a generic error, inspect this request:

Browser API calls fail

Check the browser response code:

Headless Commerce Overview

Pick the right integration shape for custom storefronts, apps, and backend flows.

Checkout Embed SDK

Use the hosted modal when you do not need a fully custom checkout UI.

Storefront SDK

Read public product, cart, and storefront data from browser code.

Webhooks

Fulfill orders and update your app after Shoppex receives payment events.