API Reference
ZatlasCardCapture
Section titled “ZatlasCardCapture”The main entry point for the SDK. Create an instance before mounting any card elements.
Constructor
Section titled “Constructor”import { ZatlasCardCapture } from '@zatlas/card-capture';
const zatlas = new ZatlasCardCapture({ publishableKey: 'pk_sandbox_your_key', locale: 'es-MX',});| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
publishableKey | string | Yes | — | Your publishable key. Starts with pk_sandbox_ in sandbox or pk_live_ in production. Identifies your account and determines the environment. |
locale | string | No | 'es-MX' | BCP 47 locale for labels, placeholders, error messages, and the CTA button. Supported: 'es-MX', 'es-ES', 'en-US', 'en-GB', 'pt-BR'. |
theme | object | No | defaultTheme | Theme object to customize the card form appearance. See Themes and the Theming Guide. |
Zatlas() factory
Section titled “Zatlas() factory”If you prefer a functional style, the named export Zatlas returns the same instance:
import { Zatlas } from '@zatlas/card-capture';
const zatlas = Zatlas({ publishableKey: 'pk_sandbox_your_key',});Zatlas(options) is equivalent to new ZatlasCardCapture(options).
create()
Section titled “create()”Creates a card element that can be mounted into the DOM. The element renders a secure iframe containing the card form (number, expiry, CVC, and cardholder name).
const card = zatlas.create('card', { mode: 'checkout', // or 'tokenize' showCardholderName: true, showPostalCode: false,});| Option | Type | Required | Default | Description |
|---|---|---|---|---|
mode | 'checkout' | 'tokenize' | Yes | — | Determines the CTA label and SDK behavior. 'checkout' shows “Continuar” and expects a checkout() call. 'tokenize' shows “Guardar metodo” and expects a createToken() call. |
showCardholderName | boolean | No | true | Show the cardholder name field inside the iframe. |
showPostalCode | boolean | No | false | Show a postal code field inside the iframe. Required by some acquirers for US-issued cards. |
Returns a MountedElement.
MountedElement
Section titled “MountedElement”The object returned by create(). Use it to mount the card form into the DOM, listen for events, and clean up when done.
Mounting
Section titled “Mounting”Pass a CSS selector or an HTMLElement:
// CSS selectorcard.mount('#card-element');
// Direct element referenceconst container = document.getElementById('card-element');card.mount(container);The SDK injects an iframe into the target element. The iframe auto-resizes to fit its contents.
Cleanup
Section titled “Cleanup”Always unmount when navigating away or destroying the component to avoid memory leaks:
card.unmount();In React, this is handled automatically by <CardElement /> (see React).
Methods
Section titled “Methods”| Method | Signature | Description |
|---|---|---|
mount | mount(target: string | HTMLElement): void | Injects the iframe into the given DOM element. Throws if the element is not found. |
unmount | unmount(): void | Removes the iframe from the DOM and tears down internal listeners. Safe to call multiple times. |
on | on(event: string, handler: Function): void | Subscribes to an event. |
off | off(event: string, handler: Function): void | Unsubscribes a previously registered handler. |
destroy | destroy(): void | Alias for unmount(). Removes iframe and cleans up. |
focus | focus(): void | Programmatically focuses the card number field inside the iframe. |
blur | blur(): void | Programmatically blurs the currently focused field inside the iframe. |
clear | clear(): void | Clears all fields inside the iframe and resets validation state. |
Events
Section titled “Events”Subscribe to events with card.on(event, handler). All events are emitted from the MountedElement instance.
Fired once the iframe has loaded and the card form is interactive. Use this to hide a loading spinner or enable surrounding UI.
card.on('ready', () => { document.getElementById('spinner').style.display = 'none'; document.getElementById('pay-section').style.opacity = '1';});change
Section titled “change”Fired whenever the guest types or the validation state changes. The handler receives a payload describing the current form state.
card.on('change', (event) => { console.log(event.complete); // true when all fields are valid console.log(event.error); // validation error, if any console.log(event.brand); // detected card brand});Payload fields:
| Field | Type | Description |
|---|---|---|
complete | boolean | true when all fields pass validation and the form is ready to submit. |
empty | boolean | true when all fields are empty. |
brand | string | null | Detected card brand: 'visa', 'mastercard', 'amex', 'discover', or null if not yet identified. |
error | { code: string, message: string } | null | Current validation error, or null if the form is valid. See Validation errors. |
cta_clicked
Section titled “cta_clicked”Fired when the guest clicks the CTA button inside the iframe (“Continuar” in checkout mode, “Guardar metodo” in tokenize mode). This is where you call checkout() or createToken().
// 1. Get a fresh access token from your serverconst { accessToken } = await fetch('/api/payment-token').then(r => r.json());
card.on('cta_clicked', async () => { // 2. Process the payment const { payment, error } = await zatlas.checkout({ accessToken, amount: 25000, currency: 'mxn', reservationId: 'RES-456', });
// 3. Handle the result if (payment) { showConfirmation(payment.id); } else { console.error(`Payment failed: ${error.code} - ${error.message}`); }});The SDK automatically shows a loading spinner inside the iframe while your async handler is running.
Fired when any field inside the iframe receives focus.
card.on('focus', (event) => { console.log(`Field focused: ${event.field}`); // event.field is 'cardNumber', 'expiry', 'cvc', or 'cardholderName'});Fired when any field inside the iframe loses focus. Useful for triggering your own validation UI.
card.on('blur', (event) => { console.log(`Field blurred: ${event.field}`); if (!event.complete) { highlightContainer('warning'); }});Fired when a non-recoverable error occurs inside the iframe (e.g. network failure loading the form). This is different from validation errors in the change event.
card.on('error', (event) => { console.error('Iframe error:', event.code, event.message); showFallbackUI();});checkout()
Section titled “checkout()”Processes a full payment using the card data captured in the iframe. The SDK tokenizes the card, creates the payment, handles installment selection (MSI) and 3D Secure automatically, and polls for the final result.
const { accessToken } = await fetch('/api/payment-token').then(r => r.json());
card.on('cta_clicked', async () => { const { payment, error } = await zatlas.checkout({ accessToken, amount: 50000, currency: 'mxn', reservationId: 'RES-789', description: 'Suite Deluxe - 2 nights', installments: { required: true }, metadata: { bookingRef: 'BK-001' }, });
if (payment) { // payment.id — 'pay_...' // payment.status — 'succeeded' // payment.amount — 50000 window.location.href = `/confirmation?payment=${payment.id}`; } else { console.error(error.code, error.message); }});CheckoutOptions
Section titled “CheckoutOptions”| Option | Type | Required | Default | Description |
|---|---|---|---|---|
accessToken | string | Yes | — | OAuth2 access token from your server. Short-lived (1 hour). |
amount | number | Yes | — | Payment amount in currency units (e.g. 12000 = $12,000.00 MXN). |
currency | string | Yes | — | Three-letter ISO 4217 currency code, lowercase. Example: 'mxn', 'usd'. |
reservationId | string | Yes | — | Your reservation or booking identifier. Used for reconciliation. |
description | string | No | undefined | Human-readable description shown on the guest’s card statement (if supported by the acquirer). |
installments | { required: boolean } | No | undefined | Pass { required: true } to show the installment (MSI) picker inside the iframe. The guest selects 3, 6, 9, 12, 18, or 24 months. Omit or set to undefined for single payment. |
metadata | Record<string, string> | No | undefined | Arbitrary key-value pairs attached to the payment. Useful for internal references. Max 20 keys, 500 chars per value. |
CheckoutResult
Section titled “CheckoutResult”// On successtype CheckoutSuccess = { payment: { id: string; // 'pay_...' methodId: string; // 'mth_...' — reusable for future charges status: 'succeeded'; amount: number; currency: string; installments?: { count: number; perInstallment: number }; // null if single payment card: { brand: string; // 'visa', 'mastercard', etc. last4: string; // '4242' expMonth: number; // 12 expYear: number; // 2030 }; createdAt: string; // ISO 8601 }; error: null;};
// On failuretype CheckoutFailure = { payment: null; error: { code: string; // e.g. 'card_declined', 'insufficient_funds' message: string; // human-readable, localized declineCode?: string; // raw decline code from the acquirer, if available };};
type CheckoutResult = CheckoutSuccess | CheckoutFailure;createToken()
Section titled “createToken()”Tokenizes the card data captured in the iframe and returns a reusable mth_* payment method token. Your server stores this token and charges later via the Payments API.
const { accessToken } = await fetch('/api/payment-token').then(r => r.json());
card.on('cta_clicked', async () => { const { token, error } = await zatlas.createToken({ accessToken, currency: 'mxn', metadata: { guestId: 'G-42' }, });
if (token) { // token.id — 'mth_...' // token.card — { brand, last4, expMonth, expYear } await fetch('/api/save-method', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ methodId: token.id, brand: token.card.brand, last4: token.card.last4, }), }); showSuccess('Card saved'); } else { console.error(error.code, error.message); }});TokenCreateOptions
Section titled “TokenCreateOptions”| Option | Type | Required | Default | Description |
|---|---|---|---|---|
accessToken | string | Yes | — | OAuth2 access token from your server. |
currency | string | Yes | — | Three-letter ISO 4217 currency code. Used to validate the card against the correct acquirer. |
metadata | Record<string, string> | No | undefined | Arbitrary key-value pairs attached to the payment method. Max 20 keys, 500 chars per value. |
TokenResult
Section titled “TokenResult”// On successtype TokenSuccess = { token: { id: string; // 'mth_...' card: { brand: string; // 'visa', 'mastercard', etc. last4: string; // '4242' expMonth: number; // 12 expYear: number; // 2030 }; createdAt: string; // ISO 8601 }; error: null;};
// On failuretype TokenFailure = { token: null; error: { code: string; // e.g. 'card_declined', 'invalid_card_number' message: string; // human-readable, localized };};
type TokenResult = TokenSuccess | TokenFailure;updateTheme()
Section titled “updateTheme()”Changes the visual theme of the card form at runtime without remounting. Useful for toggling between light and dark modes.
// Switch to dark themeimport { darkTheme } from '@zatlas/card-capture';zatlas.updateTheme(darkTheme);
// Switch back to defaultimport { defaultTheme } from '@zatlas/card-capture';zatlas.updateTheme(defaultTheme);You can also pass a partial theme object — only the properties you include are updated:
zatlas.updateTheme({ colors: { primary: '#1a73e8', borderFocus: '#1a73e8', background: '#f9fafb', }, borders: { radius: '12px', },});See the Theming Guide for the full list of customizable properties.
Error codes
Section titled “Error codes”Errors returned by checkout() and createToken() fall into three categories.
Decline errors
Section titled “Decline errors”Returned when the card issuer or acquirer rejects the transaction. These are shown to the guest inside the iframe automatically.
| Code | Description | Recoverable |
|---|---|---|
card_declined | Generic decline. The issuer did not provide a reason. | Yes |
insufficient_funds | The card does not have enough balance. | Yes |
expired_card | The card has expired. | No |
incorrect_cvc | The CVC does not match. | Yes |
incorrect_number | The card number is wrong. | Yes |
lost_card | The card has been reported lost. | No |
stolen_card | The card has been reported stolen. | No |
pickup_card | The issuer requests the card be retained. | No |
do_not_honor | The issuer declined without a specific reason. | Yes |
fraudulent | The issuer flagged this as a fraudulent transaction. | No |
processing_error | A transient error at the acquirer. | Yes |
try_again_later | The issuer is temporarily unavailable. | Yes |
Recoverable = Yes means the guest can retry with different card details or after contacting their bank.
Infrastructure errors
Section titled “Infrastructure errors”Returned when the SDK cannot complete the request due to network or server issues. These are not caused by the card data itself.
| Code | Description | What to do |
|---|---|---|
network_error | Could not reach the Zatlas API. The guest may be offline. | Show a retry button. Check the guest’s connection. |
timeout | The request timed out waiting for a response. | Retry once. If it persists, contact support. |
server_error | Zatlas API returned an unexpected error (5xx). | Retry after a brief delay. If it persists, contact the Zatlas team. |
authentication_error | The access token is invalid, expired, or missing. | Fetch a new access token from your server and retry. |
rate_limit_exceeded | Too many requests from this publishable key. | Back off and retry after a few seconds. |
invalid_request | The request parameters are malformed (e.g. missing amount). | Check the parameters passed to checkout() or createToken(). This is a code bug, not a guest error. |
Validation errors
Section titled “Validation errors”Returned in the change event payload when the guest’s input fails client-side validation. These are shown inline next to the field inside the iframe.
| Code | Description | Trigger |
|---|---|---|
incomplete_number | The card number is too short. | Guest has not finished typing the full card number. |
invalid_number | The card number fails the Luhn check. | Guest entered an impossible card number. |
incomplete_expiry | The expiry date is incomplete. | Guest typed only the month or left the field blank. |
invalid_expiry_past | The expiry date is in the past. | Guest entered a month/year that has already passed. |
incomplete_cvc | The CVC is too short. | Guest entered fewer digits than required (3 for Visa/MC, 4 for Amex). |
invalid_cvc | The CVC contains non-numeric characters. | Guest typed letters or symbols in the CVC field. |
invalid_holder_name | The cardholder name is too short. | Guest typed less than 2 characters (name field is optional — empty is valid). |
The SDK ships React bindings for seamless integration with React and Next.js projects.
ZatlasProvider
Section titled “ZatlasProvider”Wraps your app (or the payment section) with the SDK instance. Create the ZatlasCardCapture instance first, then pass it to the provider.
import { ZatlasCardCapture } from '@zatlas/card-capture';import { ZatlasProvider } from '@zatlas/card-capture/react';
const zatlas = new ZatlasCardCapture({ publishableKey: 'pk_sandbox_your_key', locale: 'es-MX',});
function App() { return ( <ZatlasProvider zatlas={zatlas}> <PaymentPage /> </ZatlasProvider> );}useZatlas
Section titled “useZatlas”Hook that returns the ZatlasCardCapture instance from the nearest ZatlasProvider. Use it to call checkout() or createToken().
import { useZatlas } from '@zatlas/card-capture/react';
function PaymentPage() { const zatlas = useZatlas(); // Use zatlas.checkout() or zatlas.createToken() in event handlers}CardElement
Section titled “CardElement”Renders the card form iframe. Handles mounting, unmounting, and event binding automatically. The cta_clicked event is handled via card.on() on the vanilla instance — use useZatlas() to access it.
import { CardElement, useZatlas } from '@zatlas/card-capture/react';
function PaymentForm() { const zatlas = useZatlas();
return ( <CardElement options={{ mode: 'checkout' }} onReady={() => console.log('Card form ready')} onChange={(e) => console.log('Valid:', e.complete)} onFocus={() => console.log('Focused')} onBlur={() => console.log('Blurred')} onError={(e) => console.error('Error:', e.code)} /> );}To handle the CTA button click and trigger checkout, use the vanilla API alongside the React component:
import { useEffect, useRef } from 'react';import { ZatlasCardCapture } from '@zatlas/card-capture';
function CheckoutForm({ amount, reservationId }) { const cardRef = useRef(null);
useEffect(() => { const zatlas = new ZatlasCardCapture({ publishableKey: 'pk_sandbox_your_key', locale: 'es-MX', });
const card = zatlas.create('card', { mode: 'checkout' }); card.mount(cardRef.current);
const { accessToken } = await fetch('/api/payment-token').then(r => r.json());
card.on('cta_clicked', async () => { const { payment, error } = await zatlas.checkout({ accessToken, amount, currency: 'mxn', reservationId, }); if (payment) window.location.href = `/success?id=${payment.id}`; });
return () => card.unmount(); }, [amount, reservationId]);
return <div ref={cardRef} />;}CardElement Props:
| Prop | Type | Required | Description |
|---|---|---|---|
options | CardElementOptions | No | Options object with mode, showCardholderName, showPostalCode. |
onReady | () => void | No | Called when the iframe is loaded and interactive. |
onChange | (event: ChangeEvent) => void | No | Called on every input change. See change event. |
onFocus | () => void | No | Called when a field receives focus. |
onBlur | () => void | No | Called when a field loses focus. |
onError | (error: FieldError) => void | No | Called on non-recoverable iframe errors. |
className | string | No | CSS class applied to the outer <div> wrapper. |
id | string | No | ID applied to the outer <div> wrapper. |
Themes
Section titled “Themes”The SDK ships with built-in themes. Import them by name or pass a custom theme object to the constructor or updateTheme().
import { darkTheme, mergeTheme } from '@zatlas/card-capture';
// Built-in dark themeconst zatlas = new ZatlasCardCapture({ publishableKey: 'pk_sandbox_your_key', theme: darkTheme,});
// Custom overrides (deep-merged with default theme)const zatlas = new ZatlasCardCapture({ publishableKey: 'pk_sandbox_your_key', theme: { colors: { primary: '#1a73e8', borderFocus: '#1a73e8', background: '#f9fafb', text: '#111827', error: '#ef4444', }, borders: { radius: '12px', }, },});Built-in themes: defaultTheme (light, teal accents) and darkTheme (dark background, lighter accents). Use mergeTheme() to extend either one.
For the full list of theme properties and visual examples, see the Theming Guide.