Skip to content

Tokenization Integration

Tokenization captures the guest’s card details and returns a secure mth_* token. No payment is created on the frontend. Your server stores the token and charges later via the Payments API.

ScenarioWhy tokenization fits
Scheduled chargesCharge the guest at check-in or check-out without asking for the card again.
Recurring paymentsBill the guest weekly, monthly, or on any schedule your system defines.
Authorization + captureAuthorize an amount now and capture it later (e.g. hold a deposit).
Multiple chargesSplit the stay into multiple payments (room, minibar, spa) using the same card.
No-show feesKeep the card on file and charge a no-show fee if the guest does not arrive.
<div id="card-element"></div>
<script type="module">
import { ZatlasCardCapture } from '@zatlas/card-capture';
const zatlas = new ZatlasCardCapture({
publishableKey: 'pk_sandbox_your_key',
locale: 'es-MX',
});
const card = zatlas.create('card', { mode: 'tokenize' });
card.mount('#card-element');
// Get a fresh access token from your server
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',
});
if (token) {
// Send token to your server for storage
await fetch('/api/save-method', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
methodId: token.id,
last4: token.card.last4,
brand: token.card.brand,
}),
});
showConfirmation('Card saved successfully');
} else {
console.error('Tokenization failed:', error.code);
}
});
</script>

When your server is ready to charge the guest, call the Payments API with the stored mth_* token. No frontend interaction is needed — your server sends the methodId, amount, and currency, and receives the payment result.

See the Payments API documentation for endpoints, authentication, and response formats.

The createToken() promise resolves with a TokenResult object containing card metadata you can display or store:

interface TokenResult {
token: {
id: string; // e.g. "mth_abc123"
card: {
last4: string; // e.g. "4242"
brand: string; // e.g. "visa", "mastercard", "amex"
expMonth: number; // e.g. 12
expYear: number; // e.g. 2030
};
createdAt: string; // ISO 8601 timestamp
};
error: null;
}

You can show the guest a confirmation like “Visa ending in 4242 saved” using token.card.brand and token.card.last4.

Tokenization can fail if the card is invalid, the network times out, or the access token has expired. Always check for error in the result:

const { token, error } = await zatlas.createToken({
accessToken,
currency: 'mxn',
});
if (error) {
switch (error.code) {
case 'card_declined':
// The card issuer rejected the card — ask the guest for a different card
break;
case 'expired_card':
// The card is past its expiration date
break;
case 'incorrect_cvc':
// The CVC does not match — the guest can correct it and retry
break;
case 'processing_error':
// Temporary issue — safe to retry
break;
case 'authentication_error':
// The access token expired — fetch a new one from your server
break;
default:
console.error('Unexpected error:', error.code, error.message);
}
}

The SDK also displays error messages inside the iframe, so the guest sees feedback even if your code does not render a custom message.

PropertyTypeRequiredDescription
accessTokenstringYesOAuth2 access token obtained from your server.
currencystringYesISO 4217 currency code, lowercase (e.g. 'mxn', 'usd'). Determines which payment processor to use for tokenization.
metadataRecord<string, string>NoKey-value pairs attached to the token for your reference.