Checkout SDK
Configuration and lifecycle
Configure checkout, callbacks, redirects, theming, and destroy().
Configuration reference
Pass options to ZippyPay.create() or use theme-* attributes on <zippy-pay-checkout>.
ZippyPayConfig
typescripttype ZippyPayConfig = {
// Required
environment: "production" | "staging" | "development";
sessionId: string; // UUID v4
clientToken: string; // zps_…
// Embed
mode?: "inline" | "modal"; // default: "inline"
container?: HTMLElement | string; // required for inline
// Appearance
theme?: ZippyTheme;
appLinks?: { ios?: string; android?: string };
locale?: "en"; // reserved — currently only "en"
// Checkout methods (SDK >= 1.1.0; default mobileApp.policy enforce in 1.2.0+)
checkoutPolicy?: "QR" | "MANUAL"; // omit for full chooser
mobileApp?: { policy?: "off" | "option" | "enforce" }; // phone only; default enforce (1.2.0+)
// Redirects (after terminal screen countdown)
redirectOnComplete?: boolean;
redirectOnFailure?: boolean;
// Modal only
closeOnBackdropClick?: boolean; // default: false
closeOnEscape?: boolean; // default: false
// Callbacks
onReady?: (session: PaymentSession) => void;
onSessionUpdate?: (session: PaymentSession) => void;
onComplete?: (session: PaymentSession) => void;
onExpired?: (session: PaymentSession) => void;
onError?: (error: ZippyPayError) => void;
onClose?: () => void; // modal only
};Required and embed fields
| Name | Type | Required | Description |
|---|---|---|---|
environment | production | staging | development | Required | Resolves the API base URL. Must match where the session was created. |
sessionId | UUID v4 | Required | Invalid format throws at init: Zippy Pay: sessionId must be a UUID v4. |
clientToken | zps_… | Required | Payment session token from your server. Authorizes checkout for this session only. |
mode | inline | modal | Optional | Embed mode. Defaults to "inline". |
container | string | HTMLElement | Optional | Required for inline mode. CSS selector or DOM element. Throws if not found. |
Optional behavior
| Name | Type | Description |
|---|---|---|
checkoutPolicy | "QR" | "MANUAL" | Restrict web checkout methods. Omit for full chooser (QR + manual). Affects fallback options after failed mobile app handoff. |
mobileApp.policy | off | option | enforce | Phone only — ignored on desktop. Default enforce (SDK 1.2.0+): auto-start Pay with Zippy. option: chooser + Pay with Zippy. off: web-only (QR/manual per checkoutPolicy). |
redirectOnComplete | boolean | After success screen countdown, redirect to session.successUrl. |
redirectOnFailure | boolean | After failure or expiry screen countdown, redirect to session.failureUrl. |
appLinks | { ios?, android? } | Override App Store / Google Play URLs in the checkout footer. |
closeOnBackdropClick | boolean | Modal only. Default: false. |
closeOnEscape | boolean | Modal only. Default: false. |
Web component checkout attributes
| Name | Type | Description |
|---|---|---|
checkout-policy | QR | MANUAL | Same as checkoutPolicy. |
mobile-app-policy | off | option | enforce | Same as mobileApp.policy. Default enforce (SDK 1.2.0+). Supports off, option, enforce. |
Default — Pay with Zippy on phone (SDK 1.2.0+)
typescript// Omitting mobileApp is equivalent to { policy: 'enforce' } on phone
ZippyPay.create({
environment: "production",
sessionId: "550e8400-e29b-41d4-a716-446655440000",
clientToken: "zps_REDACTED",
mode: "inline",
container: "#zippy-checkout",
});Web-only on phone (pre-1.2.0 behavior)
typescriptZippyPay.create({
environment: "production",
sessionId: "550e8400-e29b-41d4-a716-446655440000",
clientToken: "zps_REDACTED",
mode: "inline",
container: "#zippy-checkout",
mobileApp: { policy: "off" },
});Chooser + Pay with Zippy
typescriptZippyPay.create({
environment: "production",
sessionId: "550e8400-e29b-41d4-a716-446655440000",
clientToken: "zps_REDACTED",
mode: "inline",
container: "#zippy-checkout",
mobileApp: { policy: "option" },
checkoutPolicy: "QR", // optional — restrict web fallbacks after failed handoff
});Web component
html<!-- Default: enforce on phone (SDK 1.2.0+) -->
<zippy-pay-checkout
environment="production"
session-id="550e8400-e29b-41d4-a716-446655440000"
></zippy-pay-checkout>
<!-- Web-only on phone -->
<zippy-pay-checkout
environment="production"
session-id="550e8400-e29b-41d4-a716-446655440000"
mobile-app-policy="off"
></zippy-pay-checkout>Example
typescriptimport { ZippyPay } from "@zippypay/checkout";
ZippyPay.create({
environment: "production",
sessionId: "550e8400-e29b-41d4-a716-446655440000",
clientToken: "zps_REDACTED",
mode: "inline",
container: "#zippy-checkout",
redirectOnComplete: true,
redirectOnFailure: true,
theme: { primary: "#1a56db", mode: "auto" },
onReady: (session) => console.log(session.amount),
onComplete: (session) => console.log(session.transactionId),
});Instance lifecycle
ZippyPay.create(config) returns an instance with open(), close(), and destroy().
Instance methods
| Name | Type | Description |
|---|---|---|
open() | void | Open modal checkout. No-op for inline mode. |
close() | void | Close modal without destroying. Session stays alive. No-op for inline. |
destroy() | void | Stop polling, remove UI, clean up timers and listeners. Idempotent. |
Callbacks and events
Imperative API callbacks
| Name | Type | Description |
|---|---|---|
onReady(session) | PaymentSession | Fires once after the session loads successfully. |
onSessionUpdate(session) | PaymentSession | Fires on every poll update and session change. |
onComplete(session) | PaymentSession | Fires when status === 'COMPLETED'. |
onExpired(session) | PaymentSession | Fires when session expires (status === 'EXPIRED'). |
onError(error) | ZippyPayError | Fires on API or terminal errors. |
onClose() | — | Modal only. Fires when modal is closed. |
Web component events
| Name | Type | Description |
|---|---|---|
zippy-ready | PaymentSession | Initial load complete. |
zippy-session-update | PaymentSession | Session state changed. |
zippy-complete | PaymentSession | Payment succeeded. |
zippy-expired | PaymentSession | Session expired. |
zippy-error | ZippyPayError | Recoverable or terminal error. |
zippy-close | null | Modal closed. |
ZippyPayError
typescriptclass ZippyPayError extends Error {
readonly code: string;
readonly status: number;
readonly detail: string;
readonly correlationId?: string;
}Redirect behavior
When checkout reaches a terminal state, the SDK shows a result screen with a 7-second countdown, then:
Terminal exit behavior
| Name | Type | Description |
|---|---|---|
Success + redirectOnComplete + successUrl | redirect | Redirect to success URL with query params. |
Failure/expiry + redirectOnFailure + failureUrl | redirect | Redirect to failure URL. |
Otherwise (inline) | destroy | Removes checkout UI. |
Otherwise (modal) | close + destroy | Closes modal then destroys instance. |
Success redirect query params
text?sessionId=550e8400-e29b-41d4-a716-446655440000&status=COMPLETED&transactionId=…Expired redirect query params
text?sessionId=550e8400-e29b-41d4-a716-446655440000&status=EXPIREDOther failure types redirect to failureUrl without extra query params.
Theming
Pass a partial theme object — unset tokens use SDK defaults. When mode: 'auto', the SDK follows prefers-color-scheme: dark.
Theme tokens
| Name | Type | Description |
|---|---|---|
primary | CSS color | Buttons, links, accents. Default: #3f63f3. |
primaryForeground | CSS color | Text on primary buttons. Default: #ffffff. |
background | CSS color | Main background. Default: #ffffff (#0f172a in dark). |
surface | CSS color | Cards and inputs. Default: #ffffff (#1e293b in dark). |
text | CSS color | Primary text. |
textMuted | CSS color | Secondary text. |
border | CSS color | Borders. |
error | CSS color | Error states. Default: #dc2626. |
success | CSS color | Success states. Default: #059669. |
borderRadius | CSS length | Card corner radius. Default: 20px. |
fontFamily | font stack | Font family. Default: 'DM Sans', system-ui, … |
mode | light | dark | auto | Color scheme. Default: "light". |
Web component theme attributes
| Name | Type | Description |
|---|---|---|
theme-primary | attribute | primary |
theme-primary-foreground | attribute | primaryForeground |
theme-background | attribute | background |
theme-surface | attribute | surface |
theme-text | attribute | text |
theme-text-muted | attribute | textMuted |
theme-border | attribute | border |
theme-error | attribute | error |
theme-success | attribute | success |
theme-border-radius | attribute | borderRadius |
theme-font-family | attribute | fontFamily |
theme-mode | attribute | mode |
Theme example
typescriptZippyPay.create({
theme: {
primary: "#1a56db",
primaryForeground: "#ffffff",
borderRadius: "12px",
fontFamily: "'Inter', sans-serif",
mode: "auto",
},
// …session + token…
});App download links
On desktop, the checkout footer includes App Store and Google Play badge links (HTTPS) so customers can install the Zippy Pay app. Tapping a badge opens a modal with a store QR code and direct link.
On phone, install is offered on the failed app handoff screen via Install Zippy — not via footer badges. The store opens only when the customer taps that button; it is never opened automatically.
Override desktop footer store URLs
typescriptZippyPay.create({
sessionId: "550e8400-e29b-41d4-a716-446655440000",
clientToken: "zps_REDACTED",
environment: "production",
appLinks: {
ios: "https://apps.apple.com/app/your-app/id1234567890",
android: "https://play.google.com/store/apps/details?id=your.package",
},
});Default footer URLs (if appLinks omitted)
| Name | Type | Description |
|---|---|---|
iOS | URL | https://apps.apple.com/in/app/zippypay/id6806799311 |
Android | URL | https://play.google.com/store/apps/details?id=app.getzippy.pay |
Security checklist
- Never bundle
X-Api-Keyin browser code. - Keep
clientTokenin memory only — notlocalStorage, cookies, query strings, or analytics. - Encode only
sessionIdin QR codes and deep links — never the client token. - Display amount from
onReady/onSessionUpdate, not from page props or URL params. - Register the page origin under Integrations → Allowed browser origins in the portal. Unregistered domains return
403 payment-session.origin-not-allowed. - Origin allowlisting applies to embedded checkout. Authenticate server-side session create with
X-Api-Keyon your backend only. - Create a new session when the client token is invalid (401) — do not retry blindly.
- Use HTTPS in production for your checkout page.
- Call
destroy()on SPA navigation to stop polling and remove UI.