Verestro Paytool Client SDK

Paytool Web SDK v1

Embed Paytool flows on your site. This SDK exposes a small, focused API on window.Paytool for easy integration.


Quick start

Add the SDK to your page:

<script src="https://paytool.verestro.com/v1/paytool.js"></script>

This creates a global window.Paytool object with the following methods:

  • embedCardForm(options)
  • isEmbedError(err)

Note (CORS/allowlist): Your domain must be allowlisted for the SDK and hosted pages to load. See the full guidelines at https://developer.verestro.com or contact support to request an allowlist update.

Environments

Tip: Staging requires separate credentials. The environment may change more frequently; occasional instability can occur.


API reference

All examples below assume the SDK has been loaded and window.Paytool is available.

embedCardForm(options)

Embeds a secure card form (iframe) you can style and control. Returns a CardFormEmbed instance once the form is fully rendered and sized.

Signature:

Paytool.embedCardForm(options: CardFormEmbedOptions): Promise<CardFormEmbed>

CardFormEmbedOptions and defaults:

interface CardFormEmbedOptions {
target: HTMLElement; // required
// Provide full PaymentMethods payload (as returned by /payment-methods).
// Strongly recommended. If omitted or null, the legacy token-only flow is used,
// which is deprecated and will be removed in a future version.
paymentMethods?: PaymentMethods | null;
optionalElements?:
| boolean
| {
firstNameField?: boolean; // default: true
lastNameField?: boolean; // default: true
emailField?: boolean; // default: true
cedulaField?: boolean; // default: false
storeField?: boolean; // default: true
transactionAgreement?: boolean; // default: true
dccInfo?: boolean; // default: true
cardNetworksInfo?: boolean; // default: true
submitLoader?: boolean; // default: true
};
onSubmit?: (state: CardFormEmbedState) => void; // default: no-op
onFormStateChange?: (state: CardFormEmbedState) => void; // default: no-op
onCardNumberChange?: (e: { token: string | null } | CardNumberInfo) => void; // default: no-op
// Note: The `{ token }` shape is deprecated and will be removed in a future version.
// Provide `paymentMethods` to receive a `CardNumberInfo` payload instead.
}

onCardNumberChange payload shape:

  • Deprecated (no paymentMethods): { token: string | null }token is null while the number is invalid. Deprecated: The token-only payload will be removed in a future release. Use CardNumberInfo instead by passing paymentMethods and relying on cardNumberInfo/paymentMethodData in CardFormEmbedState.
  • With payment methods: CardNumberInfo
    • type: 'STORED_PAYMENT_METHOD' includes { id: string; encryptedCardNumber: null }
    • type: 'ENCRYPTED_CARD_NUMBER' includes { encryptedCardNumber: string; id: null }

Example: preloading saved payment methods

// Fetch available payment methods for the user
const paymentMethodsFromServer = await getPaymentMethodsFromYourServer();

// Pass the whole object to the SDK; the card form will use the 'CARD' entry
const form = await Paytool.embedCardForm({
target: document.getElementById('card-form')!,
paymentMethods: paymentMethodsFromServer,
optionalElements: true
});

Helper example: getPaymentMethodsFromYourServer

// Example only — call your backend to fetch available methods for the current user.
// The endpoint should return the full `PaymentMethods` payload expected by the SDK.
async function getPaymentMethodsFromYourServer() {
const res = await fetch('/api/payment-methods', { credentials: 'include' });
if (!res.ok) throw new Error('Failed to fetch payment methods');
return res.json();
}

Example response shape returned by your backend:

{
"paymentMethods": [
{
"type": "CARD",
"storedPaymentMethodData": [
{
"type": "CARD",
"id": "693f3244-9919-49ba-91c8-b095a5cf2ffb",
"maskedCardNumber": "************9507",
"expirationDate": "12/26",
"cvcRequiredForPayment": false,
"cardBrand": "MASTERCARD",
"paymentMethodDataOwner": { "name": "Jan Kowal" }
}
]
}
]
}

