Pandabase
Vault

Elements

Collect sensitive data in your page and send it directly to Vault.

Vault is in alpha. There are no Vault fees during alpha.

Elements are input fields hosted by Pandabase and embedded in your page. Each field runs in an iframe and sends the customer's input directly to Vault. Your page receives a token and display details, such as a card's last four digits, without reading the raw input.

Elements are part of the WebSDK. Load the SDK from https://js.pandabase.io.

Create a session on your server

Create a session from your server with a secret key. The session lets the browser create one token. Pass its client_secret to the page that contains your form.

curl https://api.pandabase.io/v2/workspaces/wks_01j9zk2m4p6r8t0v2x4z6b8d0f/vaults/vlt_01j9zm3n5q7s9u1w3y5a7c9e1g/sessions \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "type": "card", "metadata": { "customer": "cus_123" } }'
{
  "object": "vault_session",
  "id": "vss_01j9zr8k2p4m6q8s0u2w4y6a8c",
  "type": "card",
  "client_secret": "vss_01j9zr8k2p4m6q8s0u2w4y6a8c_secret_7Hq2Lm9xR4",
  "metadata": { "customer": "cus_123" },
  "expires_at": "2026-09-01T12:30:00Z",
  "created_at": "2026-09-01T12:00:00Z"
}

A session expires after 30 minutes or when it creates a token. The token belongs to the session's vault and inherits its metadata. Create a new session when the previous one has been used or has expired.

Mount Elements on your page

Add an empty container where the field should appear, then create and mount the Element with your publishable key and the session's client_secret.

<form id="card-form">
  <div id="card-element"></div>
  <button type="submit">Save card</button>
</form>
const pandabase = Pandabase('pk_live_...');

const elements = pandabase.vault.elements({ clientSecret });
const card = elements.create('card');

card.mount('#card-element');

Save the data as a token

const form = document.getElementById('card-form');

form.addEventListener('submit', async (event) => {
  event.preventDefault();

  const { token, error } = await pandabase.vault.tokenize(card);
  if (error) {
    showError(error.message);
    return;
  }

  await fetch('/api/save-card', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ tokenId: token.id }),
  });
});

tokenize returns the token and its mask. Use the mask to display a label such as "Visa ending in 4242", and send the token ID to your server to save. The result does not include raw data.

Element types

TypeCollectsToken type
cardNumber, expiry, and CVC in one fieldcard
cardNumber, cardExpiry, cardCvcEach part of a card in its own fieldcard
bankAccountAccount and routing numbersbank_account
textA single sensitive value, such as a tax IDpii

For separate card fields, create the number, expiry, and CVC fields from the same elements instance. Calling tokenize on any one of them combines all three into one card token.

const number = elements.create('cardNumber');
const expiry = elements.create('cardExpiry');
const cvc = elements.create('cardCvc');

number.mount('#card-number');
expiry.mount('#card-expiry');
cvc.mount('#card-cvc');

const { token } = await pandabase.vault.tokenize(number);

For a text Element, pass a format to validate and mask the input, such as us_ssn or iban.

Respond to field changes

Use field events to show errors and enable the submit button when the input is complete.

card.on('change', (event) => {
  submitButton.disabled = !event.complete;
  errorMessage.textContent = event.error ? event.error.message : '';
});
EventFires when
readyThe Element has loaded and can accept input.
changeThe value changes. Includes complete, empty, error, and for cards, brand.
focus, blurThe Element gains or loses focus.

Style the fields

Your page's CSS can't style the fields inside the iframe. Pass a style object when creating an Element. Set the default appearance in base, then add invalid or complete styles if needed.

const card = elements.create('card', {
  style: {
    base: {
      color: '#0a0f0c',
      fontFamily: 'Geist, sans-serif',
      fontSize: '15px',
      '::placeholder': { color: '#9aa4a0' },
    },
    invalid: { color: '#dc2626' },
  },
});

Load custom fonts by passing fonts to pandabase.vault.elements(), as a list of CSS URLs from a font provider.

Last updated on

On this page