Checkout SDK
Embeddable checkout for React, Vue, Svelte, SvelteKit, Nuxt, Solid, Angular, Next.js, jQuery and vanilla JS — card entry stays inside a cross-origin iframe.
What it does
@checkout/sdk mounts a ready-made checkout into your page. The customer picks a payment method, enters a card, and completes 3DS — all inside a cross-origin iframe served from the Lodash frame origin, so raw PANs never touch your DOM or your JavaScript context.
You render a container. The SDK owns everything inside it.
Install
bun add @checkout/sdk # or npm / pnpm / yarnFramework peers (react, vue, svelte, solid-js, @angular/core, tailwindcss, …) are optional — install only the one you use.
styles.css is not auto-injected. Every integration must import it once: import '@checkout/sdk/styles.css'. Tailwind v4 users can instead @import "@checkout/sdk/tailwind.css" to pull the SDK theme layer into their own build.
Three things you must supply
| Field | What it is | Why |
|---|---|---|
source.session | A one-time checkout token ({ kind: 'checkout', session: 'cs_…' }) | Minted by your server calling POST /checkouts with its secret key (sk_…). Never call that from the browser. Payment links use { kind: 'payment_link', token: '…' } instead. |
config.apiEndpoint | The Lodash API origin | Required. The SDK will not guess it from window.location — that would send the session token to your own server. Omitting it throws MissingEndpointError. |
config.publishableKey | Your client-safe pk_test_… / pk_live_… key | The server checks that the key and the session belong to the same app, and that your page's Origin is allow-listed. |
For the cross-origin embed you also pass frameUrl.
frameUrl is a base, not a page. The SDK appends /checkout.html itself via checkoutFrameUrl(). Pass https://pay.example.com/embed — not https://pay.example.com/embed/checkout.html.
A publishable key must be pk_test_ or pk_live_ followed by at least four alphanumerics. A bare prefix, an underscore in the body, sk_ secret keys, Omise pkey_ keys and pk_p256_ service-account keys are all rejected with PublishableKeyError.
Quick start
import { EmbeddedCheckout } from '@checkout/sdk/react'
import '@checkout/sdk/styles.css'
export function PayPage({ session }: { session: string }) {
return (
<EmbeddedCheckout
source={{ kind: 'checkout', session }}
config={{
apiEndpoint: 'https://api.example.com',
publishableKey: 'pk_test_abcd1234',
}}
frameUrl="https://pay.example.com/embed"
returnUrl={window.location.href}
onSuccess={() => console.log('paid')}
onError={(err) => console.error(err)}
/>
)
}@checkout/sdk/next re-exports the same React surface with 'use client' already applied.
Do not pass onRedirect unless you mean it. Omitting it is the correct default — the SDK navigates the top window itself via navigateTop, which is written to survive being called from inside a cross-origin iframe. If you pass a handler, you own the navigation, and a handler that only logs will strand the customer mid-3DS on a blank frame.
Configure once instead of per call
import { configure } from '@checkout/sdk'
configure({
apiEndpoint: 'https://api.example.com',
frameUrl: 'https://pay.example.com/embed',
publishableKey: 'pk_test_abcd1234',
})Values passed at a call site always win over configure(). Full reference: Configuration.
Export map
| Subpath | Contents |
|---|---|
@checkout/sdk | mountEmbeddedCheckout, configure, CheckoutClient, assertPublishableKey, resolveApiEndpoint / resolveVaultEndpoint / resolveFrameUrl / checkoutFrameUrl, createProvider / registerProvider / getAvailableProviders / LodashProvider, checkout-return helpers, formatters and validators |
@checkout/sdk/react | Checkout, EmbeddedCheckout, PaymentElement, SetupIntentElement, BankAccountElement, useCheckout, resolveCheckoutGate, LinkBadge, useLink, CheckoutClient, applePay / googlePay / promptPay |
@checkout/sdk/next | ./react re-exported with 'use client' |
@checkout/sdk/vue ./svelte ./sveltekit ./nuxt ./angular ./solid | The shared framework-agnostic surface (the root list minus the React components). ./solid additionally exports its EmbeddedCheckout. |
@checkout/sdk/vue/EmbeddedCheckout.vue ./svelte/EmbeddedCheckout.svelte ./solid/EmbeddedCheckout ./angular/EmbeddedCheckout | The per-framework component. Angular's exports EmbeddedCheckoutComponent. |
@checkout/sdk/vanilla | IIFE for <script> tags — CheckoutSDK global — plus an ESM build for bundlers |
@checkout/sdk/jquery | IIFE — CheckoutJQuery global — and installs $.fn.checkout(options) / $.fn.checkoutDestroy() |
@checkout/sdk/plugins | Wallet buttons: applePay, googlePay, promptPay |
@checkout/sdk/frame | The frame-side host, used by the checkout page itself |
@checkout/sdk/styles.css @checkout/sdk/tailwind.css | Stylesheets |
The framework components ship as source (.vue / .svelte / .tsx / .ts) and are compiled by your own toolchain — the same convention svelte-package uses. You need the matching Vite plugin (@vitejs/plugin-vue, @sveltejs/vite-plugin-svelte, vite-plugin-solid), which any app in that framework already has. Solid also ships a pre-compiled fallback for bundlers that do not apply the Solid Babel transform.
Which entry do I use
| Your app | Import from | Mount with |
|---|---|---|
| React / Next.js | @checkout/sdk/react (or /next) | <EmbeddedCheckout> |
| Vue | @checkout/sdk/vue/EmbeddedCheckout.vue | the SFC |
| Svelte / SvelteKit | @checkout/sdk/svelte/EmbeddedCheckout.svelte | the component |
| Solid | @checkout/sdk/solid | <EmbeddedCheckout> |
| Angular | @checkout/sdk/angular/EmbeddedCheckout | EmbeddedCheckoutComponent |
No bundler, plain <script> | @checkout/sdk/vanilla | CheckoutSDK.mountEmbeddedCheckout(target, options) |
| Existing jQuery page | @checkout/sdk/jquery | $(el).checkout(options) |
Every one of these is the same core: mountEmbeddedCheckout mounting the checkout frame. The framework wrappers only manage the container's lifecycle.
Errors worth handling
| Error | Cause |
|---|---|
MissingEndpointError | No apiEndpoint / frameUrl from either the call site or configure() |
PublishableKeyError | Missing key, a secret (sk_) or provider key, or a malformed one |
ApiError | A non-2xx response from the checkout API |
Where to go next
Configuration
apiEndpoint, frameUrl, publishableKey, colorScheme, locale, country — and configure().
Framework adapters
Vue, Svelte, SvelteKit, Nuxt, Angular, Solid and Next.js usage.
Embed & vanilla API
mountEmbeddedCheckout, the handle, 3DS return handling, jQuery.
Payment providers
createProvider, registerProvider, and the PaymentProvider contract.