Web SDK — Overview
Lunixi publishes eight browser SDKs. They share one core; what differs is what they do and how they authenticate.
| SDK | What it does | Page |
|---|---|---|
checkout | Payment form | Checkout Form |
field | Hosted card field (narrows PCI scope) | Hosted Card Field |
identity | Device and behavioural telemetry | Identity Web SDK |
kyc | Guided identity verification flow | KYC SDK |
portal | Customer portal — plans, subscriptions, cards | Portal SDK |
marketplace | Sub-merchant application and management flow | Marketplace SDK |
paymentLink | The payment link screen — run by Lunixi on pay.lunixi.com, nothing for you to install; embedding it in your site is coming soon | Payment Page |
loader | Entry point that lazy-loads the others | Below |
Loader — one script, all of them
You do not have to load each SDK with its own <script>. Include the loader, and the module you call is fetched on first use.
<script src="https://cdn.lunixi.com/lunixi-loader.min.js"></script>// lunixi-kyc.min.js is downloaded on this line, not before
await Lunixi.kyc.mount('#kyc', { … });The loader installs a proxy: calling Lunixi.<module>.<method>(...) downloads the module, then forwards the call. A second call to the same module does not download it again.
If you need to change the CDN address, define window.Lunixi = { config: { cdnBaseUrl: '…' } } before loading and the loader will use it. Otherwise it derives the base from its own <script src>.
Four integration modes
The SDKs do not force one usage style. You pick based on how much control you want:
| Mode | What you get | Call |
|---|---|---|
| Mode 0 — Catalog | Read-only data via a publishable key; no session, anonymous visitor | Lunixi.portal.catalog({...}) |
| Mode 1 — Pre-built UI | We render the whole screen; you supply a DOM target | .mount(target, {...}) · .form({...}) |
| Mode 2 — Headless | You write the UI; the SDK is only the data layer | .create({...}) |
| Mode 3 — Hybrid | You mount individual pieces of the screen | Lunixi.portal.plans.mount(...) |
You can move between Mode 1 and Mode 2. Ship quickly with the pre-built UI, then switch to the same SDK's headless client when your branding needs grow — the endpoints and the session model do not change.
The difference between .mount() and .form(): mount attaches directly, form returns a handle so you can unmount later.
Authentication — it differs per SDK
This is the most important table on the page. A secret key is never present in the browser; each SDK has its own safe route.
| SDK | What travels in the browser | How it is verified |
|---|---|---|
portal catalog (Mode 0) | Bearer mk_live_pk_… | Publishable key plus an Origin match |
kyc | Publishable key → signed session | POST /api/v1/kyc/sdk/init |
identity | Session token minted by your server | sessionBootstrapUrl (your endpoint) |
portal (Mode 2) | X-Portal-Session (JWT) | Portal session |
marketplace | X-Marketplace-Token (mp_…) | Not Bearer — a portal-token pattern |
checkout | Checkout token plus a session-proof cookie | Payment session |
paymentLink | No key — the link's short code; a bot check (Turnstile) and a short-lived payment session cookie when starting a payment, then a checkout token at the payment step | Payment link session (/api/public/v1/pay/*) |
How a publishable key is protected
A publishable key is not a secret — it is visible in your page source. The protection is not in the key but in where it can be used from:
- The key is shaped
mk_{environment}_pk_…; the server checks the prefix. - The request must carry an
Originheader — the browser sets it, and JavaScript on the page cannot forge it. - That
Originmust be an exact match in the allow-list registered for the key. - No match,
401.
So even a stolen key cannot be used from outside your domain. But if you keep the origin allow-list wide — wildcard-like patterns, test domains left in production — you weaken that protection yourself.
Hosted card field (field)
For cases where the card number must never enter your page, there is a separate SDK: the field is embedded as an iframe served from fields.lunixi.com. Card data never touches your DOM, which narrows your PCI scope.
It is also reachable from the checkout SDK via Lunixi.checkout.createCardField(...).
Shared behaviour
- Lazy loading — the heavy UI (React plus the flow screens) is downloaded only in Mode 1, on first
mount. Go headless and it never enters your bundle. - Not fail-open — SDK calls do not silently return a pass on failure; they throw. You own the fallback.
- Environment separation — the SDK talks to whichever environment your key was issued for.
Never put a secret key in the browser. The only key that belongs on a page is a publishable key. If an SDK is asking you for a secret key, you are using the wrong mode.
Where to start
- Taking payments → Checkout Form
- Verifying identity → KYC SDK
- Showing plans or opening a customer portal → Portal SDK
- Onboarding sub-merchants → Marketplace SDK
- Collecting device signals → Identity Web SDK