Web

Every method, option and error in the Web SDK.

Reference for Tonder's Web SDK (@tonder.io/web-sdk, TypeScript, types included). The step-by-step guide is at Web SDK; source code and README at github.com/tonderio/web-sdk.

import { createTonder, AppError, ErrorKeyEnum } from '@tonder.io/web-sdk';

Prefer loading it with a <script> tag instead of npm? The approved stage and production CDN URLs are in Web SDK → Installation.

createTonder(config)

Creates an SDK instance for one shopper/session.

interface TonderConfig {
  api_key: string;
  environment: 'sandbox' | 'stage' | 'production';
  session?: {
    customer?: {
      email: string;
      first_name?: string;
      last_name?: string;
      phone?: string;
    };
    secure_token?: string;
  };
  presentation_mode?: 'redirect' | 'embedded';
  events?: {
    presentation?: {
      on_open?(): void;
      on_close?(): void;
    };
  };
  customization?: TonderCustomization;
}
FieldRequiredDescription
api_keyYesPublic Tonder key for browser integrations.
environmentYes'sandbox', 'stage', or 'production'.
session.customerFor pay() and saved-card operationsCustomer identity.
session.secure_tokenFor saved-card operationsShort-lived token minted by your backend.
presentation_modeNo'redirect' (default) or 'embedded'.
events.presentation.on_openNoCalled when an embedded hosted-payment view opens.
events.presentation.on_closeNoCalled when the shopper closes the embedded view.
customization.card_fieldsNoSecure card-field customization (below).

Throws INIT_ERROR when config or api_key is missing, or environment is invalid.

customization.card_fields

All fields are optional; omitted values use the SDK defaults.

FieldTypeDescription
labelsCardLabelsText shown above each secure field (cardholder_name, card_number, cvv, expiration_month, expiration_year).
placeholdersCardPlaceholdersPlaceholder text inside each secure field.
stylesCardStylesGlobal (card_form) and per-field styles for inputs, labels, errors, and the card icon (enable_card_icon).
error_messagesCardFieldErrorMessagesValidation-message overrides (required, invalid, and per field).

Style values use CSS-in-JS keys supported by the secure renderer (e.g. font_size, font_family, color, border_color). styles applies inside the secure iframe; the mount container's layout (e.g. .card-field { max-height: 90px; }) is controlled by your own CSS.

const tonder = createTonder({
  api_key: 'pk_test_...',
  environment: 'sandbox',
  customization: {
    card_fields: {
      labels: { card_number: 'Card number', cvv: 'Security code' },
      placeholders: { card_number: '4111 1111 1111 1111', expiration_month: 'MM' },
      styles: {
        card_form: {
          input_styles: {
            base: { color: '#111827', font_family: 'Inter, sans-serif', font_size: '16px' },
            focus: { border_color: '#2563eb' },
            invalid: { color: '#b91c1c' },
          },
          label_styles: { base: { color: '#374151', font_weight: '600' } },
          error_styles: { base: { color: '#b91c1c' } },
        },
        enable_card_icon: true,
      },
      error_messages: { required: 'Complete this field.', invalid: 'Check this field.' },
    },
  },
});

Methods

MethodWhat it doesNeeds init()
tonder.init()Fetches merchant configuration and prepares the SDK. Safe to call more than once.
tonder.create('card_fields', options?)Creates the secure card-fields component.No
card_fields.mount()Mounts the secure fields into the containers.Yes
card_fields.unmount()Unmounts this component's fields.No
card_fields.reveal(input)Reveals display-safe saved-card values (never the CVV).Yes
tonder.pay(input)Creates a payment.Yes
tonder.getTransaction(id)Reads the current transaction state.No
tonder.enrollCard()Saves the mounted new card for session.customer.Yes
tonder.getCustomerCards()Lists the customer's saved cards.Yes
tonder.removeCustomerCard(card_id)Removes a saved card.Yes
tonder.getPaymentMethods()Lists the business's active payment methods.No
tonder.getPaymentMethodBanks()Lists SafetyPay banks grouped by channel.No