CardFormEmbed main methods and events:

  • pay(transactionId: string): Promise<EmbedPayResult> — disables the form and begins payment.
    • If dynamic currency conversion (DCC) is available, a DCC selection overlay is presented as part of the flow.
    • If a 3‑D Secure challenge is required, a dedicated overlay is shown; the promise resolves/rejects after the flow completes.
  • getFormState(): Promise<CardFormEmbedState> — current validity, selected method, sender data, etc.
  • enable() / disable() — control interactivity.
  • destroy() — unmount the component.
  • Events: statechange, cardnumberchange, submit (see Events section).

Typical flow:

<div id="card-form"></div>
<script>
(async () => {
// 0) Get payment methods from server
const paymentMethodsFromServer = await getPaymentMethodsFromYourServer();
// 1) Embed the form
const cardForm = await Paytool.embedCardForm({
target: document.getElementById('card-form'),
optionalElements: true,
paymentMethods: paymentMethodsFromServer,
onFormStateChange: s => {
// s.isValid; s.token (deprecated); s.paymentMethodData; s.senderData; s.cardNumberInfo
},
onCardNumberChange: payload => {
if ('token' in payload) {
// Deprecated path (no payment methods): payload is { token }
const { token } = payload;
} else {
// Prefer using CardNumberInfo by providing `paymentMethods`.
console.log(payload);
}
}
});

// 2) When ready to charge (e.g., submit button), get latest state if needed
const state = await cardForm.getFormState();
const payload = state; // choose what your backend expects

// 3) Create a transaction on your server using the data above
const transactionId = await createTransactionOnYourServer(payload);

// 4) Start the payment
try {
const res = await cardForm.pay(transactionId);
console.log('Payment complete:', res.status);
} catch (err) {
if (!Paytool.isEmbedError(err)) throw err;
console.log('Payment failed:', err.status, err.reason);
}
})();

async function createTransactionOnYourServer(payload) {
// Example only: call your backend. Never handle charges purely on the client.
return '12345678-transaction-id';
}
</script>

Diagram flow

isEmbedError(err)

Type guard that returns true if the error originated from the SDK (EmbedError). Useful when distinguishing SDK errors from unexpected script errors.

if (Paytool.isEmbedError(err)) {
console.log(err.status, err.reason);
}

Events (card form)

Every callback in CardFormEmbedOptions has a matching DOM event on the CardFormEmbed element. This is handy if you prefer standard listeners over passing callbacks upfront.

  • statechange — payload: CardFormEmbedState
  • cardnumberchange — payload:
    • Deprecated (no payment methods): { token: string | null } Deprecated: will be removed in a future release. Provide paymentMethods to receive CardNumberInfo.
    • With saved methods: CardNumberInfo (new card typing or saved card selection)
  • submit — payload: CardFormEmbedState

Example:

const form = await Paytool.embedCardForm({ target: el });
form.addEventListener('statechange', e => console.log(e.detail));
form.addEventListener('cardnumberchange', e => console.log(e.detail));
form.addEventListener('submit', e => console.log(e.detail));

Styling tips (card form)

The card form is rendered inside an iframe and sets its height dynamically after it finishes initial rendering. The element gets an initialized CSS class at that moment — use it for layout styles to avoid a brief empty gap during first paint.

verestro-paytool-card-form-embed.initialized {
display: block;
background: #f3f4f6;
border: 2px solid #e8e8e8;
border-radius: 4px;
padding: 25px 28px 28px;
}

Troubleshooting

  • SDK doesn’t load or iframes fail to display: ensure your domain is allowlisted and that the correct environment URL is used.
  • The promise doesn’t resolve immediately when calling cardForm.pay(...): if a 3‑D Secure challenge or another step is required, an overlay is shown and the promise resolves/rejects after the flow completes.
  • Handle rejections: always wrap await cardForm.pay(...) in try/catch and use isEmbedError to branch between SDK errors and unexpected ones.

For end‑to‑end integration guidance (backend setup, redirect URLs, and merchant onboarding), see https://developer.verestro.com.