Collect Card Data from User

Collect Card Data with VGS

In an agentic system, card data must be collected in a secure and compliant way without exposing raw PAN or CVC to your systems or AI agents. This page shows you how to use VGS Collect to securely collect, tokenize, and store card data with full PCI compliance.

This method:

  • Uses customizable PCI-compliant hosted fields

  • Creates a Card Object along with VGS Aliases for the PAN and CVC fields

  • Authenticates via backend-generated JWT (using a minimally-scoped service account)


Step 1: Create a Client-Side Service Account

  1. Navigate to the Service Accounts section of the VGS Dashboard: Vault > Organization > Service Accounts.

  2. Click on the Create New button.

  3. Select your Vault and add the following scopes: cards:write & network-tokens:write

Reference Documentation

Full Service Account Setup Guide


Step 2: Backend – Generate JWT to be used with Collect Form

Your backend must generate a short-lived JWT signed with your service account's private key. This token will be used by the frontend to authenticate to your account during form submission.

Below is a sample ExpressJS server that can be used to generate the JWT.

// sample-agentic-app
// `npm start` to run

const express = require('express');
const axios = require('axios');
const cors = require('cors');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3030;

app.use(cors());
app.use(express.static('public')); // serve frontend

const CLIENT_ID = process.env.VGS_CLIENT_ID;
const CLIENT_SECRET = process.env.VGS_CLIENT_SECRET;
const TOKEN_URL = 'https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token';

app.get('/get-collect-token', async (req, res) => {
  try {
    const params = new URLSearchParams();
    params.append('client_id', CLIENT_ID);
    params.append('client_secret', CLIENT_SECRET);
    params.append('grant_type', 'client_credentials');

    const response = await axios.post(TOKEN_URL, params);
    res.json({ access_token: response.data.access_token });
  } catch (error) {
    console.error('Error getting VGS token:', error.response?.data || error.message);
    res.status(500).json({ error: 'Failed to get token' });
  }
});

app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

Step 3: Frontend – Instantiate the Form

Load the VGS Collect library and instantiate the form:

const VAULT_ID = "tntsample"; // replace with your Vault ID
const ENVIRONMENT = "sandbox";

const form = VGSCollect.create(VAULT_ID, ENVIRONMENT, () => { console.log("Form created") });

Reference Documentation

Step 4: Create Form Fields

Use the built-in card field types to render secure, styled input fields:

const VAULT_ID = "tntsample"; // replace with your Vault ID
const ENVIRONMENT = "sandbox";

const form = VGSCollect.create(VAULT_ID, ENVIRONMENT, () => { console.log("Form created") });

const css = {
  "vertical-align": "middle",
  "white-space": "normal",
  "background": "none",
  "font-family": "sofia, arial, sans-serif",
  "font-size": "16px",
  "color": "rgb(34, 25, 36)",
  "line-height": "normal",
  "padding": "0px 1em",
  "box-sizing": "border-box",
  "&::placeholder": {
    "color": "#6A6A6A"
  },
};

form.cardholderNameField('#cardholder-name', { placeholder: 'Jane Doe', css: css });
form.cardNumberField('#card-number', { placeholder: '4111 1111 1111 1111', css: css });
form.cardExpirationDateField('#card-expiration', { placeholder: 'MM / YY', css: css });
form.cardCVCField('#card-cvc', { placeholder: '123', css: css });

Reference Documentation

Step 5: Create a Card

When the user submits the form, call form.createCard(...) and pass the backend-generated JWT from Step 2 into the createCard function.

document.getElementById('submit-btn').addEventListener('click', async () => {
  try {
    const res = await fetch('/get-collect-token');
    const { access_token } = await res.json();

    const response = await form.createCard({
      auth: access_token,
      data: {
        "cardholder": {}
      }
    },
      function (status, card_object) {
        alert('Card created. Check your console for the details.');
        console.log("Card ID: " + card_object.data.id);
        console.log("PAN Alias: " + card_object.data.attributes.pan_alias);
        console.log("CVC Alias: " + card_object.data.attributes.cvc_alias);
        console.log('Card Object: ', card_object.data);
      },
      function (e) {
        alert('Card creation failed. Check your console for the details.');
        console.log("Error", e);
      });
  } catch (err) {
    console.error('Error:', err);
    alert('Card creation failed. Check console.');
  }
}); 

Using the Card Object for Payments

The createCard function will provide a card object to your front-end. Below are the key elements of the card object to use for payments and additional services.

Name
JSON Path

Card ID

This is the main identifier forthe card object. It can be used to reference the card using the card GET endpoint as-needed in the future.

This value will remain constant even if the underlying card details change using card services.

card_object.data.id

PAN Alias

This is a unique token that represents the exact value of the card number (PAN). This value can change when VGS receives an update to the card number using the VGS Account Updater service.

This value can be used with the VGS Outbound Proxy when you wish to share the original PAN with a third-party.

`card_object.data.attributes.pan_alias

CVC Alias

This is a unique token that represents the exact value card number (PAN). This value can be used with the VGS Outbound Proxy when you wish to share the original PAN with a third-party PSP or other payment system. Because the CVC is considered "SAD" (Sensitive Authentication Data) according to PCI-DSS regulations, this value can only be used as a reference for 1 hour.

`card_object.data.attributes.cvc_alias

Expiration Date

The expiration date of the card. This value will be required for issuing PSP tokens and performing payments.

card_object.data.attributes.exp_month card_object.data.attributes.exp_year

Card Object JSON Sample
{
  "data": {
    "id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "type": "cards",
    "attributes": {
      "pan_alias": "tok_abcdefghijklmnop",
      "cvc_alias": "tok_zbcdefgh",
      "cvc_status": "active",
      "bin": "411111",
      "first8": "41111111",
      "last4": "1111",
      "exp_month": 5,
      "exp_year": 28,
      "card_fingerprint": "6TeSCB16LtyifEAmY2goxYfSk5sALriXpefzzxh29xhu",
      "capabilities": [
        "network-tokens",
        "card-updates"
      ],
      "created_at": "2025-08-01T00:00:00Z",
      "updated_at": "2025-08-01T00:00:00Z"
    },
    "meta": {
      "token_type": "pan"
    }
  }
}

Last updated