tonder.create('card_fields', options?)

Without options, the SDK mounts the full new-card form using the default containers:

FieldDefault container
cardholder_name#collect-cardholder-name
card_number#collect-card-number
expiration_month#collect-expiration-month
expiration_year#collect-expiration-year
cvv#collect-cvv (or #collect-cvv-<card_id> for saved cards)
interface CardFieldsOptions {
  fields?: (CardField | { field: CardField; container_id?: string })[];
  card_id?: string; // for a saved card's CVV
  unmount_context?: 'all' | 'none' | 'current' | 'create' | string;
  events?: Partial<Record<CardField, {
    on_change?(state: CardFieldState): void;
    on_blur?(state: CardFieldState): void;
    on_focus?(state: CardFieldState): void;
    on_ready?(state: CardFieldState): void;
  }>>;
}

tonder.pay(input)

interface PayInput {
  amount: number;
  currency?: string;
  return_url: string;
  payment_method:
    | { type: 'card' }
    | { type: 'saved_card'; card_id: string }
    | { type: string; config?: Record<string, unknown> };
  metadata?: Record<string, unknown>;
  billing_address?: {
    street?: string;
    street2?: string;
    state?: string;
    country?: string;
    zip_code?: string;
  };
  client_reference: string;
  idempotency_key?: string;
}
FieldRequiredDescription
amountYesPayment amount (decimal units). Must be greater than 0.
currencyNoCurrency code. Defaults to MXN.
return_urlYesURL used after hosted authentication or redirect completion.
payment_methodYesNew card, saved card, or an enabled alternative payment method.
billing_addressNoThe buyer's billing address. Every field inside it is optional.
client_referenceYesYour order reference — shown in dashboards, exports, webhooks, and reports.
idempotency_keyNoStable key per payment attempt so retries don't create duplicate charges.
metadataNoNon-sensitive context for reconciliation and reports.

metadata keys with reporting meaning:

KeyReport usage
operation_dateBusiness operation date/time for reporting and reconciliation.
customer_emailCustomer email shown in transaction reports.
customer_idMerchant customer identifier for report filtering.
business_userInternal user, POS terminal, or automation that initiated the payment.

Returns Promise<RawTransaction>. A transaction that needs 3DS or hosted instructions can include next_action.redirect_to_url.url; APM/SPEI responses may include clabe, bank_name, payment_instructions, and voucher_pdf.

tonder.getCustomerCards()

interface Card {
  card_id: string;
  card_number: string; // masked
  expiration_month: string;
  expiration_year: string;
  card_scheme: string;
  subscription_id: string | null;
}

subscription_id is returned only when Card-on-File is enabled for the business. When it is null, mount the saved-card CVV field before calling pay() with that card.

tonder.getPaymentMethods()

interface PaymentMethodInfo {
  id: number;
  payment_method: string; // the value you pass as payment_method.type in pay()
  label: string;
  logo: string;
  category: string;
}

Returns Promise<PaymentMethodInfo[]> with the business's enabled alternative payment methods. Use it to build the method list in your UI instead of hard-coding it: payment_method is the value you then pass as payment_method.type in pay().

[
  {
    "id": 7,
    "payment_method": "oxxopay",
    "label": "Oxxo Pay",
    "logo": "https://...",
    "category": "cash"
  }
]

tonder.getPaymentMethodBanks()

interface PaymentMethodBank {
  id: number;
  name: string;
  code: string;
  country: string;
  channel: 'WP' | 'OL'; // WP = cash, OL = transfer
  logo?: string;
}

interface PaymentMethodBanks {
  cash: PaymentMethodBank[];
  transfer: PaymentMethodBank[];
}

For safetypayCash / safetypayTransfer, build payment_method.config from country (bank.country), channel (bank.channel), and bank_ids: [{ id: bank.code }] — the bank routing code, not the internal bank.id.

Types

import type {
  TonderConfig,
  PayInput,
  RawTransaction,
  Customer,
  Card,
  EnrollResult,
  PaymentMethodInfo,
  PaymentMethodBank,
  PaymentMethodBanks,
  CardFieldsOptions,
  CardFieldsComponent,
  TonderEvents,
  PresentationEvents,
} from '@tonder.io/web-sdk';

