docs

@xpay/sdk-js

The browser JavaScript SDK. Reference for every public export, method signature, and option type.

The XPay JavaScript SDK is a tiny CDN-loaded library that gives you a typed XPayInstance from your publishable key. From there you can mount payment UI as Elements, open a drop-in checkout, or run a single-call initCheckout and confirm a payment.

pnpm add @xpay/sdk-js
# or: npm install @xpay/sdk-js / yarn add @xpay/sdk-js

The package ships ESM and CJS builds, plus full TypeScript types. The runtime itself is loaded on demand from https://checkout.xpay.app/sdk.js. There's also a CDN script tag if you're not using a bundler:

<script src="https://checkout.xpay.app/sdk.js"></script>

This page is the reference for every public export. For walkthroughs, see Drop-in and Elements under Integrate.

Use this package when

@xpay/sdk-js is the vanilla SDK and is the right pick whenever you're not on React. That covers:

  • Plain HTML and static sites (use the CDN script tag).
  • Vue, Svelte, Solid, Angular, Lit, Qwik, Astro, and any other framework. Call the SDK from inside that framework's component lifecycle (mount, onMount, useEffect equivalent, etc.).
  • React Native via WebView until a native package ships.
  • Server-side scripts that need to type their clientSecret payloads (the package's TypeScript types are framework-agnostic).

For React, @xpay/sdk-react is a thin convenience wrapper on top of this package. It builds on loadXPay, xpay.initCheckout, and xpay.elements, so anything you read here applies under the hood there too.

Quick start

The recommended path is loadXPay at module level, then xpay.initCheckout() once you have a clientSecret from your server.

import { loadXPay } from "@xpay/sdk-js";

// Module-level: call once, share across the app.
const xpayPromise = loadXPay("pk_test_...");

async function startCheckout() {
  const xpay = await xpayPromise;
  if (!xpay) return; // SSR returns null on the server

  // initCheckout accepts a Promise<string> too, so you can pass the fetch directly.
  const checkout = await xpay.initCheckout({
    clientSecret: fetch("/api/create-checkout", { method: "POST" })
      .then((r) => r.json())
      .then((d) => d.clientSecret as string),
  });

  // Mount the payment element.
  const elements = checkout.getElements();
  const paymentElement = elements.create("payment");
  paymentElement.mount("#payment-element");

  // Listen for state changes (promo codes, quantity updates, fee recalcs).
  checkout.on("change", (session) => {
    document.getElementById("total")!.textContent =
      `${session.currency} ${(session.amountTotal / 100).toFixed(2)}`;
  });

  // Confirm when the customer submits.
  document.getElementById("pay")!.addEventListener("click", async () => {
    const result = await checkout.confirm({
      customerDetails: { email: "customer@example.com", name: "Aya Hassan" },
    });
    if (result.type === "error") {
      console.error(result.error.message);
      return;
    }
    window.location.href = "/thank-you";
  });
}

Exports at a glance

ExportKindWhat it is
loadXPay(publishableKey)functionLoads the SDK from CDN and returns an XPayInstance (or null on the server during SSR).
XPayInstanceinterfaceFactory for Elements, drop-in Checkout, confirmPayment, and initCheckout.
ElementsinterfaceManages payment elements (PaymentElement) and the session lifecycle.
PaymentElementinterfaceMountable payment-method selector with the card form, BNPL, kiosk, and wallet methods.
ConfirmPaymentOptionsinterfaceShape passed to xpay.confirmPayment() and checkout.confirm().
CheckoutOptionsinterfaceConfiguration for xpay.checkout(). Drop-in modal or inline embed.
CheckoutInstanceinterfaceDrop-in checkout handle: open(), close(), destroy(), plus events.
CheckoutCompleteResultinterfacePayload for the drop-in onComplete callback.
InitCheckoutOptionsinterfaceOptions for xpay.initCheckout(). The modern single-call API.
InitCheckoutResulttypeSession data merged with action methods (confirm, promo codes, etc.).
CheckoutActionsinterfaceThe action methods that ride on the checkout object.
CheckoutSessiontypeThe session data shape: amount, currency, status, payment methods, line items.
ActionResulttypeTagged union: { type: "success", session } or { type: "error", error }.
XPayErrorinterfaceUnified error type across every SDK action.
AppearancetypeBranding overrides for the embedded UI (color mode, border style, colors, font).
PaymentElementChangeEventinterfacePayload for PaymentElement change events.
ElementsReadyEventinterfacePayload for the Elements "ready" event.
ElementsLoadErrorEventinterfacePayload for the Elements "loaderror" event.
CustomerDetails, AddressinterfaceShapes for customer fields collected by your form and passed at confirm time.
PaymentMethodInfotypeInformation about an available payment method on the session.
SessionStatustypeTagged union: open, expired, or complete.

loadXPay(publishableKey)

Loads the SDK runtime from CDN and returns an XPayInstance. Call this once at module level, not inside a component.

import { loadXPay } from "@xpay/sdk-js";

const xpayPromise = loadXPay("pk_test_...");
// later, when you have a clientSecret:
const xpay = await xpayPromise;
const elements = xpay.elements({ clientSecret: "cs_test_..." });
ParameterTypeDescription
publishableKeystringYour publishable API key (pk_test_... or pk_live_...).

Returns Promise<XPayInstance | null>. null is returned during server-side rendering (no window). The XPayProvider from @xpay/sdk-react handles null gracefully by retrying on the client.

The runtime is fetched once; subsequent loadXPay calls reuse the same script tag. If a script with sdk.js is already on the page, it isn't re-injected.

XPayInstance

The factory you get back from loadXPay. Four methods.

interface XPayInstance {
  elements(options: ElementsOptions): Elements;
  checkout(options: CheckoutOptions): CheckoutInstance;
  confirmPayment(options: ConfirmPaymentOptions): Promise<ActionResult>;
  initCheckout(options: InitCheckoutOptions): Promise<InitCheckoutResult>;
}

elements(options)

Creates an Elements instance for custom checkout UI. Pass it the clientSecret from a Checkout Session.

const elements = xpay.elements({
  clientSecret: "cs_test_...",
  appearance: { colorMode: "dark", borderStyle: "rounded" },
  locale: "en",
});

ElementsOptions:

FieldTypeDescription
clientSecretstring | Promise<string>Required. The Checkout Session client secret. Can be a Promise.
appearanceAppearanceOptional. UI overrides merged with the session's server-side branding.
locale"en" | "ar"Optional. Defaults to "en".

checkout(options)

Creates a drop-in checkout instance. See CheckoutOptions below.

confirmPayment(options)

Submits a payment using the data collected by Elements. See ConfirmPaymentOptions below.

initCheckout(options)

Modern single-call API: returns the session data and action methods together. See InitCheckoutOptions below.

Elements

Returned by xpay.elements(). Manages one shared payment iframe and exposes session-mutation methods.

interface Elements {
  create(type: "payment"): PaymentElement;
  getElement(type: "payment"): PaymentElement | null;
  fetchPaymentMethods(): Promise<PaymentMethodInfo[]>;

  on(event: "ready" | "change" | "loaderror" | "error", handler): void;
  off(event: string, handler): void;

  applyPromotionCode(code: string): Promise<ActionResult>;
  removePromotionCode(): Promise<ActionResult>;
  updateLineItemQuantity(args: { lineItem: string; quantity: number }): Promise<ActionResult>;
  submit(): Promise<{ error?: XPayError; selectedPaymentMethod?: string }>;
  fetchUpdates(): Promise<ActionResult>;
  changeAppearance(appearance: Appearance): void;
  destroy(): void;
}

Events

EventHandler signatureFires when
"ready"(data: ElementsReadyEvent) => voidSession is loaded and elements are mountable. Fires immediately if already loaded.
"change"(session: CheckoutSession) => voidSession data changes (payment method selection, promo codes, fee recalculations).
"loaderror"(data: ElementsLoadErrorEvent) => voidSession fails to load (network error, invalid client secret, API error).
"error"(error: XPayError) => voidUnsolicited error not triggered by a merchant action (e.g. session expired during a fee recalculation).

Methods

  • create("payment", options?): returns a PaymentElement you can mount.
  • getElement("payment"): returns the existing element or null if none was created.
  • fetchPaymentMethods(): returns the list of PaymentMethodInfo the session supports.
  • applyPromotionCode(code): applies a promotion code, returns ActionResult.
  • removePromotionCode(): removes the applied code, returns ActionResult.
  • updateLineItemQuantity({ lineItem, quantity }): updates a line item, returns ActionResult.
  • submit(): validates element fields. Returns either an error or the selectedPaymentMethod type string.
  • fetchUpdates(): re-fetches the session from the server.
  • changeAppearance(appearance): updates branding at runtime without recreating elements.
  • destroy(): tears down the instance and frees resources.

PaymentElement

The full payment-method selector with the card form, BNPL, kiosk, and wallet methods. Get one from elements.create("payment").

interface PaymentElement {
  mount(container: string | HTMLElement): void;
  unmount(): void;
  destroy(): void;
  focus(): void;
  blur(): void;
  collapse(): void;

  on(event: "ready" | "loaderstart" | "loaderror", handler): void;
  off(event: string, handler): void;
}

PaymentElementChangeEvent is the payload for the parent Elements "change" event when triggered by a payment-method change:

FieldTypeDescription
elementType"payment"Always "payment" for this element.
emptybooleanWhether all card fields are empty.
completebooleanWhether the form is complete and ready to submit.
collapsedbooleanWhether the method selector is collapsed (no method selected).
value{ type: string }The currently selected payment method type.
sessionCheckoutSessionLatest session snapshot.

ConfirmPaymentOptions

Shape passed to xpay.confirmPayment() and checkout.confirm().

FieldTypeDescription
elementsElementsRequired (for xpay.confirmPayment). The Elements instance managing the form. checkout.confirm injects this for you.
customerDetailsCustomerDetailsOptional. Customer fields collected by your form.
customFieldsRecord<string, string | number | boolean>Optional. Custom-field values for the session.
deviceFingerprint{ visitorId: string; confidence?: number }Optional. Device fingerprint for fraud detection.
paymentMethodstringOptional. Override the selected payment method type.
redirect"if_required" | "always"Default "if_required". Controls post-payment navigation.
returnUrlstringOptional. Override the session's afterCompletion.redirect.url.

redirect semantics:

  • "if_required" returns the result to your code; only redirects when the payment method requires it (e.g. 3-D Secure, BNPL).
  • "always" always redirects to returnUrl after payment. The page navigates away and the function never returns on success.

CheckoutOptions

Configuration for the drop-in xpay.checkout().

FieldTypeDescription
clientSecretstringRequired. The Checkout Session client secret.
mode"modal" | "inline""modal" (default) renders an overlay; "inline" embeds in container.
containerstring | HTMLElementRequired for inline mode. CSS selector or DOM node to embed in.
appearanceAppearanceUI overrides merged with the session's branding.
locale"en" | "ar"UI locale. Defaults to "en".
onComplete(result: CheckoutCompleteResult) => voidCalled when payment completes successfully.
onClose() => voidCalled when the modal closes.
onReady(session: CheckoutSession) => voidCalled when the session loads and the UI is ready.
onConfirmed() => voidCalled when the customer confirms payment, before the final result.
onError(error: CheckoutError) => voidCalled when an error occurs.

CheckoutInstance

Returned by xpay.checkout(). Imperative handle.

interface CheckoutInstance {
  open(): void;     // modal mode
  close(): void;
  destroy(): void;
  on(event: "complete" | "close" | "ready" | "confirmed" | "error", handler): void;
  off(event: string, handler): void;
}

CheckoutCompleteResult (the payload for onComplete):

FieldTypeDescription
status"succeeded"Always "succeeded" for this callback.
paymentIntentIdstringThe Payment Intent ID for server-side verification.
chargeIdstringOptional. The Charge ID, when available.
redirectUrlstringOptional. The session's after-completion redirect URL.

InitCheckoutOptions

Modern single-call API. Combines elements() with session loading and exposes session data plus action methods on a single object.

const checkout = await xpay.initCheckout({ clientSecret: "cs_test_..." });
console.log(checkout.amountTotal); // session field
const result = await checkout.confirm({ customerDetails: { email } });
FieldTypeDescription
clientSecretstring | Promise<string>Required. The session client secret.
appearanceAppearanceOptional. UI overrides.
locale"en" | "ar"Optional. Defaults to "en".

InitCheckoutResult is CheckoutSession & CheckoutActions. The action methods on CheckoutActions:

MethodWhat it does
confirm(options?)Confirms the payment. Returns ActionResult.
applyPromotionCode(code)Applies a code. Returns ActionResult.
removePromotionCode()Removes the applied code. Returns ActionResult.
updateLineItemQuantity({ lineItem, quantity })Updates a line item quantity. Returns ActionResult.
submit()Validates fields. Returns { error?, selectedPaymentMethod? }.
fetchUpdates()Re-fetches the session from the server. Returns ActionResult.
changeAppearance(appearance)Updates branding at runtime.
on(event, handler)Listen for "change", "error", or a custom event.
getElements()Returns the underlying Elements for element creation.

CheckoutSession (data type)

Session data exposed to the merchant. Derived from the server's response, trimmed to the merchant-facing fields.

FieldTypeDescription
idstringThe cs_* session ID.
amountSubtotalnumberSubtotal in minor units (e.g. 50000 for 500.00 EGP).
amountTotalnumberTotal in minor units after fees, taxes, and discounts.
currencystringISO currency code (e.g. "EGP").
merchantNamestringYour business display name.
livemodebooleantrue for live keys; false for test mode.
expiresAtstringISO timestamp when the session expires.
statusSessionStatusTagged union: open, expired, complete.
canConfirmbooleanWhether the session can currently be confirmed.
paymentMethodsPaymentMethodInfo[]Available payment methods on this session.
lineItemsCheckoutLineItem[]Line items.
totalDetailsCheckoutTotalDetailsSubtotal, tax, shipping, discount breakdown.
feesCheckoutFeesFee breakdown when feesPassThrough is on.
discountsCheckoutDiscount[]Applied promotion codes.

SessionStatus:

type SessionStatus =
  | { type: "open" }
  | { type: "expired" }
  | { type: "complete"; paymentStatus: "paid" | "unpaid" | "no_payment_required" };

PaymentMethodInfo:

FieldTypeDescription
typestringMethod type ("card", "valu", "fawry").
displayNamestringLocalized label ("Card", "ValU", "Fawry").
category"card" | "bnpl" | "kiosk" | "wallet"Bucket for UI grouping.
iconstringOptional icon URL.
nextActionTextstringOptional. Description of the next step shown to the customer.

ActionResult and XPayError

Every action that mutates the session returns an ActionResult. It's a tagged union, so narrow by result.type before reading the payload.

type ActionResult<E = XPayError> =
  | { type: "success"; session: CheckoutSession }
  | { type: "error"; error: E };

XPayError is the unified error shape. Payment-specific fields are null for non-payment errors.

FieldTypeDescription
typestringError category: "card_error", "invalid_request_error", "api_error".
codestring | nullMachine-readable code ("card_declined", "promotion_code_not_found").
messagestringHuman-readable message.
paramstring | nullParameter that caused the error (e.g. "promotionCode").
docUrlstring | nullDocumentation URL for this error code.
declineCodestring | nullDecline detail like "insufficient_funds". Null for non-payment errors.
adviceCodestring | nullRetry advice: "try_again_later", "do_not_try_again", "confirm_card_data".
chargeIdstring | nullFailed charge ID.
paymentMethodIdstring | nullFailed payment method ID.
paymentMethodTypestring | nullPayment method type ("card", "valu").
paymentMethodRecord<string, unknown> | nullPayment method snapshot at failure time.

For a guide on handling API errors and the three error code spaces, see Errors, API error codes, Payment error codes, and Decline codes.

Appearance

Branding overrides for the embedded UI. Mirrors a subset of the merchant-default fields you set in Branding settings.

FieldValues
colorMode"system" | "light" | "dark"
borderStyle"rounded" | "sharp" | "pill"
spacing"condensed" | "normal" | "spacious"
inputSize"small" | "medium" | "large"
inputStyle"outlined" | "flat" | "filled"
formLayout"compact" | "spacious"
colorsObject with twelve semantic tokens (primary, foreground, background, muted, accent, border, input, ring, destructive, plus the foreground pairs).
fontFamilyCSS font-family string.

Pass an Appearance to xpay.elements(), xpay.checkout(), or xpay.initCheckout(). Or call elements.changeAppearance() / checkout.changeAppearance() to update at runtime.

CustomerDetails and Address

Shapes for customer fields you collect on your form and pass at confirm time.

interface CustomerDetails {
  email?: string;
  name?: string;
  phone?: string;
  billingDetails?: { name?: string; email?: string; phone?: string; address?: Address };
  shipping?: { name?: string; phone?: string; address?: Address };
}

interface Address {
  line1?: string;
  line2?: string;
  city?: string;
  state?: string;
  postalCode?: string;
  country?: string;
}

For the developer-side cross-reference on what each Checkout Session field controls (collection toggles, custom fields, prefill priority), see Customer lifecycle.

Where to next

On this page