Type Definitions
Every public type of the Bahn Web SDK, exactly as the SDK declares it. Each SDK Reference and Payment Flows page links here for the full shape of a parameter or result.
Use the types in your project
The SDK loads as a plain <script>, so there is no package to install types from. Download the declaration file instead:
Save it in your project (for example as types/bahn.d.ts) and make sure your tsconfig.json include covers it. It declares the Bahn global, window.BahnCake, and every type below under the Bahn namespace — no import needed:
const bahn = new Bahn({ pk: "pk_test_...", environment: "sandbox" });
const options: Bahn.CardMountOptions = {
layout: { columns: 1 },
allowedSchemes: ["visa", "mastercard"],
};
const card = bahn.mountCard("#card-container", options);
const { payment_intent, three_ds_payload } = await bahn.confirmPayment({ client_secret });
// ^ Record<string, unknown> ^ Bahn.ThreeDSPayloadDecoded | undefinedThe snippets below drop the Bahn. prefix, since they are written inside the namespace.
Amounts
Every amount is in the smallest currency unit — VND as-is, cents for USD.
Bahn class
The global the script defines. A singleton — a second new Bahn() returns the existing instance. See SDK Reference for what each method does.
/** The Bahn SDK. A singleton — a second `new Bahn()` returns the existing instance. */
declare class Bahn {
constructor(options: Bahn.BahnOptions);
getConfig(): Promise<Bahn.BahnConfig>;
mountCard(containerId: string, options?: Bahn.CardMountOptions): Bahn.CardComponent;
mountPaymentQR(selector: string, clientSecret: string, options?: Bahn.QRMountOptions): Bahn.IQRComponent;
isApplePayAvailable(): Promise<boolean>;
/** Pass `clientSecret` for direct confirmation, `undefined` for the token-based flow. */
mountApplePay(
selector: string,
clientSecret: string | undefined,
options: Bahn.ApplePayButtonOptions,
): Bahn.IApplePayButtonComponent;
unmountApplePay(): void;
readonly applePay: Bahn.IApplePay;
isGooglePayAvailable(): Promise<boolean>;
/** Pass `clientSecret` for direct confirmation, `undefined` for the token-based flow. */
mountGooglePay(
selector: string,
clientSecret: string | undefined,
options: Bahn.GooglePayButtonOptions,
): Bahn.IGooglePayButtonComponent;
unmountGooglePay(): void;
mount3DS(
sessionId: string,
callbacks: Bahn.ThreeDSCallbacks,
options?: Bahn.ThreeDSecureOptions,
): Bahn.IThreeDSecure;
getChallengeRedirectUrl(sessionId: string, returnUrl: string, options?: { brandName?: string }): string;
/** Requires `mountCard()`. Rejects with `Bahn.APIError`. */
confirmPayment(payload: Bahn.ConfirmPaymentPayload): Promise<{
payment_intent: Record<string, unknown>;
/** Present only when 3DS authentication is required. */
three_ds_payload?: Bahn.ThreeDSPayloadDecoded;
}>;
/** Requires `mountCard()`. Rejects with `Bahn.APIError`. */
confirmCardSetup(payload: Bahn.ConfirmCardSetupPayload): Promise<Bahn.ConfirmCardSetupResult>;
/** Requires `mountCard()`. Rejects with `Bahn.APIError`. */
createConfirmationToken(payload: Bahn.CreateConfirmationTokenOptions): Promise<Bahn.ConfirmationTokenResult>;
handleNextAction(input: Bahn.PaymentIntentInput, callbacks: Bahn.HandleNextActionCallbacks): Promise<void>;
pollPaymentIntentStatus(clientSecret: string, callbacks: Bahn.PaymentIntentPollCallbacks): void;
stopPaymentIntentPolling(): void;
pollSetupIntentStatus(clientSecret: string, callbacks: Bahn.PaymentIntentPollCallbacks): void;
stopSetupIntentPolling(): void;
cleanup(): void;
}
interface Window {
Bahn: typeof Bahn;
BahnCake?: Bahn;
}Options & config
Passed to new Bahn() and returned by bahn.getConfig(). See SDK Reference → BahnOptions.
SDKEnvironment
type SDKEnvironment = "sandbox" | "production";BahnOptions
interface BahnOptions {
/** Publishable key, sent as the `X-Bn-Publishable-Key` header. */
pk: string;
/** Target environment — selects the API and iframe domains. */
environment: SDKEnvironment;
/** Tenant app ID for 3DS routing. */
appId?: string;
/** Tenant team ID for 3DS routing. */
teamId?: string;
/** Maximum payment/setup intent polling attempts (default: 10). */
paymentIntentPollAttempts?: number;
}ApplePaySDKConfig
interface ApplePaySDKConfig {
enabled: boolean;
merchant_name: string;
supported_networks: string[];
merchant_capabilities: string[];
}BahnConfig
interface BahnConfig {
apple_pay: ApplePaySDKConfig;
}Billing details & confirmation tokens
Used by createConfirmationToken() and the payment_method.billing_details field of every confirm call. See Token-Based Flow.
ConfirmationTokenAddress
interface ConfirmationTokenAddress {
country?: string;
city?: string;
line1?: string;
line2?: string;
postal_code?: string;
}ConfirmationTokenBillingDetails
interface ConfirmationTokenBillingDetails {
name?: string;
email?: string;
phone?: string;
address?: ConfirmationTokenAddress;
}CreateConfirmationTokenOptions
interface CreateConfirmationTokenOptions {
payment_method?: {
billing_details?: ConfirmationTokenBillingDetails;
};
[key: string]: unknown;
}ConfirmationTokenResult
interface ConfirmationTokenResult {
confirmation_token: string;
}Confirming intents
Payloads, results and callbacks for confirmPayment(), confirmCardSetup(), handleNextAction() and the polling methods. The payment_intent and setup_intent objects are typed as Record<string, unknown> by the SDK — their fields are documented in the API Reference. See Confirm Payment.
ThreeDSPayloadDecoded
/** Decoded 3DS payload returned when an intent needs 3DS authentication. */
interface ThreeDSPayloadDecoded {
/** 3DS provider identifier. */
provider: string;
/** Tenant app ID. */
app_id: string;
/** Tenant team ID. */
team_id: string;
/** 3DS session ID — pass to `mount3DS()` or `getChallengeRedirectUrl()`. */
id: string;
}ConfirmPaymentPayload
interface ConfirmPaymentPayload {
/** Client secret of the payment intent created by your backend. */
client_secret: string;
/** Card details are added by the iframe — never pass them here. */
payment_method?: {
billing_details?: ConfirmationTokenBillingDetails;
};
/** Payment-method-specific options. */
payment_method_options?: Record<string, unknown>;
/** Token from `createConfirmationToken()`. */
confirmation_token?: string;
/** Optional amount override, in the smallest currency unit. */
amount?: string;
}ConfirmCardSetupPayload
interface ConfirmCardSetupPayload {
/** Client secret of the setup intent created by your backend. */
client_secret: string;
/** Card details are added by the iframe — never pass them here. */
payment_method?: {
billing_details?: ConfirmationTokenBillingDetails;
};
/** Payment-method-specific options. */
payment_method_options?: Record<string, unknown>;
}ConfirmCardSetupResult
interface ConfirmCardSetupResult {
setup_intent: Record<string, unknown>;
/** Present only when 3DS authentication is required. */
three_ds_payload?: ThreeDSPayloadDecoded;
}PaymentIntentInput
/**
* Input to `handleNextAction()`: a payment intent `client_secret`, or a
* `payment_intent` object your backend already returned (must include
* `client_secret`).
*/
type PaymentIntentInput = string | (Record<string, unknown> & { client_secret: string });HandleNextActionCallbacks
interface HandleNextActionCallbacks {
onReady?: () => void;
onSuccess?: (paymentIntent: Record<string, unknown>) => void;
/** Receives the failed payment intent, or the 3DS error if the challenge failed. */
onFailure?: (errorOrIntent?: ComponentError | Record<string, unknown>) => void;
onTimeout?: () => void;
onError?: (error: Error) => void;
onProgress?: (attempt: number, maxAttempts: number, status: string) => void;
}PaymentIntentPollCallbacks
/** Shared by payment- and setup-intent polling. */
interface PaymentIntentPollCallbacks {
onSuccess?: (intent: Record<string, unknown>) => void;
onFailure?: (intent: Record<string, unknown>) => void;
onTimeout?: () => void;
onError?: (error: Error) => void;
onProgress?: (attempt: number, maxAttempts: number, status: string) => void;
}3DS
Used by bahn.mount3DS(). ThreeDSErrorCode lists every value ComponentError.code can take. See 3DS Authentication.
ComponentError
interface ComponentError {
/** One of `ThreeDSErrorCode`. */
code: string;
message: string;
}ThreeDSErrorCode
type ThreeDSErrorCode =
| "boot-failed"
| "frame-load-error"
| "session-complete"
| "session-not-found"
| "session-unknown-error"
| "challenge-failed"
| "challenge-cancelled"
| "challenge-aborted"
| "something-went-wrong";ThreeDSCallbacks
interface ThreeDSCallbacks {
onReady?: () => void;
onSuccess: () => void;
onFailure: (error?: ComponentError | Record<string, unknown>) => void;
}ColorScheme
type ColorScheme = "normal" | "light" | "dark" | "only light" | "only dark" | "light dark";ThreeDSecureOptions
interface ThreeDSecureOptions {
/** Color scheme passed to the challenge iframe. */
colorScheme?: ColorScheme;
/** Explicit iframe size (default: full-viewport overlay). */
size?: { width: string; height: string };
/**
* Behavior when the issuer requires a challenge:
* `false` (default) shows it, `true` fails the session without UI,
* a function decides at challenge time.
*/
failOnChallenge?: boolean | (() => boolean | Promise<boolean>);
}ThreeDSecureEvents
interface ThreeDSecureEvents {
ready: () => void;
success: () => void;
failure: (error: ComponentError) => void;
error: (error: ComponentError) => void;
}IThreeDSecure
interface IThreeDSecure {
mount(selector?: string | HTMLElement): this;
unmount(): this;
update(options?: ThreeDSecureOptions): this;
/** Returns an unsubscribe function. */
on<T extends keyof ThreeDSecureEvents>(event: T, callback: ThreeDSecureEvents[T]): () => void;
}Card
Used by bahn.mountCard(). See Card Payments.
CardEventHandler
type CardEventHandler = (data?: unknown) => void;CardComponent
interface CardComponent {
mount(selector: string): void;
unmount(): void;
on(event: string, handler: CardEventHandler): void;
validate(): void;
/** Re-apply labels/placeholders without remounting (e.g. on language switch). */
applyConfig(fields: NonNullable<CardMountOptions["fields"]>, inputStyle?: CardInputStyle): void;
/** Re-apply base/focus/invalid styles without remounting. */
applyStyles(stateStyles: CardStateStyles): void;
/** Validity state only — card values never leave the iframes. */
readonly values: {
isComplete: boolean;
isValid: boolean;
errors?: Record<string, string>;
};
}CardInputStyle
/** Allowlisted input styles — any other property is dropped. */
interface CardInputStyle {
color?: string;
backgroundColor?: string;
fontSize?: string;
fontFamily?: string;
fontWeight?: string;
fontStyle?: string;
lineHeight?: string;
letterSpacing?: string;
textAlign?: string;
borderRadius?: string;
border?: string;
borderColor?: string;
borderWidth?: string;
padding?: string;
paddingTop?: string;
paddingBottom?: string;
paddingLeft?: string;
paddingRight?: string;
height?: string;
opacity?: string;
boxShadow?: string;
caretColor?: string;
}CardStateStyles
interface CardStateStyles {
/** Reasserted on blur. */
base?: CardInputStyle;
/** Applied while the field has focus. */
focus?: CardInputStyle;
/** Applied on blur when the field fails validation. */
invalid?: CardInputStyle;
}CardLayoutConfig
interface CardLayoutConfig {
/** 2 (default): number on row 1, expiry | cvc on row 2. 1: one field per row. */
columns?: 1 | 2;
/** Gap between all fields (default: "8px"). */
gap?: string;
columnGap?: string;
rowGap?: string;
/** Height of the card-number iframe (defaults to `fieldHeight`). */
cardNumberHeight?: string;
/** Height of the expiry/cvc iframes (default: "92px"). */
fieldHeight?: string;
}CardScheme
type CardScheme = "visa" | "mastercard" | "amex" | "jcb" | "discover" | "diners" | "unionpay";CardLogoScheme
/** Schemes with built-in logo artwork for `customLogos`. */
type CardLogoScheme = "visa" | "mastercard" | "jcb";CardFieldConfig
interface CardFieldConfig {
label?: string;
placeholder?: string;
/**
* number: keyed by `incomplete_number` | `invalid_number`.
* expiry: keyed by `incomplete_expiry` | `invalid_expiry_month` | `invalid_expiry_year`.
* cvc: a plain string.
*/
errorMsg?: Record<string, string> | string;
/** Help (?) tooltip — `cvc` only. */
tooltip?: boolean;
/** Hide the brand logos inside the input — `number` only. */
hideLogo?: boolean;
}CardNumberConfig
interface CardNumberConfig extends CardFieldConfig {
/** Fixed set of logos, shown regardless of the detected scheme. */
customLogos?: Array<CardLogoScheme | CustomLogoSvg>;
}CardMountOptions
interface CardMountOptions {
fields?: {
number?: CardNumberConfig;
expiry?: CardFieldConfig;
cvc?: CardFieldConfig;
};
layout?: CardLayoutConfig;
inputStyle?: CardInputStyle;
stateStyles?: CardStateStyles;
/** Reveal each CVV digit for ~500ms before masking (default: false). */
cvvPeek?: boolean;
/** Treat card numbers from other schemes as invalid. */
allowedSchemes?: CardScheme[];
}RectProps
interface RectProps {
type: "rect";
x: string;
y: string;
width: string;
height: string;
rx?: string;
fill?: string;
stroke?: string;
}PathProps
interface PathProps {
type: "path";
d: string;
fill?: string;
fillRule?: "nonzero" | "evenodd";
clipRule?: "nonzero" | "evenodd";
}GProps
interface GProps {
type: "g";
/** Local fragment references (`url(#id)`) only. */
clipPath?: string;
children: SVGChildProps[];
}SVGChildProps
type SVGChildProps = RectProps | PathProps | GProps;CustomLogoSvg
interface CustomLogoSvg {
width: string;
height: string;
fill?: string;
viewBox: string;
children: SVGChildProps[];
}QR
Used by bahn.mountPaymentQR(). See QR Payments.
QRStyle
interface QRStyle {
dotsOptions?: {
color?: string;
type?: "square" | "dots" | "rounded" | "extra-rounded" | "classy" | "classy-rounded";
};
backgroundOptions?: {
color?: string;
};
cornersSquareOptions?: {
color?: string;
type?: "dot" | "square" | "extra-rounded";
};
}QRMountOptions
interface QRMountOptions {
/** Iframe height (default: "300px"). */
height?: string;
/** Polling interval in ms (default: 3000, minimum: 1000). Negative disables polling. */
pollIntervalMs?: number;
qrStyle?: QRStyle;
}QREventHandler
type QREventHandler = (data?: unknown) => void;IQRComponent
interface IQRComponent {
unmount(): void;
on(event: "ready" | "payment:success" | "payment:failed" | "payment:error", handler: QREventHandler): void;
off(event: "ready" | "payment:success" | "payment:failed" | "payment:error", handler: QREventHandler): void;
download(name?: string): void;
}Apple Pay
Used by bahn.mountApplePay() and bahn.applePay. See Apple Pay.
ApplePayCardNetwork
type ApplePayCardNetwork = "amex" | "discover" | "interac" | "jcb" | "masterCard" | "privateLabel" | "visa";ApplePayMerchantCapability
type ApplePayMerchantCapability = "supports3DS" | "supportsCredit" | "supportsDebit";ApplePayButtonType
type ApplePayButtonType =
| "add-money"
| "book"
| "buy"
| "check-out"
| "continue"
| "contribute"
| "donate"
| "order"
| "pay"
| "plain"
| "reload"
| "rent"
| "set-up"
| "subscribe"
| "support"
| "tip"
| "top-up";ApplePayButtonStyle
type ApplePayButtonStyle = "black" | "white" | "white-outline";ApplePayShippingMethod
interface ApplePayShippingMethod {
/** Echoed back in `"shippingmethodselected"`. */
identifier: string;
label: string;
detail?: string;
/** Smallest currency unit (0 for free shipping). */
amount: number;
}ApplePayShippingContact
/** Coarse address — no street-level fields until the payment is authorized. */
interface ApplePayShippingContact {
city?: string;
state?: string;
postalCode?: string;
country?: string;
countryCode?: string;
}ApplePayShippingContactUpdate
interface ApplePayShippingContactUpdate {
shippingMethods?: ApplePayShippingMethod[];
lineItems?: Array<{ label: string; amount: number }>;
amount?: number;
}ApplePayShippingMethodUpdate
interface ApplePayShippingMethodUpdate {
lineItems?: Array<{ label: string; amount: number }>;
amount?: number;
}ApplePayShippingContactSelectedEvent
interface ApplePayShippingContactSelectedEvent {
contact: ApplePayShippingContact;
resolve: (update: ApplePayShippingContactUpdate) => void;
reject: () => void;
}ApplePayShippingMethodSelectedEvent
interface ApplePayShippingMethodSelectedEvent {
shippingMethod: ApplePayShippingMethod;
resolve: (update: ApplePayShippingMethodUpdate) => void;
reject: () => void;
}ApplePayButtonOptions
interface ApplePayButtonOptions {
/** Smallest currency unit. */
amount: number;
/** ISO 4217, e.g. "VND". */
currency: string;
/** ISO 3166-1 alpha-2, e.g. "VN". */
country: string;
priceLabel?: string;
lineItems?: Array<{ label: string; amount: number }>;
/** Defaults to your merchant's configured value. */
merchantName?: string;
/** Default: "plain". */
type?: ApplePayButtonType;
/** Default: "black". */
style?: ApplePayButtonStyle;
/** Default: "en". */
locale?: string;
/** Pixels (default: 4). */
borderRadius?: number;
/** Default: 100% width, 48px height. */
size?: { width?: string | number; height?: string | number };
/** Defaults to your merchant's configured value. */
supportedNetworks?: ApplePayCardNetwork[];
/** Defaults to your merchant's configured value. */
merchantCapabilities?: ApplePayMerchantCapability[];
requestBillingAddress?: boolean;
requestPayerDetails?: ("name" | "email" | "phone")[];
/** Requires a `"shippingcontactselected"` listener. */
requestShipping?: boolean;
shippingMethods?: ApplePayShippingMethod[];
}IApplePayButtonComponent
interface IApplePayButtonComponent {
unmount(): void;
/** Returns an unsubscribe function. */
on(
event: "ready" | "success" | "token" | "error" | "cancel" | "shippingcontactselected" | "shippingmethodselected",
handler: (data?: unknown) => void,
): () => void;
}ApplePayValidateMerchantResult
interface ApplePayValidateMerchantResult {
/** Pass to `session.completeMerchantValidation()`. */
merchant_session: Record<string, unknown>;
}ApplePayConfirmPaymentPayload
interface ApplePayConfirmPaymentPayload {
client_secret: string;
/** `event.payment.token` from `onpaymentauthorized`, as-is. */
token: Record<string, unknown>;
billing_details?: ConfirmationTokenBillingDetails;
}ApplePayConfirmPaymentResult
interface ApplePayConfirmPaymentResult {
payment_intent: Record<string, unknown>;
three_ds_payload?: ThreeDSPayloadDecoded;
}ApplePayCreateConfirmationTokenPayload
interface ApplePayCreateConfirmationTokenPayload {
/** `event.payment.token` from `onpaymentauthorized`, as-is. */
token: Record<string, unknown>;
billing_details?: ConfirmationTokenBillingDetails;
}IApplePay
/** `bahn.applePay` — backend calls for a hand-rolled `ApplePaySession`. */
interface IApplePay {
validateMerchant(validationURL: string): Promise<ApplePayValidateMerchantResult>;
confirmPayment(payload: ApplePayConfirmPaymentPayload): Promise<ApplePayConfirmPaymentResult>;
createConfirmationToken(payload: ApplePayCreateConfirmationTokenPayload): Promise<ConfirmationTokenResult>;
}Google Pay
Used by bahn.mountGooglePay(). See Google Pay.
GooglePayCardNetwork
type GooglePayCardNetwork = "AMEX" | "DISCOVER" | "INTERAC" | "JCB" | "MASTERCARD" | "VISA";GooglePayAuthMethod
type GooglePayAuthMethod = "PAN_ONLY" | "CRYPTOGRAM_3DS";GooglePayButtonType
type GooglePayButtonType = "book" | "buy" | "checkout" | "donate" | "order" | "pay" | "plain" | "subscribe";GooglePayButtonColor
type GooglePayButtonColor = "black" | "white";GooglePayShippingOption
interface GooglePayShippingOption {
/** Echoed back in `"shippingoptionchanged"`. */
id: string;
label: string;
description?: string;
/** Smallest currency unit (0 for free shipping). */
amount: number;
}GooglePayShippingAddress
/** Coarse address — no street-level fields until the payment is authorized. */
interface GooglePayShippingAddress {
locality?: string;
administrativeArea?: string;
postalCode?: string;
countryCode?: string;
}GooglePayShippingAddressUpdate
interface GooglePayShippingAddressUpdate {
shippingOptions?: GooglePayShippingOption[];
lineItems?: Array<{ label: string; amount: number }>;
amount?: number;
}GooglePayShippingOptionUpdate
interface GooglePayShippingOptionUpdate {
lineItems?: Array<{ label: string; amount: number }>;
amount?: number;
}GooglePayShippingAddressChangedEvent
interface GooglePayShippingAddressChangedEvent {
address: GooglePayShippingAddress;
resolve: (update: GooglePayShippingAddressUpdate) => void;
reject: () => void;
}GooglePayShippingOptionChangedEvent
interface GooglePayShippingOptionChangedEvent {
shippingOption: GooglePayShippingOption;
resolve: (update: GooglePayShippingOptionUpdate) => void;
reject: () => void;
}GooglePayButtonOptions
interface GooglePayButtonOptions {
/** Smallest currency unit. */
amount: number;
/** ISO 4217, e.g. "VND". */
currency: string;
/** ISO 3166-1 alpha-2, e.g. "VN". */
country: string;
priceLabel?: string;
lineItems?: Array<{ label: string; amount: number }>;
merchantName?: string;
/** Default: "pay". */
type?: GooglePayButtonType;
/** Default: "black". */
color?: GooglePayButtonColor;
/** Default: "en". */
locale?: string;
/** Default: 100% width, 48px height. */
size?: { width?: string | number; height?: string | number };
/** Default: every network. */
allowedCardNetworks?: GooglePayCardNetwork[];
/** Default: PAN_ONLY, CRYPTOGRAM_3DS. */
allowedAuthMethods?: GooglePayAuthMethod[];
requestBillingAddress?: boolean;
requestPayerDetails?: ("email" | "phone")[];
/** Requires a `"shippingaddresschanged"` listener. */
requestShipping?: boolean;
shippingOptions?: GooglePayShippingOption[];
}IGooglePayButtonComponent
interface IGooglePayButtonComponent {
unmount(): void;
/** Returns an unsubscribe function. */
on(
event: "ready" | "success" | "token" | "error" | "cancel" | "shippingaddresschanged" | "shippingoptionchanged",
handler: (data?: unknown) => void,
): () => void;
}Errors
Every promise-returning method rejects with an APIError. The script build doesn't expose the APIError class itself, so check error.name === "APIError" rather than instanceof. The SDK's methods don't set code today, so branch on status and isUserError. See Error Handling.
APIError
interface APIError extends Error {
readonly name: "APIError";
/** HTTP status, or 0 for client-side and network errors. */
readonly status: number;
/** true when the message is safe to show to the shopper. */
readonly isUserError: boolean;
/** Not set by the Web SDK's methods today — branch on `status` and `isUserError`. */
readonly code?: string;
}