RawTransaction

pay() and getTransaction() return transaction fields in snake_case, matching Tonder's API and webhook payloads:

interface RawTransaction {
  id: string;
  operation_type: string;
  status: string;
  amount: number;
  currency: string;
  client_reference?: string;
  metadata?: Record<string, unknown>;
  provider?: string;
  created_at?: string;
  status_code?: number;
  next_action?: {
    redirect_to_url?: {
      url: string;
      verify_transaction_status_url?: string;
    };
  };
  decline_code?: string;
  decline_reason?: string;
  payment_instructions?: Record<string, unknown>;
  voucher_pdf?: string;
  clabe?: string;
  bank_name?: string;
  [key: string]: unknown;
}

Errors

SDK failures are thrown as AppError. Payment declines are not thrown: they're returned as transactions — read transaction.status. Branch on error.code; don't parse error.message.

try {
  const transaction = await tonder.pay({ /* ... */ });
} catch (error) {
  if (error instanceof AppError) {
    console.error(error.code, error.status_code, error.details.system_error);
    if (error.code === ErrorKeyEnum.MISSING_CUSTOMER) {
      // Recreate the SDK with session.customer.
    }
  } else {
    throw error;
  }
}

Main codes:

CodeWhen it happensHow to fix
INIT_ERRORSDK initialization failed.Check api_key, environment, and network access.
NOT_INITIALIZEDA method needs init() completed.Call await tonder.init() before the operation.
MISSING_CUSTOMERsession.customer is missing.Create the SDK with session.customer.email.
SECURE_TOKEN_REQUIREDSaved-card operations require session.secure_token.Mint the token on your backend and pass it in createTonder().
INVALID_PAYMENT_REQUESTamount, return_url, client_reference, or payment_method is invalid.Validate the request before calling pay().
INVALID_APM_CONFIGsafetypayCash/safetypayTransfer is missing config.country, config.channel, or config.bank_ids.Build config from the selected getPaymentMethodBanks() bank.
MOUNT_COLLECT_ERRORSecure fields could not mount or collect valid data.Ensure the containers exist and the fields are complete.
SECURE_FIELDS_LOAD_ERRORThe browser could not load the secure fields.Check CSP, ad blockers, and network access.
PAYMENT_PROCESS_ERRORThe payment could not be created/processed.Inspect error.details; retry only when safe/idempotent.
FETCH_TRANSACTION_ERRORTransaction lookup failed.Verify the id and reconcile from backend/webhooks.
POLL_TIMEOUT_ERROREmbedded 3DS completed but reconciliation didn't reach a final status in time.Don't fulfill from the client result; reconcile with getTransaction() or webhooks.
SAVE_CARD_ERROR / REMOVE_CARD_ERROR / CARD_ON_FILE_DECLINEDCard save/removal/enrollment failed.Ask for another card or inspect error.details.
FETCH_PAYMENT_METHODS_ERROR / FETCH_PAYMENT_METHOD_BANKS_ERRORThe methods/banks catalog could not be retrieved.Retry, or pass known method codes directly to pay().

The complete list (including rare/compatibility codes) is in the SDK README.

Payment statuses

Read payment state from transaction.status:

StatusMeaningWhat to do
SuccessPayment completed.Confirm the order.
AuthorizedPayment authorized by the processor path.Continue per your Tonder setup and reconcile with webhooks.
PendingNot final yet (redirect 3DS, asynchronous APM/SPEI).Wait for the webhook or read later with getTransaction().
ProcessingStill being processed by the provider.Don't fulfill yet.
DeclinedIssuer/processor declined the payment.Show a recoverable message.
FailedPayment failed.Show a recoverable message or offer another method.
CancelledPayment was cancelled or voided.Don't fulfill; let the shopper start a new payment.
ExpiredNot completed in time.Ask the customer to start a new payment.

Next steps

Was this page helpful?

On this page