# Overview

VGS stores sensitive data and tackles critical payment acceptance challenges such as multi-PSP management, card issuance, payment orchestration enablement, PCI compliance, and the protection of personally identifiable information (PII). We provide our clients with complete ownership, control, and insights into their payment data, driving growth and enhancing user experiences across industries.

VGS offers a comprehensive suite of solutions, including a composable Credential Management Platform, a PCI-compliant Vault, and advanced network value-added services such as Network Tokens, Account Updater, and Card Attributes. Our innovative technologies empower businesses to boost revenue through higher authorization rates, reduce fraud, and streamline operations - all while seamlessly integrating with existing tech stacks.

At VGS, we're not just securing payments - we're empowering businesses to unlock new possibilities in the ever-evolving payment landscape.

**Clients who are signed up to the Credential Management Platform (CMP) should navigate to this** [**page.**](https://docs.verygoodsecurity.com/card-management)


# Release Notes

A place to learn more about our publicly available products and services, feature enhancements, and improvements.

{% updates format="full" %}
{% update date="2026-06-26" tags="user-experience,cmp,data,3ds" %}

## June 2026 Release Notes

* #### **Support for Format Preserving PAN Alias**
  * On 6/26/2026, VGS released support for **format-preserving PAN Alias**.
  * Format-preserving PAN alias support allows CMP to return `pan_alias` in a configured format at the account level. With this configuration enabled, customers can choose a supported `pan_alias` format that better fits their integration needs. [Learn more.](/cmp/payment-credentials/cards#supported-card-alias-formats)<br>
  * **Key Benefits**

    * Keeps CMP compatible with systems that already depend on a specific alias format.
    * Reduces migration impact for customers using GENERIC\_T\_FOUR format

* #### **Dashboard Enhancements**
  * The [CMP Dashboard](https://dashboard.verygoodsecurity.com/cmp) now supports additional existing capability found in the [Vault Dashboard](https://dashboard.verygoodsecurity.com) experience. [Learn more](/cmp/platform/overview/cmp-dashboard). <br>
    * **Dashboard parity**
      * From the CMP Dashboard, users can now:
        * Initiate the process of Org Activation
        * Create new Organizations
        * Org admins can manage read/write/access permissions on the vault/tenant leveL
        * Org admins can Delete Vault/Tenants
        * Org admins can Rename Vault/Tenants<br>
    * **Minor enhancements**
      * Usage Reports - Added support for Amex + Discover
      * PAN Alias format available in Tenant Settings
      * Account Validation enablement available in Tenant Settings<br>
  * **Key Benefits**
    * Reduced the need for users to context-switch across experiences to access tools
    * Progress towards a unified dashboard experience.
      {% endupdate %}
      {% endupdates %}


# Overview

## VGS Credential Management Platform (CMP) <a href="#vgs-card-management-platform-cmp" id="vgs-card-management-platform-cmp"></a>

The VGS Credential Management Platform (CMP) empowers you with a secure, streamlined, and unified solution for managing your payment credential data. Say goodbye to complex integrations and technical overhead. CMP consolidates essential card services into an intuitive platform, allowing you to focus on what matters: growing your business.\
\
✧ [**Access the CMP Dashboard**](https://dashboard.verygoodsecurity.com/cmp) to view credential data, manage your organization and users, and more.

### Key Services within CMP <a href="#key-services-within-cmp" id="key-services-within-cmp"></a>

* Network Tokens: Elevate payment security and customer experience with network tokens. These unique digital identifiers replace sensitive PAN data, enhancing security while maximizing conversion rates.
* Account Updater: Eliminate declined transactions and customer frustration. AU seamlessly delivers updated card information directly from issuers, ensuring your data is always current.

### Benefits of CMP <a href="#benefits-of-cmp" id="benefits-of-cmp"></a>

* Simplified Integrations: Access all core payment credential services through a single, unified API, dramatically reducing integration complexity.
* Accelerated Time-to-Market & Operational Efficiency: Deploy new services faster with customizable configurations, optimizing operations and freeing up valuable resources.
* Enhanced Authorization Rates: Leverage high-quality payment credential data to improve authorization rates and reduce payment failures.

### Core Features of CMP <a href="#core-features-of-cmp" id="core-features-of-cmp"></a>

* **Account and Service Registration:**
  * Configure accounts tailored to your organizational structure. Whether you're a direct merchant or a payment service provider (PSP), CMP supports flexible account management.
  * Accounts represent logical entities where services are activated by creating a unique AccountID(aka vaultID). For example, a PSP may need multiple accounts to map to each of its merchants
* **Unified Payment Object Creation:**
  * Create and manage payment credential data through a single, comprehensive API, eliminating the need for multiple integrations.
  * Utilize the CMP Create endpoints to easily store and manage card objects for the created payment credential.
* **Configurable Automated Actions:**
  * Automate actions on payment credential objects based on your specific business rules.
  * Define desired actions upon payment credential object creation during account setup, streamlining workflows.
* **Service-Specific Endpoints:** Perform targeted actions on payment credential objects for individual services:
  * **Network Token Enrollment:** Secure transactions and improve processing speeds by enrolling cards in network token services.
  * **Account Updater Management:** Maintain up-to-date card information, reducing declined transactions, with Account Updater subscription and management features.

These actions can be automated or manually triggered through the CMP Workflow Engine, providing flexibility and control.

**In essence, CMP simplifies payment credential data management, allowing you to focus on driving growth and improving customer satisfaction.**

### Forward-Compatible API Integration <a href="#forward-compatible-api-integration" id="forward-compatible-api-integration"></a>

As we continue to enhance CMP by introducing new features, we may add new optional fields to existing API requests and response payloads. These changes are designed to be **non-breaking**, but your integration must be built to handle them safely.

We recommend the following practices to ensure forward compatibility:

**Design Your Integration to Be Flexible**

* Avoid performing strict schema validations or full JSON object comparisons for request or response payloads.
* Be prepared for **additional fields** to appear in existing API responses.
* Expect **optional request parameters** to be added over time.
* Do not assume the **order** of fields in a JSON object will remain consistent.

**Handle IDs and Opaque Values Robustly**

* CMP object IDs and tokens may evolve in **length and format**, including potential changes in prefixing (e.g., `card_`, `bankacct_`).
* Ensure any IDs or string values are treated as opaque and stored with adequate length (up to 255 characters). For example, if using MySQL, use VARCHAR(255) COLLATE utf8\_bin for case-sensitive lookups.

**Webhooks and Events**

* We may introduce **new event types** over time.
* Your webhook listeners should gracefully ignore unfamiliar event types and continue processing supported ones.


# CMP Dashboard

The [**CMP Dashboard**](https://dashboard.verygoodsecurity.com/cmp) is a front-end experience available to both existing and prospective CMP clients. Launched in June 2025, the CMP dashboard enables users to [create Sandbox CMP tenants](/cmp/platform/getting-started#create-a-sandbox-account-through-the-cmp-dashboard-preferred), view credential data, manage Organizations and users, and more.

### Key Services of the CMP Dashboard <a href="#key-services-within-cmp" id="key-services-within-cmp"></a>

* **Payment Credentials Search**: Search for specific Credential Objects by Card ID

<figure><img src="/files/yWK4tB6IXJve07XbNb1Y" alt=""><figcaption></figcaption></figure>

* **Payment Credentials Details**: Isolate specific credentials and view granular credential data, service-related data, and credential attributes.

<figure><img src="/files/rVIIVS8dnh5NbGrwPzZp" alt=""><figcaption></figcaption></figure>

* **Settings**: View the current configuration settings of your Sandbox and Live CMP tenants

<figure><img src="/files/vqbjxOS1kX9mBfgbhpCe" alt=""><figcaption></figcaption></figure>

* **Create Sandbox Tenants**: Use self-service account creation options to create new, preconfigured Sandbox tenants and quickly begin exploring CMP capabilities.

<figure><img src="/files/1MCXdyN7QNQHGZu6aQeD" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/KXapsinjFhsFj6EhvjbI" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note: The CMP Dashboard is an **evolving product**. It currently exists as a companion experience to the original VGS dashboard, the [Vault Dashboard](/vault/readme/vault-dashboard). \
\
As of 2025, some technical capabilities CMP users require to utilize the full breadth of CMP services are housed in the Vault Dashboard experience. Please note that some CMP activities will require navigation across dashboards until all capabilities are consolidated into a single experience.&#x20;
{% endhint %}


# Designing your CMP account

### Understanding Accounts <a href="#understanding-accounts" id="understanding-accounts"></a>

Accounts in the Card Management Platform serve as distinct, logical units for managing card services and credentials. Think of them as containers that isolate and organize your card-related activities.

#### Purpose <a href="#purpose" id="purpose"></a>

Accounts enable you to segment and manage different sets of cards and services. They also allow for separate enrollments with third parties such as VISA, Mastercard, American Express, and Discover in the situation that the third party requires separate enrollments into services per-merchant.

For merchant aggregators such as Payment Service Providers (PSPs), PayFacs, and Marketplaces, this allows for clear separation of merchant data, where each merchant can have its own dedicated account.

#### Key Characteristics <a href="#key-characteristics" id="key-characteristics"></a>

* Each account is uniquely identified by a Tenant ID (also referred to as a *Vault ID* or *Account ID*).
* Cards created within an account are exclusive to that account.
* Service configurations and settings are applied at the account level.

### Account Configuration Options <a href="#account-configuration-options" id="account-configuration-options"></a>

The platform offers flexible service configuration options at both the account and network levels:

#### Account-Level Service Control <a href="#account-level-service-control" id="account-level-service-control"></a>

* You have the ability to enable or disable services for the entire account.
* This provides a global setting for all cards within the account.

| Service                                                                                              | Overall Service Configuration                                                     |
| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| [Account Updater](/cmp/products-and-services/account-updater)                                        | Enabled/Disabled                                                                  |
| [Network Tokens](/cmp/products-and-services/network-tokens)                                          | Enabled/Disabled                                                                  |
| [Card Art](/cmp/products-and-services/card-art)                                                      | Enabled/Disabled                                                                  |
| [Duplicate Card Check](/cmp/payment-credentials/cards#duplicate-card-detection)                      | Enabled/Disabled                                                                  |
| [Card Attributes (Enriched Attributes)](/cmp/products-and-services/card-attributes)                  | Disabled by default. For upgrade, please contact support via **<support@vgs.io>** |
| [3DS](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds)                               | Enabled/Disabled                                                                  |
| [Account Validation](https://docs.verygoodsecurity.com/cmp/products-and-services/account-validation) | Enabled/Disabled                                                                  |

#### Network-Level Service Control <a href="#network-level-service-control" id="network-level-service-control"></a>

You can further refine service settings by enabling or disabling services at the network level (e.g., Visa, Mastercard). This allows for granular control over service availability based on the card network. Both **Account Updater** and **Network Token** services can be individually enabled or disabled per network, based on your business requirements.

| Service                                                       | Network-Level Configuration |
| ------------------------------------------------------------- | --------------------------- |
| [Account Updater](/cmp/products-and-services/account-updater) | Enabled/Disabled            |
| [Network Tokens](/cmp/products-and-services/network-tokens)   | Enabled/Disabled            |

#### Enrollment Types <a href="#enrollment-types" id="enrollment-types"></a>

The platform supports two enrollment types, determining how services are activated:

#### **On-Create Enrollment**

* This is the default setting.
* When a card object is created, the system automatically processes and activates the services enabled for the account.
* A webhook notification is sent upon successful service activation.

#### **Manual Enrollment**

* With manual enrollment, card creation does *not* automatically trigger service activation.
* You must explicitly invoke individual service endpoints to perform actions like network tokenization or account updater participation.
* This provides greater control over the timing of service activation.

| Service                                                       | Enrollment Type                 |
| ------------------------------------------------------------- | ------------------------------- |
| [Account Updater](/cmp/products-and-services/account-updater) | On Create Card (Default)/Manual |
| [Network Tokens](/cmp/products-and-services/network-tokens)   | On Create Card (Default)/Manual |


# Getting Started

## Getting Started with VGS CMP <a href="#getting-started-with-vgs-cmp" id="getting-started-with-vgs-cmp"></a>

Welcome to the VGS Credential Management Platform! This guide will help you quickly set up your sandbox environment and begin managing your accounts.

### 1. Create a Sandbox Account <a href="#id-1-create-a-sandbox-account" id="id-1-create-a-sandbox-account"></a>

Start by creating a sandbox (test) account. This allows you to create your organization and experiment with the APIs without affecting your production environment.

Currently, VGS offers two Dashboard experiences that support Sandbox account creation:<br>

* [CMP Dashboard](https://dashboard.verygoodsecurity.com/cmp): A distinct experience for users of the Credential Management Platform, with support for Sandbox account creation, payment credential search, visibility on individual credential details, and configuration of CMP accounts.

<details>

<summary>Create a Sandbox account through the CMP Dashboard (preferred):</summary>

1. Log in and authenticate to the [CMP Dashboard](https://dashboard.verygoodsecurity.com/cmp), and confirm that your preferred Organization is selected as the active Organization first - this is the Organization the account will be associated to. \
   \
   You can set your active Org by using the dropdown menu next to the title of the Organization reflected in the upper-left of the dashboard. To manage your Organizations, use the [*Vault Dashboard*](https://dashboard.verygoodsecurity.com) *> Vault > Organization settings*

2. Navigate to the 'Accounts' dropdown menu, and select  "+ Add account"

<figure><img src="/files/ui9uAlsE2vtYtOkTd4zI" alt="" width="375"><figcaption></figcaption></figure>

3. Follow the guided experience to create a Sandbox account. Sandbox accounts created through the CMP Dashboard are preconfigured with all available services set to default settings, as applicable. <br>

   <figure><img src="/files/rd75NsRflgxImITpNvGe" alt="" width="375"><figcaption></figcaption></figure>

4. Once the Sandbox account is created, locate the Tenant ID by navigating to *Settings*.<br>

   <figure><img src="/files/btv1HNCUcfFV3pDBBnzZ" alt=""><figcaption></figcaption></figure>

</details>

* [Vault Dashboard](https://dashboard.verygoodsecurity.com): A distinct experience for users of VGS Secure Data products and services, with support for vault/tenant creation, service account creation, access credential creation, notifications, route set up, VGS Collect, vaulting, and more.

<details>

<summary>Create a Sandbox account through the Vault Dashboard</summary>

1. Log in and authenticate to the [Vault Dashboard](https://dashboard.verygoodsecurity.com) and locate the *Vault* dropdown in the header. Beneath the name of each Vault (also known as a *Tenant*), an alphanumeric ID is visible.\
   \
   Note: To change the name of a Vault/Tenant, navigate to [Vault Dashboard](https://dashboard.verygoodsecurity.com) *> Vault > Vault settings.*<br>

   <figure><img src="/files/JPo5MNDvJOmzr2rWaWa0" alt="" width="563"><figcaption></figcaption></figure>

2. Click the "+New" element within the dropdown to initiate the process of opening a new Sandbox account.<br>

3. Define a name, region, and confirm the Vault/Tenant environment as Sandbox, then click 'Create Vault.'

4. Once the Vault/Tenant is created, locate alphanumeric Tenant ID and follow the next steps.<br>

   <figure><img src="/files/b3lwea1Hkz47yZZKa1nj" alt="" width="563"><figcaption></figcaption></figure>

</details>

{% hint style="info" %}
Please note that for security reasons, all dashboard experience sessions automatically expire after 20 minutes.
{% endhint %}

### 2. Set Up Services <a href="#id-2-getting-set-up-with-services" id="id-2-getting-set-up-with-services"></a>

Sandbox accounts created within the [CMP Dashboard](https://dashboard.verygoodsecurity.com/cmp) are preconfigured with all available services enabled and set to manual, as applicable.

To create a Sandbox account *without* pre-configured services, please use the [Vault Dashboard](https://dashboard.verygoodsecurity.com).

Follow these steps to begin managing your accounts:<br>

* **Locate Your Tenant ID:** Identify and record your Tenant ID (also referred to as a *Vault Id*), which is the unique identifier for your CMP Account.
* **Select Services:** Choose the desired card services from the [Configuration Options](/cmp/platform/cmp-account#account-configuration-options) section to tailor your account to your specific needs.
* **Contact Customer Support**: Once you have identified which services you want applied to the Sandbox account, contact <support@vgs.io> with your Tenant ID to assist with CMP account creation.

#### What happens when I'm done testing and ready to take my changes Live?

When you're ready to begin leveraging VGS in your real business environment, use the **Go Live** option in the [Vault Dashboard](https://dashboard.verygoodsecurity.com) to submit the necessary data, agree to our [Standard Master Services Agreement](https://www.verygoodsecurity.com/vgs-msa), and begin collaborating directly with our customer success team. \
\
If you have specific questions about activating an account from Sandbox to Live, reach out to <support@vgs.io>

The next section will cover key actions needed to properly authenticate your new account, and ensure credential data flows securely. &#x20;


# Authentication

### 1. Generate Service Account <a href="#id-1-generate-service-account" id="id-1-generate-service-account"></a>

* A **service account** is a special type of non-human client that is granted limited access to your organization's resources.&#x20;
  * Permissions to the resources of your organization are controlled by assigning [scopes](/cmp/developer-resources/api/credential-management-v1-apis-calm/account-updater-v1/api-reference-v1/account-updater-scopes-v1) to the service account.
* Each [CMP Account](/cmp/platform/cmp-account) is uniquely identified by a Tenant ID (also referred to as a *Vault ID* or *Account ID*). CMP Accounts are accessed programmatically using Service Account credentials.
* You can generate a Service Account in the dashboard or create one using the VGS Command Line Interface (CLI)

\
**Generate a Service Account through UI:**

<details>

<summary><strong>Generate a Service Account through the CMP Dashboard:</strong></summary>

* Navigate to the Developer Tools section of your [CMP Dashboard](https://dashboard.verygoodsecurity.com/cmp) and select the 'Service accounts' tab
* Click the "Create New" button.

<figure><img src="/files/xnkmTvsDRIz6JQZT8rtJ" alt=""><figcaption></figcaption></figure>

* Add the following scopes to provide CMP application access to Network Tokens and Account Updater:

| Scope                                                                                                                                                                    | Permission                                                                                                                                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cards:write                                                                                                                                                              | Required to create a card in VGS and to enroll or unenroll it in the VGS account updater.                                                                                                                                          |
| cards:read                                                                                                                                                               | Required to retrieve card details and account updater information if the card is enrolled.                                                                                                                                         |
| network-tokens:write                                                                                                                                                     | Required to enroll and delete a card in VGS network tokens.                                                                                                                                                                        |
| network-tokens:read                                                                                                                                                      | Required to retrieve network token information if the card is enrolled.                                                                                                                                                            |
| cards:read-pci                                                                                                                                                           | Required to retrieve sensitive card data (PAN and [CVC](#heading-title-text)). Applicable to clients that are PCI-compliant.                                                                                                       |
| 3ds:write                                                                                                                                                                | Required to initiate or manage [3DS](/cmp/products-and-services/3ds) device fingerprinting/initialize and authentication.                                                                                                          |
| <p>cert-manager:write</p><p><br>organization-users:read</p><p><br>organization-users:write</p><p><br>rules:admin</p><p><br>sub-accounts:admin</p><p><br>vaults:write</p> | Required to generate the Apple Pay [certificate](https://docs.verygoodsecurity.com/cmp/payment-credentials/apple-pay/create-card-apple-pay-wallet-decryption#setting-up-your-apple-certificates) used to decrypt Apple Pay tokens. |

**Note**: When CMP accounts are configured, they are configured with an existing account-tenant relationship. This means that service accounts created for a CMP account do not require the extra step to target a specific tenant/vault.

</details>

<details>

<summary><strong>Generate a Service Account through the VGS Vault Dashboard:</strong></summary>

* Navigate to the Service Accounts section of your [Vault Dashboard](https://dashboard.verygoodsecurity.com): *Vault > Organization > Service Accounts.*
* Click on the "Create New" button.

<figure><img src="/files/QB9Tir8VNXBf63mZXqYi" alt=""><figcaption></figcaption></figure>

* Select your desired Tenant/Vault and add the following scopes to provide CMP application access to Network Tokens and Account Updater:

| Scope                                                                                                                                                                    | Permission                                                                                                                                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cards:write                                                                                                                                                              | Required to create a card in VGS and to enroll or unenroll it in the VGS account updater.                                                                                                                                          |
| cards:read                                                                                                                                                               | Required to retrieve card details and account updater information if the card is enrolled.                                                                                                                                         |
| network-tokens:write                                                                                                                                                     | Required to enroll and delete a card in VGS network tokens.                                                                                                                                                                        |
| network-tokens:read                                                                                                                                                      | Required to retrieve network token information if the card is enrolled.                                                                                                                                                            |
| cards:read-pci                                                                                                                                                           | Required to retrieve sensitive card data (PAN and [CVC](#heading-title-text)). Applicable to clients that are PCI-compliant.                                                                                                       |
| 3ds:write                                                                                                                                                                | Required to initiate or manage [3DS](/cmp/products-and-services/3ds) device fingerprinting/initialize and authentication.                                                                                                          |
| <p>cert-manager:write</p><p><br>organization-users:read</p><p><br>organization-users:write</p><p><br>rules:admin</p><p><br>sub-accounts:admin</p><p><br>vaults:write</p> | Required to generate the Apple Pay [certificate](https://docs.verygoodsecurity.com/cmp/payment-credentials/apple-pay/create-card-apple-pay-wallet-decryption#setting-up-your-apple-certificates) used to decrypt Apple Pay tokens. |

</details>

***

<details>

<summary>Extra Context: Accessing and Handling CVC</summary>

Card Verification Code (CVC) is a security measure, typically a three-digit number on the back of the card (or four digits on some cards like American Express). It will be applicable for Clients that desire to perform transactions on behalf of their customers (MIT) and also use the CVC as part of transaction authorization upstream with their PSPs.

This is also applicable for VGS clients who want to use VGS Collect with CMP and use the PAN and CVC. Clients can directly integrate with the API. Clients can perform transactions using CVC, in addition to PAN.

Clients can store CVC in their account in a volatile way for a short period of time and it can be used multiple times during that period. Clients are enabled for CVC by default.

When a client is PCI-Client and the `cards:read-pci` scope is added, these are the expected fields:

* PAN
* PAN Alias
* CVC
* CVC Alias
* CVC Status

When a client is not PCI-Client and the `cards:read-pci` is *not* added, these are the expected fields:

* PAN
* CVC
* CVC Status

</details>

\
\
**Generate a Service Account through CLI:**

Execute the sample code below, which will create `credentials.yaml` file:

```bash
vgs generate service-account -t calm --var vault_id=<your_vault_id> credentials.yamlBash
```

### 2. Generate Access Token <a href="#id-2-generate-access-token" id="id-2-generate-access-token"></a>

To authenticate with the [CMP APIs](/cmp/developer-resources/api), you should use the CLIENT\_ID and CLIENT\_SECRET generated in the [previous step](#id-1-generate-service-account) to create an `access_token`.

```bash
curl -X POST \
     -d "client_id=<CLIENT_ID>" \
     -d "client_secret=<CLIENT_SECRET>" \
     -d "grant_type=client_credentials" \    
      "https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token"Bash
```

The generated token can now be used with the CMP APIs. Please note that this `access_token` is valid only for 20 minutes. After expiry, you can generate a new access token using the same process. `refresh_token` should not be used. Pass the created `access_token` as an Authorization: `Bearer ${VGS_ACCESS_TOKEN}` header in each API call.

### 3. Generate Access Credentials <a href="#id-3-generate-access-credentials" id="id-3-generate-access-credentials"></a>

To create access credentials, go to the [Vault Dashboard](https://dashboard.verygoodsecurity.com/) *> Vault > Vault Settings > Access Credentials* and press the "Generate Credentials" button. When Access Credentials are generated, you will be prompted to download them.

<figure><img src="/files/tvaQLXkUzlzqyhvVmbDa" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note that access credentials’ secrets can only be viewed at the time of generation. You can download them to keep them safe.
{% endhint %}

If you lose these credentials, you can generate a new pair following the same process.

<br>


# VGS for Platforms (Multi-MID) - Implementation Guide

Enterprise Card Management for Platform Organizations

## Multi-MID implementation overview

Use this guide to implement CMP for platforms that manage multiple merchant IDs.

CMP centralizes card lifecycle management while preserving merchant-specific service configuration.

### Introduction

#### What is CMP?

The VGS [Credential Management Platform (CMP)](/cmp) manages payment credentials across their lifecycle.

CMP creates a Card Object, or `card_id`, for each card. That object becomes the reference point for Network Tokens, Account Updater, and 3D Secure.

{% hint style="info" %}
Start with [Merchant Service Onboarding](/cmp/platform/vgs-for-platforms-multi-mid-merchant-service-onboarding) if you still need to choose your merchant structure, TRID strategy, or tenant model.
{% endhint %}

***

### Platform account model

In this model, your organization operates as the platform.

You manage sub-merchants, service accounts, and CMP services from a central organization while keeping merchant context separate where required.

#### High-level solution architecture

![](/files/CSXtpFjsnONiEwJ4z1d2)

{% hint style="info" %}
Each underlying merchant must be enrolled separately.

Each enrolled merchant gets its own CMP account and service configuration under the parent organization.
{% endhint %}

Before implementation, confirm your onboarding model, tenant structure, and TRID strategy. For those details, see [VGS for Platforms (Multi-MID) - Merchant Service Onboarding](/cmp/platform/vgs-for-platforms-multi-mid-merchant-service-onboarding).

***

### Authentication

### Authentication

#### Create a Service Account

The VGS API uses the OAuth 2.0 client credentials flow.

Create a service account and assign the scopes required for cards, accounts, network tokens, and merchants.

For setup details, see [Authentication](/cmp/platform/authentication).

This generates your `client_id` and `client_secret`.

{% hint style="warning" %}
Copy the credentials immediately. The `client_secret` is shown only once.
{% endhint %}

#### Generate Access Token

To generate the API Access Token flow, see [Generate Access Token](https://docs.verygoodsecurity.com/cmp/platform/authentication#id-2-generate-access-token).

***

### CMP card management

#### Create card

<mark style="color:blue;">**`POST /cards`**</mark>

Create a new card object in CMP.

Each card receives a persistent `card_id`. CMP uses that object to manage services such as Network Tokens and Account Updater within the correct merchant context.

For test values, see [Create Card Testing Guide](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/create-card).

API reference: [POST /cards](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards)

#### Get card

<mark style="color:blue;">**`GET /cards/{card_id}`**</mark>

Retrieve card details by `card_id`.

Use this response to inspect card state, token status, and updater status.

{% hint style="info" %}
Network Token test values work only in sandbox.
{% endhint %}

API reference: [GET /cards/{card\_id}](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#get-cards-card_id)

#### Core card testing scenarios

<table data-header-hidden><thead><tr><th width="66.96875"></th><th width="166.3359375"></th><th width="136.15234375"></th><th></th><th></th></tr></thead><tbody><tr><td>#</td><td><strong>API Endpoint</strong></td><td><strong>Test Scenario</strong></td><td><strong>Steps to Verify</strong></td><td><strong>Expected Outcome</strong></td></tr><tr><td>1.1</td><td>POST /cards</td><td>Successful Creation &#x26; Enrollment (Happy Path)</td><td>Use mock card <mark style="color:$success;"><code>5100260000019206</code></mark></td><td><code>201</code> Created. Card object created. AU and NT enrollment successful.</td></tr><tr><td>1.2</td><td>POST /cards</td><td>Creation Success, Enrollment Failure</td><td>Use mock card <mark style="color:$success;background-color:$success;"><code>5100260000009207</code></mark></td><td><code>201</code> Created. Card object created. AU and NT enrollment failed.</td></tr><tr><td>1.3</td><td>POST /cards</td><td>Required Field Validation</td><td>Send a request with a missing required field or invalid value, such as month `13`.</td><td><code>422</code> Unprocessable Entity.</td></tr><tr><td>1.4</td><td>POST /cards</td><td>Internal Service Error (5xx)</td><td>Use mock card <mark style="color:$success;"><code>5100260000019214</code></mark></td><td><code>500</code> Internal Server Error. Integration handles unexpected server-side errors.</td></tr><tr><td>1.5</td><td>GET /cards/{card_id}</td><td>Successful Retrieval (Active Card)</td><td>Use the `card_id` from test `1.1`.</td><td><code>200</code> OK. Full card object returned, including tokenized ID and metadata.</td></tr><tr><td>1.6</td><td>GET /cards/{card_id}</td><td>Card Not Found</td><td>Use a non-existent or improperly formatted <code>card_id</code>.</td><td><code>404</code> Not Found. Integration handles attempts to access a missing resource.</td></tr></tbody></table>

***

### Network Tokens

#### Provision network token

<mark style="color:blue;">**`POST /cards/{card_id}/network-tokens`**</mark>

Provision a network token for a card.

In sandbox, provisioning starts automatically when you create a card. If a token already exists, CMP skips duplicate provisioning.

API reference: [POST /cards/{card\_id}/network-tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-network-tokens)

#### Request cryptogram

<mark style="color:blue;">**`POST /cards/{card_id}/cryptogram`**</mark>

Generate a cryptogram for a tokenized card.

Use this endpoint for real-time purchase flows. Include the required amount, currency, transaction type, and cryptogram type.

API reference: [POST /cards/{card\_id}/cryptogram](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-cryptogram)

#### Delete network token

<mark style="color:blue;">**`DELETE /cards/{card_id}/network-tokens`**</mark>

Delete the network token associated with a card.

Once deleted:

* The token is no longer usable for payments.
* CMP stops tracking lifecycle updates.
* Cryptogram generation and token-based flows stop working.

API reference: [DELETE /cards/{card\_id}/network-tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#delete-cards-card_id-network-tokens)

***

### Account Updater

#### Subscribe

<mark style="color:blue;">**`POST /cards/{card_id}/card-update-subscriptions`**</mark>

Subscribe a card to Account Updater.

In sandbox, this happens automatically when you create a card. Duplicate subscriptions are ignored.

API reference: [POST /cards/{card\_id}/card-update-subscriptions](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-card-update-subscriptions)

#### Unsubscribe

<mark style="color:blue;">**`DELETE /cards/{card_id}/card-update-subscriptions`**</mark>

Remove the card from Account Updater tracking.

After unsubscription:

* CMP no longer receives updates for the card.
* The card’s AU object is removed.
* The card is treated as unenrolled.

API reference: [DELETE /cards/{card\_id}/card-update-subscriptions](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#delete-cards-card_id-card-update-subscriptions)

***

### Environment configuration for webhooks

Ensure your webhook notifications are configured in the VGS Dashboard with the correct endpoint URL.

Use distinct production webhook endpoints separate from sandbox.

**Account Updater webhook events**

Subscribe to all [Account Updater webhook events](https://docs.verygoodsecurity.com/cmp/developer-resources/notifications#cmp-account-updater-events).

**Network Token webhook events**

Subscribe to all [Network Token events](https://docs.verygoodsecurity.com/cmp/api-dev/network-token-events#network-tokens-webhooks).

{% hint style="info" %}
For setup instructions, see [Webhook Notifications](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/webhook-notifications).
{% endhint %}

***

### Webhook integration testing

These tests ensure your system correctly receives, verifies, and processes asynchronous update notifications from VGS.

{% hint style="info" %}
For additional test values, see [On-Demand Updates Testing](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/on-demand-updates#test-cards-and-expected-responses). Also see the dedicated webhook guides for [Account Updater](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/account-updater-webhooks) and [Network Tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/network-tokens-webhooks).
{% endhint %}

#### Account Updater webhooks

<table data-header-hidden><thead><tr><th width="76.4140625"></th><th width="173.3125"></th><th width="132.75390625"></th><th width="184.3203125"></th><th></th></tr></thead><tbody><tr><td>#</td><td>Event Type</td><td>Test Scenario</td><td>Steps to Verify</td><td>Expected Outcome</td></tr><tr><td>3.1</td><td><mark style="color:blue;"><strong><code>cmp_card.updated</code></strong></mark></td><td>Card Updated</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>4327390068355738</code></mark> or <mark style="color:$success;"><code>5522351100054522</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.2</td><td><mark style="color:blue;"><strong><code>cmp_card.enrolled</code></strong></mark></td><td>Card Enrolled</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.3</td><td><mark style="color:blue;"><strong><code>cmp_card.expired</code></strong></mark></td><td>Card Expired</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2223520127577835</code></mark> or <mark style="color:$success;"><code>5522351100074512</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.4</td><td><mark style="color:blue;"><strong><code>cmp_card.updated</code></strong></mark></td><td>Card Closed (updated event)</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>4403933787254356</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and marks the card as inactive or closed in your system.</td></tr><tr><td>3.5</td><td><mark style="color:blue;"><strong><code>cmp_card.closed</code></strong></mark></td><td>Card Closed</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5120350100064594</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and marks the card as inactive or closed in your system.</td></tr></tbody></table>

#### Network Token webhooks

<table data-header-hidden><thead><tr><th width="74.76953125"></th><th width="174.2734375"></th><th width="132.96875"></th><th width="185.09375"></th><th></th></tr></thead><tbody><tr><td>#</td><td><strong>Event Type</strong></td><td><strong>Test Scenario</strong></td><td><strong>Steps to Verify</strong></td><td><strong>Expected Outcome</strong></td></tr><tr><td>3.6</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Provisioned</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook with state `ACTIVE` and updates your system to reflect an active Network Token.</td></tr><tr><td>3.7</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Provisioned</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5120350100064594</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook with state `ACTIVE` and updates your system to reflect an active Network Token.</td></tr><tr><td>3.8</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Failed</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook with state `FAILED` and updates your system to reflect a failed Network Token.</td></tr><tr><td>3.9</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Suspended or Deleted</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5100260000009223</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook with state `DELETED` and marks the token as inactive in your system.</td></tr></tbody></table>

#### Webhook acknowledgment

<table data-header-hidden><thead><tr><th width="74.78515625"></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>#</td><td>Event Type</td><td>Steps to Verify</td><td>Expected Outcome</td></tr><tr><td>3.10</td><td>Any webhook payload</td><td>Receive any webhook payload from VGS.</td><td>Your server immediately responds with a <code>200</code> OK HTTP status code to prevent VGS from retrying the notification.</td></tr></tbody></table>

{% hint style="warning" %}
Always respond with `200 OK` immediately after receiving a webhook. VGS retries delivery if acknowledgment is delayed.
{% endhint %}

***

### 3D Secure

Use CMP to run 3DS data-only checks or full step-up authentication with issuers.

#### 3DS initialization

<mark style="color:blue;">**`POST /cards/{card_id}/3ds/initialize`**</mark>

1. Call the [3DS initialize endpoint](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-initialize), which may return an iframe for device fingerprinting. If no iframe is returned, initialization is not required, and authentication can proceed immediately.
2. Render the iframe on the front end as soon as it is received from VGS. You can also load it in a background frame while the cardholder waits.
3. Submit the iframe form to start device fingerprinting.
4. Start a 10-second timer after receiving the iframe. Wait until you receive either the asynchronous fingerprinting response or the timer expires before sending the authentication request.

{% hint style="info" %}
The iframe can run in the background so the cardholder experience is not interrupted.
{% endhint %}

#### 3DS authentication

<mark style="color:blue;">**`POST /cards/{card_id}/3ds/authenticate`**</mark>

Call the [3DS authenticate endpoint](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-authenticate) at purchase time.

Send the required `type` parameter to choose the 3DS flow:

* [Data-only](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-frictionless-flow) - Frictionless flow. The result is returned synchronously.
* [Challenge](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-challenge-flow) - A user challenge is triggered. The final result is delivered through the configured webhook.

API reference: [3D Secure API](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds)

***

### Production go-live checklist

Before going live, complete each section below to ensure your production environment is fully configured and validated.

#### Production service account

Generate a new service account in your production organization for CMP.

**Validate access to the live API**

* [ ] Check the list of [VGS Live IPs](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/vgs-ip-addresses)
* [ ] Connect your system to the Live API at [https://vgsapi.com](https://docs.verygoodsecurity.com/cmp/developer-resources/api)

**Access scopes**

* [ ] Assign all necessary [OAuth 2.0 scopes](https://docs.verygoodsecurity.com/cmp/platform/authentication#id-1-generate-service-account) — cards, accounts, network tokens, and merchants.

**Authentication validation**

* [ ] Confirm your backend can successfully generate a production access token.

***

#### Environment configuration for webhooks

* [ ] Ensure your server responds with `200 OK` to prevent retries. See the [webhook management guide](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/webhook-notifications#manage-webhooks).
* [ ] Verify CMP, Network Tokens, and Account Updater are enabled for each production tenant in scope.
* [ ] Confirm production webhook endpoints are separate from sandbox endpoints.

***

#### Core testing scenarios for live validation

* [ ] Card creation: Call [POST /cards](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#post-cards) to register a new card and confirm the `card_id` and `pan_alias`.
* [ ] Card retrieval: Use [GET /cards/{card\_id}](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#get-cards-card_id) to verify the full card object and metadata.
* [ ] Network Token provisioning: Verify that eligible cards successfully initiate enrollment. Validate by listening to the webhook or using Get Card.
* [ ] Cryptogram fetching: Confirm `POST /cards/{card_id}/cryptogram` returns a valid cryptogram.

***


# VGS for Platforms (Multi-MID) - Merchant Service Onboarding

Enterprise Card Management for Platform Organizations

## Multi-MID merchant service onboarding

Use this guide to plan CMP onboarding for a multi-MID platform model.

It covers merchant structure, service accounts, TRIDs, and tenant design.

### Introduction

Start by deciding how each sub-merchant enrolls with the card networks.

That decision drives your account model, tenant model, and service setup.

{% hint style="info" %}
Continue to [VGS for Platforms (Multi-MID) - Implementation Guide](/cmp/platform/vgs-for-platforms-multi-mid-implementation-guide) after you finalize your merchant structure, TRID strategy, and tenant model.
{% endhint %}

***

### Onboarding flow

{% stepper %}
{% step %}

### Understand the CMP hierarchy

CMP supports platforms, PayFacs, merchant aggregators, and ISVs that manage credentials across multiple merchants through one integration.

Before you choose an onboarding model, align on the three core CMP entities:

* **Organization** — Your top-level company entity. It contains users, accounts, service accounts, and billing relationships.
* **Account** — Your merchant-level operating entity. It is where merchant enrollment happens and where CMP services are managed.
* **Tenant** — Your storage and configuration boundary. Token storage, service configuration, and scoped access are tenant-specific.

In a multi-merchant model, platforms often create one CMP account per merchant.
{% endstep %}

{% step %}

### Choose a multi-merchant structure

Sub-merchants that register individually with the networks, or exceed volume thresholds, usually need their own CMP account, tenant, and service account.

Platforms can choose from several supported models.

{% tabs %}
{% tab title="Dedicated Account" %}
**Dedicated account per merchant**

Each merchant gets its own CMP account, tenant, and service account.

{% hint style="info" %}
Best for merchants above TRID volume thresholds.
{% endhint %}
{% endtab %}

{% tab title="Shared Account" %}
**Shared account**

Multiple sub-merchants share one CMP account and one tenant under a single TRID.

This works best for merchants below the thresholds.

If your platform acts as a PayFac, you can often process low-volume merchants under the highest-level MID. Otherwise, CMP usually maps one merchant to one MID.

{% hint style="info" %}
The same PAN enrolled across multiple merchants produces a different `card_id` for each merchant.

Plan to reconcile lifecycle updates across those card objects.
{% endhint %}
{% endtab %}

{% tab title="Universal CMP Account" %}
**Universal CMP account**

This is the Master Data Tenant pattern.

A designated main tenant acts as the shared token store and central index for cross-merchant data reuse.

This pattern lets you associate an existing card record with additional merchants without duplicating the full storage model across separate tenants.

{% hint style="info" %}
Direct CMP aliasing is tenant-specific.

Use this pattern when you need cross-merchant deduplication.
{% endhint %}
{% endtab %}

{% tab title="Hybrid Model" %}
**Hybrid model**

This combines shared and dedicated structures.

Low-volume sub-merchants use a shared account and shared TRID.

High-volume sub-merchants use dedicated CMP accounts, dedicated tenants, and dedicated TRIDs.

{% hint style="info" %}
This is common for PayFac and ISV structures.
{% endhint %}
{% endtab %}
{% endtabs %}

| Model                 | Best for                                             | Tenant                                                                                 | Service account                                                                         | TRID                                                                    |
| --------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| Dedicated account     | Simple multi-MID structures on one platform          | One tenant per merchant                                                                | One per merchant tenant                                                                 | One per merchant                                                        |
| Shared account        | Low-volume sub-merchants under TRID thresholds       | One shared tenant                                                                      | One shared account, or one per sub-merchant in the same tenant                          | One shared platform TRID                                                |
| Universal CMP account | Platforms that need cross-merchant token portability | One main tenant plus sub-merchant CMP accounts                                         | One per sub-merchant CMP account, plus one for the main tenant                          | Shared when merchants stay below thresholds                             |
| Hybrid model          | ISVs and PayFacs with mixed merchant sizes           | Shared tenant for low-volume merchants and dedicated tenants for high-volume merchants | Shared access for low-volume merchants and dedicated accounts for high-volume merchants | Shared for low-volume merchants and dedicated for high-volume merchants |

#### Additional considerations

* **MoR vs. PayFac** — Merchant of Record platforms can register on behalf of sub-merchants and may use a shared tenant. PayFacs can process low-volume sub-merchants under the highest-level MID.
* **Brands are not merchants** — If multiple brands share credentials, each brand still needs its own merchant registration, tenant, and TRID.
* **Shared PANs create multiple card objects** — If the same PAN is enrolled across multiple merchants, CMP creates a different `card_id` for each merchant.
  {% endstep %}

{% step %}

### Register network services

To start network service registration, a VGS team member shares the **CMP Enablement Form** and password through 1Password.

{% hint style="info" %}
The form submitter needs CMP Dashboard access.

Only verified users in your VGS organization receive access. Organization administrators can invite additional users as needed.

See [Manage Users](https://docs.verygoodsecurity.com/enterprise-platform/access-management/manage-users).
{% endhint %}

Select the CMP services you want to enable in the form.

If you do not have all network details yet, save the form as a draft and finish it later.

Merchants above network thresholds must enroll individually with their own network values.

Merchants below the thresholds usually do not need a separate form.

#### Enrollment rules by service

**Network Tokens**

* For **Visa**, **Mastercard**, and **Discover**, sub-merchants can enroll under a shared platform-level TRID.
* PayFacs can process low-volume sub-merchants under the highest-level MID.

**Account Updater**

* Sub-merchants below the thresholds can enroll with the platform at the TRID level.
* Visa uses a threshold of under `$1M` per year.
* Mastercard uses a threshold of under `$10M` per year.
* Merchants above those thresholds must enroll individually.

#### Network values required during onboarding

| Scope             | Network Tokens                                                                                                                                                                    | Account Updater                                                                                                                                                                   |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Main organization | <p>Visa — optional <code>CAID + BIN</code><br>Mastercard — optional <code>Acquirer BIN/ID</code><br>Amex — required <code>SEID</code><br>Discover — required <code>MID</code></p> | Not used                                                                                                                                                                          |
| Sub-accounts      | <p>Visa — optional <code>CAID + BIN</code><br>Mastercard — optional <code>Acquirer BIN/ID</code><br>Amex — required <code>SEID</code><br>Discover — required <code>MID</code></p> | <p>Visa — required <code>CAID + BIN</code><br>Mastercard — required <code>Acquirer BIN/ID</code><br>Amex — required <code>SEID</code><br>Discover — required <code>MID</code></p> |

{% hint style="info" %}
Only Direct Account merchants are eligible for Network Tokens and Account Updater.

OptBlue participants are not supported.

VGS verifies eligibility by submitting the merchant SEID to Amex and confirming Direct status and, when available, Top of Chain.
{% endhint %}

#### 3D Secure

If each merchant processes transactions as the merchant of record, place each merchant in its own CMP account and tenant for 3DS.

Merchants can still live under one shared organization.

VGS enables 3DS at the CMP account level. A single shared merchant setup does not provide the merchant-level data segregation required for individual Merchants of Record.
{% endstep %}

{% step %}

### Configure service accounts

#### How service accounts work in CMP

CMP requires a separate service account for each merchant that uses a dedicated tenant.

The dashboard does not support one service account across multiple sub-merchants.

Network Token scopes can be assigned to only one tenant per service account.

#### Service account checklist

* [ ] Generate a new production service account for CMP.
* [ ] Validate access to the Live API and confirm VGS Live IPs are allowlisted.
* [ ] Assign the required [OAuth 2.0 scopes](/cmp/platform/authentication): `cards`, `accounts`, `network_tokens`, `merchants`.
* [ ] Confirm your backend can generate a production access token.
  {% endstep %}
  {% endstepper %}

***

### Token Requestor IDs

#### What is a TRID?

A Token Requestor ID, or TRID, is a network-assigned identifier used during Network Token enrollment.

Each network assigns TRIDs per merchant as part of its review process.

VGS does not issue shared or aggregate TRIDs.

#### Network Tokens vs. Account Updater

| Service         | Identifier used                                                             |
| --------------- | --------------------------------------------------------------------------- |
| Network Tokens  | TRID for Visa and Mastercard, `SEID` for Amex, and `MID` for Discover       |
| Account Updater | Acquiring BIN plus `CAID` for Visa, `SEID` for Amex, and `MID` for Discover |

{% hint style="info" %}
Account Updater does not use a TRID.

It uses separate network identifiers for enrollment.
{% endhint %}

#### Volume thresholds for shared TRIDs

Sub-merchants can enroll under a shared platform TRID when they remain within the applicable network thresholds.

| Network    | Threshold             |
| ---------- | --------------------- |
| Visa       | Under `$1M` per year  |
| Mastercard | Under `$10M` per year |
| Discover   | No threshold          |
| Amex       | No threshold          |

Merchants above these thresholds should use a dedicated TRID, dedicated tenant, and dedicated CMP account.

{% hint style="info" %}
Thresholds apply independently by network.

For example, a merchant processing `$7M` in Visa volume and `$4M` in Mastercard volume needs a dedicated TRID for Visa, but can remain on a shared TRID for Mastercard.
{% endhint %}

{% hint style="info" %}

#### Recommended architecture for platforms

The hybrid model is a common fit for ISVs and platforms:

* Enroll lower-volume merchants under a shared platform TRID.
* Register higher-volume merchants individually with dedicated tenants, TRIDs, and CMP accounts.

This balances operational simplicity with network compliance.
{% endhint %}

#### TRID request process by network

| Network    | Method                                     | Speed      |
| ---------- | ------------------------------------------ | ---------- |
| Visa       | API                                        | A few days |
| Mastercard | API                                        | A few days |
| Amex       | Manual. Requires a Direct Merchant `SEID`. | Variable   |
| Discover   | Requires Discover `MID`.                   | Variable   |

***

### Tenant architecture

#### Shared vs. dedicated tenant architecture

Your tenant architecture should match your TRID model.

| Scenario                              | Recommended setup                                           |
| ------------------------------------- | ----------------------------------------------------------- |
| Sub-merchants under volume thresholds | Shared account with a platform TRID                         |
| Sub-merchants above volume thresholds | Dedicated account, dedicated CMP tenant, and dedicated TRID |
| Migrating from a prior VGS setup      | Create a new tenant when possible                           |

#### Migrate from a prior VGS setup

If you are migrating card files from an earlier VGS CALM setup, create a new tenant instead of enabling CMP on an existing tenant when possible.

Reusing an older tenant can inherit a pre-existing merchant ID and create configuration conflicts.

Starting with a new tenant gives you a cleaner onboarding path.

{% hint style="warning" %}
You can migrate existing card files between tenants through an SFTP workflow.

See [Migrating Cards on File to VGS](https://docs.verygoodsecurity.com/vault/guides/migrations) for details.
{% endhint %}

#### How VGS uses the tenant

The tenant is the token store that maps aliases to the underlying PAN.

Because token resolution is tenant-specific, service accounts with Network Token scopes are also tenant-specific.

This means:

* Each merchant with Network Tokens enabled needs a service account scoped to its tenant.
* Multiple low-volume merchants can share a single tenant, but that model requires careful configuration management.

***

### Go-live checks

Before you submit your production onboarding request, confirm the following:

* **Correct tenant selected** — Enable CMP on the correct tenant and environment.
* **Routes promoted to production** — Route configuration does not carry over between environments.
* **Multiple merchants per organization** — If you are onboarding more than one merchant in one organization, ensure `allow_multiple_onboarding: true` is set in the onboarding YAML.
* **Webhook routing** — Confirm Account Updater events route to the correct merchant context. One endpoint does not automatically handle all sub-merchants.


# VGS for Merchants - Implementation Guide

Implement secure card collection, storage, enrichment, and payment flows with VGS.

## Merchant implementation overview

Use this guide to collect, store, enrich, authenticate, and transact with payment data through VGS.

VGS keeps raw card data out of your systems. You work with aliases, card objects, and network tokens instead.

### Introduction

#### What is CMP?

The VGS [Credential Management Platform (CMP)](/cmp) manages payment credentials across their lifecycle.

CMP creates a Card Object, or `card_id`, for each card. That object becomes the reference point for Network Tokens, Account Updater, and 3D Secure.

***

### High-level solution architecture

<div data-with-frame="true"><figure><img src="/files/bTQtgO8l10rusA7NhPCp" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
This diagram shows a typical merchant flow with VGS. You collect, store, enrich, authenticate, and route payment data without directly handling raw PAN.
{% endhint %}

***

### Authentication

#### Create a Service Account

The VGS API uses the OAuth 2.0 client credentials flow.

Create a service account and assign the scopes required for cards, accounts, network tokens, and merchants.

For setup details, see [Authentication](/cmp/platform/authentication).

This generates your `client_id` and `client_secret`.

{% hint style="warning" %}
Copy the credentials immediately. The `client_secret` is shown only once.
{% endhint %}

#### Generate Access Token

To generate the API Access Token flow, see [Generate Access Token](https://docs.verygoodsecurity.com/cmp/platform/authentication#id-2-generate-access-token).

***

### Collect data

<figure><img src="/files/luxF6r4LYDdY3hqu6anJ" alt=""><figcaption></figcaption></figure>

#### Browser Card capture with VGS Collect

[VGS Collect ](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/index#why-vgs-collect)captures card data in the browser and sends it directly to CMP.

Your backend never receives raw PAN or CVC. It only receives `card_id`, `pan_alias`, and `cvc_alias`.

**Prerequisites**

* Allow these domains in your CSP:
  * `js.verygoodvault.com`
  * `vgs-collect-keeper.apps.verygood.systems`
  * `sandbox.vgsapi.com`
* Create a service account with the `cards-write` scope.
* Generate an access token.
* Initialize VGS Collect for your environment.
* Configure secure fields for PAN, expiration date, and CVC.

{% hint style="info" %}

#### Card creation flow

```
VGS Collect.js
     ↓
Secure fields capture PAN / CVC / expiry
     ↓
form.createCard() sends data directly to CMP
     ↓
CMP returns: card_id + pan_alias + cvc_alias
     ↓
Your backend stores card_id and aliases only
```

{% endhint %}

**Alias behavior**

* `pan_alias` is persistent.
* `cvc_alias` is volatile.
* Both aliases use standard VGS tokenization.
* CMP returns the same `pan_alias` for the same card.

***

#### Receive Card Securely via HTTPS Proxy

If partners send raw card data to you, use a VGS inbound route with a [custom hostname](https://docs.verygoodsecurity.com/vault/http-proxy/inbound-connection/custom-hostnames).

This keeps raw PAN out of your environment.

**How it works**

Partners send card data to a VGS-managed endpoint on your domain, such as `vault.acme.com`.

VGS tokenizes PAN and CVC in transit. Your backend receives aliases only.

{% hint style="info" %}

#### Convert aliases into a CMP card

After your backend receives `pan_alias`, create the card object in CMP:

```json
POST /cards
{
  "pan": "<pan_alias>",
  "expiration_month": "12",
  "expiration_year": "2027"
}
```

CMP returns `card_id` and `pan_alias`.

From there, you can use Network Tokens, Account Updater, and 3DS.
{% endhint %}

***

### Store and enroll cards in CMP

Once you have a `card_id`, you can provision a network token and request cryptograms for payment flows.

<figure><img src="/files/xkk1v3Z176vXpQvFhokL" alt=""><figcaption></figcaption></figure>

#### Network token provisioning

```http
POST /cards/{card_id}/network-tokens
```

* The card network provisions the token.
* CMP sends a webhook when the token becomes active.
* You can retrieve the token from `GET /cards/{card_id}` in `nt_pan`.

#### Cryptogram generation for CIT

```http
POST /cards/{card_id}/cryptogram
```

* The response includes a single-use cryptogram, network token, and ECI.
* Use that payload to build the `tokenizedCard` request to your PSP.
* Generate a new cryptogram for each transaction.

#### Recurring and MIT transactions

Merchant-initiated transactions do not require a cryptogram.

```http
GET /cards/{card_id}
```

Use the returned `nt_pan` in your PSP request when the token is available.

***

### CMP card management

#### Create card

<mark style="color:blue;">**`POST /cards`**</mark>

Create a new card object in CMP.

Each card receives a persistent `card_id`. CMP uses that object to manage services such as Network Tokens and Account Updater.

For test values, see [Create Card Testing Guide](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/create-card).

API reference: [POST /cards](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards)

#### Get card

<mark style="color:blue;">**`GET /cards/{card_id}`**</mark>

Retrieve card details by `card_id`.

Use this response to inspect card state, token status, and updater status.

API reference: [GET /cards/{card\_id}](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#get-cards-card_id)

#### Core card testing scenarios

<table data-header-hidden><thead><tr><th width="76.546875"></th><th width="152.0859375"></th><th width="136.15234375"></th><th></th><th></th></tr></thead><tbody><tr><td>#</td><td><strong>API Endpoint</strong></td><td><strong>Test Scenario</strong></td><td><strong>Steps to Verify</strong></td><td><strong>Expected Outcome</strong></td></tr><tr><td>1.1</td><td>POST /cards</td><td>Successful Creation &#x26; Enrollment (Happy Path)</td><td>Use mock card <mark style="color:$success;"><code>5100260000019206</code></mark></td><td><code>201</code> Created. Card object created. AU and NT enrollment successful.</td></tr><tr><td>1.2</td><td>POST /cards</td><td>Creation Success, Enrollment Failure</td><td>Use mock card <mark style="color:$success;background-color:$success;"><code>5100260000009207</code></mark></td><td><code>201</code> Created. Card object created. AU and NT enrollment failed.</td></tr><tr><td>1.3</td><td>POST /cards</td><td>Required Field Validation</td><td>Send a request with a missing required field or invalid value (e.g., month 13).</td><td><code>422</code> Unprocessable Entity.</td></tr><tr><td>1.4</td><td>POST /cards</td><td>Internal Service Error (5xx)</td><td>Use mock card <mark style="color:$success;"><code>5100260000019214</code></mark></td><td><code>500</code> Internal Server Error. Integration handles unexpected server-side errors.</td></tr><tr><td>1.5</td><td>GET /cards/{card_id}</td><td>Successful Retrieval (Active Card)</td><td>Use the card_id from test 1.1.</td><td><code>200</code> OK. Full card object returned, including tokenized ID and metadata.</td></tr><tr><td>1.6</td><td>GET /cards/{card_id}</td><td>Card Not Found</td><td>Use a non-existent or improperly formatted <code>card_id</code>.</td><td><code>404</code> Not Found. Integration handles attempts to access a missing resource.</td></tr></tbody></table>

***

### Network Tokens

#### Provision network token

<mark style="color:blue;">**`POST /cards/{card_id}/network-tokens`**</mark>

Provision a network token for a card.

In sandbox, provisioning starts automatically when you create a card. If a token already exists, CMP skips duplicate provisioning.

API reference: [POST /cards/{card\_id}/network-tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-network-tokens)

#### Request cryptogram

<mark style="color:blue;">**`POST /cards/{card_id}/cryptogram`**</mark>

Generate a cryptogram for a tokenized card.

Use this endpoint for real-time purchase flows. Include the required amount, currency, transaction type, and cryptogram type.

API reference: [POST /cards/{card\_id}/cryptogram](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-cryptogram)

#### Delete network token

<mark style="color:blue;">**`DELETE /cards/{card_id}/network-tokens`**</mark>

Delete the network token associated with a card.

Once deleted:

* The token is no longer usable for payments.
* CMP stops tracking lifecycle updates.
* Cryptogram generation and token-based flows stop working.

API reference: [DELETE /cards/{card\_id}/network-tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#delete-cards-card_id-network-tokens)

***

### Account Updater

#### Subscribe

<mark style="color:blue;">**`POST /cards/{card_id}/card-update-subscriptions`**</mark>

Subscribe a card to [Account Updater](/cmp/products-and-services/account-updater).

In sandbox, this happens automatically when you create a card. Duplicate subscriptions are ignored.

API reference: [POST /cards/{card\_id}/card-update-subscriptions](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-card-update-subscriptions)

#### Unsubscribe

<mark style="color:blue;">**`DELETE /cards/{card_id}/card-update-subscriptions`**</mark>

Remove the card from Account Updater tracking.

After unsubscription:

* CMP no longer receives updates for the card.
* The card’s AU object is removed.
* The card is treated as unenrolled.

API reference: [DELETE /cards/{card\_id}/card-update-subscriptions](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#delete-cards-card_id-card-update-subscriptions)

***

### Webhook integration testing

These tests ensure your system correctly receives, verifies, and processes asynchronous update notifications from VGS.

{% hint style="info" %}
For additional test values, see [On-Demand Updates Testing](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/on-demand-updates#test-cards-and-expected-responses). Also see the dedicated webhook guides for [Account Updater](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/account-updater-webhooks) and [Network Tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/network-tokens-webhooks).
{% endhint %}

#### Account Updater webhooks

<table data-header-hidden><thead><tr><th width="76.4140625"></th><th width="173.3125"></th><th width="132.75390625"></th><th width="184.3203125"></th><th></th></tr></thead><tbody><tr><td>#</td><td>Event Type</td><td>Test Scenario</td><td>Steps to Verify</td><td>Expected Outcome</td></tr><tr><td>3.1</td><td><mark style="color:blue;"><strong><code>cmp_card.updated</code></strong></mark></td><td>Card Updated</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>4327390068355738</code></mark> or <mark style="color:$success;"><code>5522351100054522</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.2</td><td><mark style="color:blue;"><strong><code>cmp_card.enrolled</code></strong></mark></td><td>Card Enrolled</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.3</td><td><mark style="color:blue;"><strong><code>cmp_card.expired</code></strong></mark></td><td>Card Expired</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2223520127577835</code></mark> or <mark style="color:$success;"><code>5522351100074512</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and updates the card details (PAN/Expiry) in your database.</td></tr><tr><td>3.4</td><td><mark style="color:blue;"><strong><code>cmp_card.updated</code></strong></mark></td><td>Card Closed (updated event)</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>4403933787254356</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and marks the card as inactive/closed in your system.</td></tr><tr><td>3.5</td><td><mark style="color:blue;"><strong><code>cmp_card.closed</code></strong></mark></td><td>Card Closed</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5120350100064594</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook and marks the card as inactive/closed in your system.</td></tr></tbody></table>

#### Network Token webhooks

<table data-header-hidden><thead><tr><th width="74.76953125"></th><th width="174.2734375"></th><th width="132.96875"></th><th width="185.09375"></th><th></th></tr></thead><tbody><tr><td>#</td><td><strong>Event Type</strong></td><td><strong>Test Scenario</strong></td><td><strong>Steps to Verify</strong></td><td><strong>Expected Outcome</strong></td></tr><tr><td>3.6</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Provisioned</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook (state ACTIVE) and updates your system to reflect an active Network Token.</td></tr><tr><td>3.7</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Provisioned</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5120350100064594</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook (state ACTIVE) and updates your system to reflect an active Network Token.</td></tr><tr><td>3.8</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Failed</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>2222690420064582</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook (state FAILED) and updates your system to reflect a failed Network Token.</td></tr><tr><td>3.9</td><td><mark style="color:blue;"><strong><code>cmp_network_token.updated</code></strong></mark></td><td>Token Suspended/Deleted</td><td><p>1. Create a card with mock <mark style="color:$success;"><code>5100260000009223</code></mark></p><p>2. Check your webhook server logs.</p></td><td>Your server receives a webhook (state DELETED) and marks the token as inactive in your system.</td></tr></tbody></table>

#### Webhook acknowledgment

<table data-header-hidden><thead><tr><th width="74.78515625"></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>#</td><td>Event Type</td><td>Steps to Verify</td><td>Expected Outcome</td></tr><tr><td>3.10</td><td>Any webhook payload</td><td>Receive any webhook payload from VGS.</td><td>Your server immediately responds with a <code>200</code> OK HTTP status code to prevent VGS from retrying the notification.</td></tr></tbody></table>

{% hint style="warning" %}
Always respond with a 200 OK immediately upon receiving a webhook. VGS will retry delivery if it does not receive a timely acknowledgment.
{% endhint %}

***

### Card validation and authentication

<figure><img src="/files/alec3MQ6UvdhYMYurF6p" alt=""><figcaption></figcaption></figure>

### 3D Secure

Use CMP to run 3DS data-only checks or full step-up authentication with issuers.

#### 3DS initialization

<mark style="color:blue;">**`POST /cards/{card_id}/3ds/initialize`**</mark>

1. Call the [3DS initialize endpoint](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-initialize), which may return an iframe for device fingerprinting. If no iframe is returned, initialization is not required, and authentication can proceed immediately.
2. Render the iframe on the front end as soon as it is received from VGS. It can also be loaded as an invisible or background frame while the cardholder waits, so the client does not pause for processing.
3. Once you submit the form in the iframe, the device-fingerprinting process begins.
4. Start a 10-second timer after receiving the iframe from VGS, and wait until you receive either the asynchronous device fingerprinting response from VGS or the timer expires (whichever happens first) before sending the authentication request to VGS.

{% hint style="info" %}
The iframe can be rendered in the background so the cardholder experience is not interrupted.
{% endhint %}

#### 3DS authentication

<mark style="color:blue;">**`POST /cards/{card_id}/3ds/authenticate`**</mark>

Call the [3DS authenticate endpoint](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-authenticate) at purchase time.

Send the required `type` parameter to choose the 3DS flow:

* [Data-only](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-frictionless-flow) - Frictionless flow; the result is returned synchronously.
* [Challenge](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-challenge-flow) - A user challenge is triggered, and the final result is delivered via the configured webhook notification.

API reference: [3D Secure API](https://docs.verygoodsecurity.com/cmp/developer-resources/api/3d-secure-3ds)

***

### Payments with Network Token

#### Provision network token

<mark style="color:blue;">**`POST /cards/{card_id}/network-tokens`**</mark>

Provision a network token for a card.

In sandbox, provisioning starts automatically when you create a card. If a token already exists, CMP skips duplicate provisioning.

API reference: [POST /cards/{card\_id}/network-tokens](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-network-tokens)

#### Request cryptogram

<mark style="color:blue;">**`POST /cards/{card_id}/cryptogram`**</mark>

Generate a cryptogram for a tokenized card.

Use this endpoint for real-time purchase flows. Include the required amount, currency, transaction type, and cryptogram type.

API reference: [POST /cards/{card\_id}/cryptogram](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management#post-cards-card_id-cryptogram)

### Payments with PAN Alias (via HTTPS Proxies)

If a network token is unavailable, send `pan_alias` and `cvc_alias` through a VGS [outbound route ](https://docs.verygoodsecurity.com/vault/http-proxy/outbound-connection)to your PSP.

**When to use fallback**

* `nt_status` is `NT_SUSPENDED`, `NT_DELETED`, or not active.
* The cryptogram request fails or times out.
* The card network does not support network tokens for that BIN.

**Fallback flow**

```
Merchant backend
     ↓
Build a payment request with pan_alias + cvc_alias
     ↓
POST to PSP through the VGS outbound route
     ↓
VGS reveals pan_alias → raw PAN
VGS reveals cvc_alias → raw CVC
     ↓
PSP receives raw PAN + CVC
```

> Fallback logic belongs in your application layer. Keep the outbound route focused on secure reveal and forwarding.

**Outbound route configuration**

* Set your PSP as the route upstream.
* Add a reveal filter for `pan_alias`.
* Add a reveal filter for `cvc_alias`.
* Load the outbound route YAML in the VGS Dashboard.

***

### Production go-live checklist

Before going live, complete each section below to ensure your production environment is fully configured and validated.

#### Production service account

Generate a new service account in your production organization for CMP.

**Validate access to the live API**

* [ ] Check the list of [VGS Live IPs](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/vgs-ip-addresses)
* [ ] Connect your system to the Live API at [https://vgsapi.com](https://docs.verygoodsecurity.com/cmp/developer-resources/api)

**Access scopes**

* [ ] Assign all necessary [OAuth 2.0 scopes](https://docs.verygoodsecurity.com/cmp/platform/authentication#id-1-generate-service-account) — cards, accounts, network tokens, and merchants.

**Authentication validation**

* [ ] Confirm your backend can successfully generate a production access token.

***

#### Environment configuration for webhooks

Ensure your webhook notifications are configured in the VGS Dashboard with the correct endpoint URL. Configure distinct production webhook endpoints separate from your sandbox.

For setup instructions, see [Webhook Notifications](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/webhook-notifications).

**Account Updater webhook events**

Subscribe to all [Account Updater webhook events](https://docs.verygoodsecurity.com/cmp/developer-resources/notifications#cmp-account-updater-events):

<table><thead><tr><th width="345.28125">Event</th><th></th><th>When It Occurs</th></tr></thead><tbody><tr><td><code>cmp_au_card.enrolled</code></td><td>Card successfully enrolled in Account Updater</td><td>After a card is enrolled for automatic updates through the AU service.</td></tr><tr><td><code>cmp_au_card.updated</code></td><td>Account number change message</td><td>New account creation, lost/stolen card, card upgrades/downgrades, or portfolio changes.</td></tr><tr><td><code>cmp_au_card.expired</code></td><td>Expiration date change event</td><td>Card expires but retains the same PAN and a new expiration date is issued.</td></tr><tr><td><code>cmp_au_card.closed</code></td><td>Closed account advice</td><td>Issuer reports closure of the cardholder's account.</td></tr><tr><td><code>cmp_au_card.non_participating</code></td><td>Non-participating BIN event</td><td>Cards linked to these BINs will not receive updates through Account Updater.</td></tr><tr><td><code>cmp_au_card.contact_cardholder_advice</code></td><td>Contact cardholder advice</td><td>Issuer indicates something has changed and the merchant should have the customer re-enter the credential.</td></tr><tr><td><code>cmp_au_card.unknown</code></td><td>Account not found from a participating BIN</td><td>Card is eligible for automatic updates, but no match was found.</td></tr><tr><td><code>cmp_au_card.enrollment.failed</code></td><td>AU enrollment failed</td><td>Card fails to enroll in AU (e.g., merchant-not-found errors).</td></tr></tbody></table>

**Network Token webhook events**

Subscribe to all [Network Token events](https://docs.verygoodsecurity.com/cmp/api-dev/network-token-events#network-tokens-webhooks):

<table><thead><tr><th width="278.31640625">Event</th><th>Description</th><th>When It Occurs</th></tr></thead><tbody><tr><td><code>cmp_network_token.updated</code></td><td>Network status changing — generic update event</td><td>Card networks push lifecycle updates.</td></tr><tr><td><code>cmp_network_token.suspended</code></td><td>Network token suspended by the network</td><td>Card network suspends the token (e.g., fraud, issuer action).</td></tr><tr><td><code>cmp_network_token.activated</code></td><td>Network token activated</td><td>Previously suspended token is reactivated.</td></tr><tr><td><code>cmp_network_token.deleted</code></td><td>Network token deleted</td><td>Token deleted by customer request or network action.</td></tr></tbody></table>

**General webhook requirements**

* [ ] Webhook Acknowledgment: Ensure your server responds with a 200 OK to prevent retries. See the [webhook management guide](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/webhook-notifications#manage-webhooks).
* [ ] Service Activation: Verify CMP, Network Tokens, and Account Updater are enabled for your production vault.

***

#### Core testing scenarios for live validation

* [ ] Card Creation: Call [POST /cards](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#post-cards) to register a new card and confirm the card\_id and pan\_alias.
* [ ] Card Retrieval: Use [GET /cards/{card\_id}](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#get-cards-card_id) to verify the full card object and metadata.
* [ ] Network Token Provisioning: Verify that eligible cards successfully initiate enrollment. Validate by listening to the webhook or using Get Cards.
* [ ] Cryptogram Fetching: Confirm POST /cards/{card\_id}/cryptogram returns a valid cryptogram.

***


# VGS for Merchants - Wallet Decrypt Implementation Guide

Decrypt Apple Pay payment tokens with CMP and route payments through the Outbound Proxy.

### Overview

Use this guide to create a [Credential Management Platform](/cmp#vgs-card-management-platform-cmp) card from an encrypted Apple Pay payment token.

CMP decrypts the token, stores the wallet credential, and returns a card object with wallet metadata.

In most merchant flows, your backend stores `card_id` and aliases only.

Wallet Decrypt currently supports **Apple Pay only**.

### Benefits

Use Wallet Decrypt to:

* Keep raw wallet credentials out of merchant systems
* Reduce PCI scope
* Create reusable wallet cards in CMP
* Route authorizations through the Outbound Proxy with aliases

***

### Before you begin

Make sure you have:

* A VGS organization with CMP enabled
* OAuth credentials for CMP APIs
* A configured VGS Outbound Proxy
* Access to your PSP sandbox
* Apple Pay sandbox test accounts and devices

For Apple Pay, you also need:

* An Apple Developer account
* A Merchant Identifier
* A Payment Processing Certificate uploaded to VGS
* A Merchant Identity Certificate only if you use Apple Pay on the web

***

### High-level solution architecture

<figure><img src="/files/QvIyict0IZzOpHTiF2L3" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This flow lets you accept Apple Pay without building your own decryption service.
{% endhint %}

***

### How Wallet Decrypt works

1. The customer authorizes Apple Pay at checkout.
2. Apple returns an encrypted payment token to your frontend.
3. Your backend sends the encrypted token to `POST /cards`.
4. CMP decrypts the token with your configured Apple Pay payment processing certificate.
5. CMP creates a card and returns the card object with aliases and wallet metadata.
6. Your backend builds the authorization request with the returned values.
7. The payment request goes through the VGS Outbound Proxy to your PSP.
8. The proxy detokenizes aliases before forwarding the request.

{% hint style="warning" %}
Do not send wallet aliases or raw wallet credentials directly to your PSP. Route payment requests through the VGS Outbound Proxy.
{% endhint %}

***

### Configure Apple Pay certificates

CMP uses your Apple Pay payment processing certificate to decrypt the token.

1. Generate an Apple Pay payment processing CSR in VGS.
2. Upload the CSR to Apple Developer.
3. Download the Apple-signed certificate.
4. Upload the signed certificate to VGS.
5. Send the token's `publicKeyHash` value as `key_hash` in the Create Card request.

Use an ECC-based CSR. Apple Pay Wallet Decryption supports `EC_v1` only.

For the full certificate flow, see [Apple Pay](/cmp/payment-credentials/apple-pay) and [Create Card - Apple Pay Wallet Decryption](/cmp/payment-credentials/apple-pay/create-card-apple-pay-wallet-decryption).

***

### Create a card from an encrypted Apple Pay token

Submit the encrypted Apple Pay payload to the Cards API.

```http
POST /cards
```

```json
{
  "data": {
    "attributes": {
      "encrypted_payment_data": {
        "encrypted_payload_text": "<paymentData.data>",
        "key_hash": "<paymentData.header.publicKeyHash>",
        "public_key": "<paymentData.header.ephemeralPublicKey>",
        "digital_signature": "<paymentData.signature>",
        "version": "EC_v1",
        "wallet_type": "apple_pay",
        "wallet_transaction_id": "<paymentData.header.transactionId>"
      }
    }
  }
}
```

You can also include `payment_method` if you want CMP to persist wallet display metadata such as display name, network, and type.

### What the response includes

On success, CMP returns a card object and related wallet metadata.

Expect the response to include:

* `card_id`
* `pan_alias`
* `wallet_type`
* `token_type` as `dpan` or `mpan`
* masked card details such as `bin`, `first8`, and `last4`
* `wallet_details.payment_data_type`

For DPAN flows, the response can also include:

* `wallet_details.cryptogram`
* `wallet_details.cryptogram.eci`

For MPAN flows, the response can include:

* `wallet_details.merchant_token_identifier`

{% hint style="info" %}
The cryptogram is single-use. Use it only for the initial customer-authorized transaction. CMP does not persist it.
{% endhint %}

***

### Process payments

After card creation:

1. Store the returned `card_id`.
2. Build the authorization request with the aliases and wallet values from the Create Card response.
3. Send the request through the VGS Outbound Proxy.
4. Let the proxy reveal aliases before the request reaches your PSP.

#### Customer-initiated transactions

For the first Apple Pay authorization, pass the single-use cryptogram and ECI when they are present in the response.

Typical fields include:

* DPAN
* Cryptogram
* ECI
* Expiration date

#### Merchant-initiated transactions

Recurring or scheduled transactions do not generate a new wallet cryptogram.

Store the network transaction ID returned by your PSP from the original customer-initiated authorization. Many PSPs require it for later stored credential transactions.

***

### Retrieve the card

Use `GET /cards/{card_id}` to retrieve the stored card later.

The response includes persisted wallet metadata and masked card details.

Single-use payment artifacts are not returned.

This includes:

* `cryptogram`
* amount
* currency

***

### Limitations

Cards created through Apple Pay Wallet Decryption have these limitations:

* Wallet Decrypt supports Apple Pay only
* Duplicate card detection is not applied
* Network Tokens are not supported
* Account Updater is not supported
* 3DS is not supported
* Card `meta` is not supported

***

### Test the integration

Validate the integration in this order:

1. Create a card from an encrypted Apple Pay payload.
2. Confirm the response includes the expected wallet metadata.
3. Retrieve the card with `GET /cards/{card_id}`.
4. Send an authorization through your sandbox PSP and the Outbound Proxy.

Keep these points in mind:

* Apple Pay cryptograms are single-use
* Apple Pay sandbox testing requires Apple sandbox setup
* `GET /cards/{card_id}` does not return cryptogram, amount, or currency

For step-by-step testing flows, see [Wallet Decrypt](/cmp/developer-resources/guides/testing/wallet-decrypt).

***

### Next steps

Use these pages to complete the integration:

* [VGS for Merchants - Implementation Guide](/cmp/platform/vgs-for-merchants-implementation-guide)
* [Apple Pay](/cmp/payment-credentials/apple-pay)
* [Create Card - Apple Pay Wallet Decryption](/cmp/payment-credentials/apple-pay/create-card-apple-pay-wallet-decryption)
* [Wallet Decrypt](/cmp/developer-resources/guides/testing/wallet-decrypt)


# Cards

The VGS Credential Management Platform (CMP) allows businesses to securely register, manage, and operate on payment card data.&#x20;

Cards created through CMP are tied to specific accounts, enabling structured, account-level access and operations. This design allows organizations to manage large portfolios of cards with clarity and control. This system is designed to support secure data handling, simplify integrations, and give businesses full control over the card lifecycle—all while reducing customers PCI scope when used in conjunction with tools like VGS Collect.

When a card object is created using  CMP, it is stored securely and assigned a unique, persistent Card ID—a stable identifier that remains unchanged even if the underlying PAN, expiration date, or other card attributes are updated. When a card object is created, both the Card ID and Card Fingerprint are generated.&#x20;

### Duplicate Card Detection

CMP supports a fingerprint-based duplicate detection feature to help prevent the creation of redundant card objects.

When Duplicate Card Check is enabled on the account, during card object creation the system generates a fingerprint derived from the card's Primary Account Number (PAN) and checks if it already exists within the account. If a matching fingerprint is found, it indicates that the card has been created previously. In this case, the system identifies the card as a duplicate and returns the existing card ID with an HTTP 303 response instead of creating a new card object. A card ID is a unique, system-generated identifier assigned to each card object to reference it within the platform. If no match is found, a new card object is created, and the system returns an HTTP 201 response with the new card ID.

This mechanism helps maintain a clean and accurate card database by avoiding duplicate card entries.

#### How it works

* During card creation, CMP automatically generates a fingerprint from the PAN.
* If Duplicate Card Check is enabled for the account:
  * Match found: The system identifies an existing card with the same fingerprint and returns a HTTP 303 response. This response includes the existing card's `cardID` and `card_fingerprint`.
  * No match: A new card is created, and the system returns an HTTP 201 response with a new `card ID` and `card_fingerprint`.
* If the feature is disabled:
  * The system skips fingerprint checks entirely and always returns an HTTP 201 with a new `cardID` and `card_fingerprint`.&#x20;

#### Utilizing Fingerprint with VGS

* The `card_fingerprint` is included in the card creation response, allowing you to store and track fingerprints across your customer base.
* The fingerprint is derived solely from the card number (PAN) and does not take the expiration date into account. That means a renewed card with a later expiry will have the same fingerprint as the original.
* When a card is subscribed to VGS Account Updater and the PAN is updated, a new fingerprint is generated. This updated fingerprint is included in the Account Updater – Card Update notification. The Card ID remains unchanged throughout the card’s lifecycle.
* When the On-Demand Account Updater API is used and the PAN is updated, a new fingerprint is also generated. However, in this case, no notification is sent. The updated fingerprint can be retrieved via the GET /card API for the same (existing) Card ID.&#x20;
* Fingerprints are unique per CMP account. If the same card is added to two different CMP accounts, they will have different fingerprints.
* CMP returns a 303 response with the card that has the most recent updated\_at timestamp when a matching fingerprint is found. This ensures the most current card record is always returned.
* CMP retains fingerprint history when a card is updated (e.g., due to a PAN change). If a previously used PAN is registered again, CMP matches against historical fingerprints and returns a 303 response with the current (updated) card.

#### Notifications

* CMP includes fingerprint data in all customer notifications.
* If a card is updated via Account Updater and results in a duplicate PAN:
  * The system will surface this in the `cmp_au_card.updated` event.
  * A new optional field `fingerprint_matches` will list the card IDs with matching fingerprints.
* This allows clients to handle deduplication logic post-update and maintain data integrity.

#### **Onboarding Requirements**

* *This feature is **disabled** by default for all Credential Management Platform accounts; however, clients have the option to adjust this setting during onboarding.*

### Updating a Card Object

You can modify certain fields of a card object using the Update card endpoint, which is accessed via the specific card's ID.

#### Updatable Fields

The following fields within the card object can be updated:

* `CVC`
* `exp_month` (Expiration Month)
* `exp_year` (Expiration Year)

#### Endpoint Behavior

When you call the Update card endpoint with new information:

* The fields provided in the request body are updated in the card object.
* The API returns a `200 OK` response upon successful update.
* Idempotency: Replaying the exact same request will continue to update the data and will consistently return a `200 OK` response.
* Updating the card object does not automatically trigger any associated services or actions.
* Timeouts:
  * To ensure optimal performance, set a 5s endpoint timeout. Always perform a GET operation to validate data availability prior to executing a PATCH request.

### Delete Card by ID

The **CMP Delete Card endpoint** allows customers to permanently remove a payment card from the system using a unique `card_id`.

#### How it works

* The deletion process is triggered through a single API call:&#x20;
  * **Endpoint:** **`DELETE`**` ``/cards/{card_id}`
* When invoked, the system performs the following actions:
  * The specified card record is permanently deleted from CMP.
  * All services associated with the card ID are automatically removed, including:
    * Network Tokens&#x20;
    * Account Updater&#x20;
* By default, deleting a card ID removes Network Token and Account Updater services **across all duplicate card records.**
* The operation is permanent and cannot be undone.
* Any subsequent GET request for the deleted `card_id` will return no results.

#### Best suited for

* Removing stale or inactive cards that are no longer needed.
* Cleaning up payment credentials that should not be used for future transactions.

Because deletion is final, ensure the card is no longer required for active payments or retries before invoking this endpoint.

### User-Defined Metadata

The meta object allows you to attach structured information to a card object in VGS.\
Metadata is useful for storing additional, application-specific details alongside the card, without affecting payment processing.

You can include any string key-value pairs to suit your business needs — for example, linking a card to your own customer records, identifying the source system, or tagging the record with relevant attributes.

Metadata is fully user-defined. Metadata may be supplied when creating a card and is retrievable thereafter. Metadata fields are immutable — updates and deletes to metadata are not supported. VGS does not use or modify the metadata you provide, but it is stored and returned in the `GET /cards/{id}` response.

#### Metadata Validations

When adding metadata:

* Values can contain strings, numbers, arrays, ASCII text, JSON, or nested JSON.
* Maximum key length: 50 characters. If a key exceeds this limit, the request will fail with:\
  “data.meta keys must not be longer than 50 characters”.
* Maximum value length: 500 characters. If a value exceeds this limit, the request will fail with: “data.meta values must not be longer than 500 characters”.
* Maximum number of metadata entries: 50 key-value pairs. If more than 50 are provided, the request will fail with: “user defined metadata must not contain more than 50 items”.
* If the same key is provided more than once in the meta object, the last occurrence will override earlier values, and only the final key-value pair will appear in the response.
* **Sensitive information** such as bank account numbers, card details, and so on, **must not be stored** in metadata.

#### Example

```
{
   "data": {​
   "attributes": {​
     "pan": "4111111111111111",
     "exp_month": 4,
     "exp_year": 28​,
   },
   "meta": {​
     "customerID": 1234​
   }​
 }​
​}

```

### Supported Card Alias Formats

Format-preserving PAN alias support allows CMP to return `pan_alias` in a configured format at the account level.

By default, when a card object is created or retrieved, CMP returns `pan_alias` in UUID format. With this configuration enabled, customers can choose a supported `pan_alias` format that better fits their integration needs.

Once configured, both `POST Create Card` and `GET Card` responses return the `pan_alias` in the selected format. If no custom format is configured, existing behavior remains unchanged and CMP continues to return `pan_alias` in UUID format.

* CMP supports the following `pan_alias` formats:
  * `UUID`
  * `NUM_LENGTH_PRESERVING`
  * `FPE_SIX_T_FOUR`
  * `FPE_T_FOUR`
  * `PFPT`
  * `NON_LUHN_FPE_ALPHANUMERIC`
  * `GENERIC_T_FOUR`
  * `RAW_UUID`
  * `ALPHANUMERIC_SIX_T_FOUR`
  * `VGS_FIXED_LEN_GENERIC`
    * For details on how each format behaves, see the [VGS alias formats](https://docs.verygoodsecurity.com/vault/tokens#alias-formats) reference.
    * **To configure any of these formats for your cards, please reach out to your VGS representative.**
* CMP supports the following `cvc_alias` formats:
  * `UUID`

#### Card Alias Fallback Behavior

* If a card is created using a **non-Luhn-valid PAN**, some `pan_alias` formats will fall back to a default format.
* In addition, if the requested alias format cannot be generated for any reason, CMP may return the configured fallback format instead.

| Requested pan\_alias format | Fallback format         |
| --------------------------- | ----------------------- |
| `UUID`                      | `UUID`                  |
| `NUM_LENGTH_PRESERVING`     | `RAW_UUID`              |
| `FPE_SIX_T_FOUR`            | `UUID`                  |
| `FPE_T_FOUR`                | `RAW_UUID`              |
| `PFPT`                      | `RAW_UUID`              |
| `NON_LUHN_FPE_ALPHANUMERIC` | `RAW_UUID`              |
| `GENERIC_T_FOUR`            | `UUID`                  |
| `RAW_UUID`                  | `RAW_UUID`              |
| `ALPHANUMERIC_SIX_T_FOUR`   | `UUID`                  |
| `VGS_FIXED_LEN_GENERIC`     | `VGS_FIXED_LEN_GENERIC` |

### Proxy Reveal Behavior for CMP-Generated Aliases

When CMP generates aliases for card data, it also assigns **classifiers** to those aliases. These classifiers can be used as **tags** during proxy setup and determine which aliases can be revealed through proxy routes.

For CMP-generated aliases, CMP uses the following classifiers:

| CMP alias   | Classifier / proxy tag |
| ----------- | ---------------------- |
| `pan_alias` | `card-number`          |
| `cvc_alias` | `cvv`                  |

For CMP cards, when using tags, proxy routes should the `card-number` tag for PAN reveal and the `cvv` tag for CVV reveal.

Customer-defined classifiers or custom proxy tags will **not reveal** CMP-generated PAN or CVV aliases. Only the CMP-generated classifiers listed above should be used for proxy reveal.

For example:

* Use `card-number` to reveal `pan_alias`
* Use `cvv` to reveal `cvc_alias`
* Do not use customer-defined tags to reveal CMP-generated PAN/CVV aliases

This ensures CMP-generated aliases can be used consistently with proxy while keeping alias generation and reveal behavior aligned.

#### Onboarding Requirements

* No additional onboarding steps are required.
* Customers who are already able to create a card using CMP, can immediately use this functionality without any further setup.


# Apple Pay

## **Overview**

CMP supports storing Apple Pay wallet cards, including Device Primary Account Numbers (DPANs) and Merchant Primary Account Numbers (MPANs).

Merchants can store Apple Pay cards in CMP in two ways:

1. **Submit a decrypted wallet token (DPAN or MPAN) directly to CMP.** This means the merchant already has the clear wallet token value — meaning the clear DPAN or MPAN — and sends that token directly in the Create Card request.
2. **Submit an encrypted Apple Pay payment token to CMP.** CMP decrypts the Apple Pay payload, extracts the underlying DPAN or MPAN, and converts it into a stored card.

Both approaches result in a card stored in CMP that can be retrieved using the standard [`GET /cards/{id}`](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#get-cards-card_id) API.

## **Understanding Apple Pay Tokens**

When a customer pays using Apple Pay, Apple Pay returns tokenized card data rather than exposing the original PAN. For standard one-time Apple Pay transactions, Apple Pay uses a device-specific tokenized credential (DPAN) in place of the PAN.

#### DPAN (Device PAN)

A **DPAN** is a device-specific tokenized credential generated for a particular device and card combination. It is commonly used for Apple Pay customer-initiated transactions.

**Characteristics:**

* Device-specific
* Used in customer-initiated Apple Pay transactions
* Requires a **cryptogram** for the first authorization
* Can support recurring payments when properly linked to prior transactions

#### MPAN (Merchant PAN)

An **MPAN** is a merchant-specific network token provisioned by the card network and is not tied to a specific device. Apple positions merchant tokens for recurring payments and automatic reload scenarios, where continuity across devices is important.

**Characteristics:**

* Merchant-scoped rather than device-scoped
* Intended for recurring payments and automatic reload use cases
* Supports token lifecycle management (card updates, expiration changes, deleted)
* Designed to improve authorization rates for recurring payments
* Not tied to a specific device

MPAN support is expected to expand as Apple and card networks increase adoption.

### **Apple Pay Recurring Payment Model**

When using Apple Pay for subscriptions, recurring billing, or automatic reload flows, the payment model typically begins with a customer-authorized Apple Pay transaction and is followed by subsequent merchant-initiated or preauthorized transactions, depending on the payment processor, network, and stored credential framework in use. Apple’s merchant token guidance is specifically designed to support recurring and automatic reload payment experiences across a customer’s devices.

#### Step 1 — Customer-Initiated Transaction (CIT)

The first payment is initiated by the customer, for example during checkout using Apple Pay.

**During this step:**

* The customer authorizes the payment in Apple Pay.
* Apple Pay returns tokenized payment data together with a **single-use cryptogram** for authorization.
* The merchant submits the authorization request to their PSP using the **DPAN and cryptogram**, and the PSP processes the transaction.
* If the transaction is approved, the card network returns a **Network Transaction ID (NTID)**.
* The merchant can then store the returned wallet credential for future use, subject to processor and network requirements.

**The merchant must store:**

* DPAN (vaulted by CMP)
* Expiration date
* Network Transaction ID (NTID)

**The cryptogram:**

* Is **single-use**
* Expires quickly
* Cannot be reused if the authorization fails

If the initial transaction fails, the customer may need to complete a new Apple Pay authorization flow to generate fresh payment data.

#### Step 2 — Merchant-Initiated Transactions (MIT)

All subsequent recurring or preauthorized payments occur without customer interaction.

MIT requests typically include:

* DPAN or MPAN
* Expiration date, when applicable
* Previous **Network Transaction ID (NTID)**
* Stored credential indicators
* ECI value

The NTID links the recurring payment chain back to the original customer-authorized transaction. Without it, authorization rates may drop or transactions may be declined.


# Create Card - Using DPAN or MPAN

## **Overview**

The CMP Create Card API supports storing digital wallet cards, including Apple Pay Device PANs (DPANs) and Merchant PANs (MPANs), alongside traditional physical cards (PANs).

Cards classified as `dpan` or `mpan` from Apple Pay do not trigger downstream services such as Account Updater, Network Token provisioning, even if the account is configured for [onCreate enrollment type](/cmp/platform/cmp-account#on-create-enrollment). Cards stored in this way behave similarly to traditional cards but are tagged with Apple Pay metadata.

To store an decrypted Apple Pay DPAN or MPAN, include the wallet token in the `pan` field of the Create Card request. Additionally, specify the following in the card object:

* `wallet_type`: apple\_pay
* `token_type`: dpan / mpan

It’s important that merchants pass these values in **lowercase only**, as incorrect formatting will cause validation errors.

**Note:**&#x20;

* Apple Pay wallet tokens are only retrievable through `GET /cards/{id}`. They are clearly marked as DPAN or MPAN and are **not included in notifications**.
* Apple Pay DPAN/MPAN cards **do not trigger downstream services** such as Account Updater, Network Token provisioning or 3DS.
* This applies even if the account is configured for `onCreate` enrollment.
* Tokenized wallet cards are retrievable via  [`GET /cards/{id}`](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#get-cards-card_id) .

#### Validation Rules when Creating a Card with DPAN/MPAN

* If creating a DPAN or MPAN from Apple Pay, the `wallet_type` field **must** be included. Omitting it will return a **422 Unprocessable Entity** error.
* For physical PANs, `wallet_type` and `token_type` are optional, but `token_type` is always returned in the response as `pan`.
* Both `wallet_type` and `token_type` must be lowercase. For example: `"Apple Pay"` or `"apple_Pay"` will fail validation. Similarly, `"DPAN"` or `"MPAN"` in uppercase will also fail, returning **400 Bad Request**.

You can see a sample request and response for Apple Pay cards here: **VGS Card Management API –** [**Create a Card**](/cmp/api-dev/cards#post-cards).

#### Retrieve Card (GET /cards/{id})

When retrieving an Apple Pay card, the response includes `wallet_type` and `token_type` in the card object. These values match the ones sent during creation (`wallet_type: apple_pay`, `token_type: dpan/mpan`) and clearly indicate that the card is an Apple Pay DPAN or MPAN.

Sample response: **VGS Card Management API –** [**Get a Card**](/cmp/api-dev/cards#get-cards-card_id).

#### Onboarding Requirements

No extra steps are needed. Customers already using CMP for card creation can immediately store Apple Pay cards without additional setup.


# Create Card - Apple Pay Wallet Decryption

### Overview

CMP supports Apple Pay Wallet Decryption, allowing merchants to submit an encrypted Apple Pay payment token directly to CMP during card creation. CMP decrypts the token using an Apple-compliant key, extracts the DPAN or MPAN, creates and securely stores the card, and returns the created card object in the API response.

This feature is designed for merchants who have already obtained the encrypted Apple Pay payment token from the customer’s device and want CMP to handle decryption and card creation. The encrypted wallet token must be generated through the standard Apple Pay flow before calling the Create Card API. If you need guidance on generating encrypted Apple Pay tokens for testing, see the Wallet Decrypt [Testing Guide her&#x65;**.**](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/wallet-decrypt)

The `pan` field in the response contains the decrypted DPAN or MPAN, not the original FPAN. Tokenization behavior remains consistent with CMP: PCI-scoped clients receive both PAN and PAN alias, while non-PCI clients receive only the PAN alias. The presence of PAN in the response does not mean tokenization is bypassed.

### Benefits

* No need to build or maintain Apple Pay decryption services
* Reduced PCI scope
* Standardized handling of wallet metadata
* Continued access to CMP vaulting and card fingerprinting

### Apple Pay wallet decryption flow

After the merchant session is established and the customer authorizes the payment, the encrypted Apple Pay token can be submitted to CMP for decryption and card creation.

#### Flow overview

* The customer selects Apple Pay during checkout.
* The merchant frontend creates and begins the Apple Pay session.
* The merchant backend completes Apple merchant validation and returns the merchant session object to the frontend.
* The customer authorizes the payment in the Apple Pay sheet.
* Apple returns encrypted payment data to the merchant frontend.
* The merchant backend submits the encrypted Apple Pay token to CMP using the Create Card API.
* CMP decrypts the token using the configured Apple Pay payment processing certificate.
* CMP extracts the wallet token and related card metadata.
* CMP creates and stores the card.
* CMP returns the created card object and associated wallet metadata.

#### Apple Pay wallet decryption sequence

<figure><img src="/files/zBh1B0wAYVq0JbjcMyfJ" alt=""><figcaption></figcaption></figure>

### Setting Up Your Apple Certificates

To use **Apple Pay Wallet Decryption** with CMP, you need to configure the Apple Pay certificates required for your integration.

For **DPAN decryption with CMP**, you only need to configure the following with VGS:

* **Merchant Identifier**
* **Payment Processing Certificate**

A **Merchant Identity Certificate** is **not required by VGS for DPAN decryption**. If your integration requires merchant validation, such as Apple Pay on the web, you may generate and manage your own Merchant Identity Certificate separately.

Before generating certificates or uploading Apple-signed certificates to VGS, make sure the VGS CLI is installed and authenticated.

#### Getting Your Vault ID

To generate and upload certificates, you need your VGS Vault ID. **Work with your VGS customer representative to obtain your Vault ID.**&#x20;

> **Users must have Admin access to the target vault to generate and upload certificates using the VGS CLI.**

#### VGS CLI Setup

<pre><code>source .venv-pypi/bin/activate
<strong>pip install vgs-cli
</strong><strong>vgs login
</strong></code></pre>

Ensure you can log in successfully using `vgs login` and confirm that the **“Success!”** message appears in your terminal before proceeding with the certificate generation steps below.

#### Create a Merchant Identifier

Create a Merchant Identifier in your Apple Developer account for the Apple Pay integration you plan to use with CMP. The Merchant Identifier represents your Apple Pay merchant configuration and is required when creating Apple Pay certificates.

Apple requires the Merchant Identifier to follow reverse domain notation, for example `merchant.com.yourcompany.appname`. Identifiers that do not follow this format may be rejected by the Apple Developer portal.

Use the Merchant Identifier that corresponds to the integration you intend to test or use in production. You will reference this identifier when creating both the Payment Processing Certificate and, if needed, the Merchant Identity Certificate.

#### Create a Merchant Identity Certificate

If your integration requires merchant validation, such as Apple Pay on the web, you may generate and use your own Merchant Identity Certificate directly with Apple.

This certificate is not required by VGS for DPAN decryption, and does not need to be generated or uploaded through the VGS certificate flow described below.

**Step 1: Generate a CSR and Private Key**

Run the following OpenSSL command:

```bash
openssl req -new -newkey rsa:2048 -nodes \
  -keyout merchant_id.key \
  -out MyCSR.certSigningRequest \
  -subj "/C=<country_code>/ST=<state>/L=<city>/O=<your_organization_name>/OU=<unit>/CN=<your_merchant_identifier>"
```

Replace the placeholders:

* `<country_code>` — Two-letter country code (e.g., `US`)
* `<state>` — State or province (e.g., `California`)
* `<city>` — City name (e.g., `San Francisco`)
* `<your_organization_name>` — Your company or organization name
* `<unit>` — Organizational unit (e.g., `Payments`)
* `<your_merchant_identifier>` — Your Apple merchant identifier (e.g., `merchant.com.example.store`)

This generates two files:

* `merchant_id.key` — Your private key (keep this secure)
* `MyCSR.certSigningRequest` — The CSR to upload to Apple

**Step 2: Get the Identity Certificate from Apple**

1. Sign in to your [Apple Developer Account](https://developer.apple.com/account)
2. Navigate to **Certificates, Identifiers & Profiles**
3. Select **Apple Pay Merchant Identity Certificate**
4. Click **Create Certificate**
5. Select your Merchant ID
6. Upload `MyCSR.certSigningRequest`
7. Download the resulting `merchant_id.cer` file

**Step 3: Convert to PEM Format**

Move `merchant_id.cer` into the same folder where `merchant_id.key` was generated and convert the downloaded certificate to PEM format:

```bash
openssl x509 -inform der -in merchant_id.cer -out merchant_id.pem
```

You now have the two files needed for Apple Pay merchant validation in the same folder:

* `merchant_id.key` — Private key
* `merchant_id.pem` — Certificate in PEM format

#### Create a Payment Processing Certificate

The Payment Processing Certificate is required for Apple Pay token decryption. CMP uses this certificate to decrypt the encrypted Apple Pay payment token submitted through the Create Card API.

To set this up, generate a certificate signing request (CSR) using an ECC (Elliptic Curve Cryptography) key. CMP supports `EC_v1` tokens only, which requires an ECC-based CSR. VGS does not support RSA-based certificates. Apple’s portal may accept an RSA-based CSR without error, but the resulting certificate cannot be used with CMP and decryption will fail at runtime.

**Step 1: Generate the CSR**

Use the VGS CLI to generate the CSR for the Apple Pay Payment Processing Certificate:

```
vgs certificate generate-csr -V <VAULT_ID> --type apple-pay-payment-processing --name merchant.com.example -o payment_processing.csr
```

Replace:

* `<VAULT_ID>` with your VGS vault ID
* `merchant.com.example` with your Apple Merchant Identifier

**Step 2: Upload the CSR to Apple**

Upload the generated `.csr` file to the Apple Developer portal when creating your Apple Pay Payment Processing Certificate.

The generated CSR is uploaded to Apple, not to VGS. There is no separate command to upload the CSR back into VGS.

**Step 3: Upload the Apple-signed certificate to VGS**

After Apple signs the certificate and provides the `.cer` file, upload the Apple-signed certificate back to VGS.

Using certificate ID:

```
vgs certificate upload \
  -V <VAULT_ID> \
  --cert-id <CERT_ID> \
  -f apple_signed_cert.cer
```

Once this certificate is uploaded to VGS, it can be used to decrypt Apple Pay payment payloads sent through the Create Card API. CMP identifies the correct certificate using the `key_hash` value included in the encrypted request payload.

### Create the Apple Pay Merchant Session

Before the encrypted Apple Pay token can be submitted to CMP, the merchant must initialize and validate an Apple Pay session in the browser.

A typical merchant session flow is:

* Register and verify your web domain with Apple: The domain association file must be hosted on each domain that will use Apple Pay, and each domain or subdomain must be registered and verified separately with Apple.
* The customer clicks the Apple Pay button.
* Create an `ApplePaySession` in the frontend using an `ApplePayPaymentRequest`: This must be done synchronously inside a user gesture handler, such as a click or tap event. Do not create the session after asynchronous work, such as an `await`, promise resolution, or callback, because it may no longer be considered part of the original user gesture. If the session is created outside a user gesture handler, Safari throws a JavaScript exception and the Apple Pay sheet does not open. The error message is: `Must create a new ApplePaySession from a user gesture handler`.
* Populate the Apple Pay payment request: The payment request includes values such as:
  * `merchantIdentifier` — your registered Merchant Identifier
  * `countryCode` and `currencyCode`
  * `supportedNetworks`
  * `merchantCapabilities` — include `supports3DS`, which Apple requires for standard card payments
  * `total`
  * optional line items
* Handle merchant validation: The Apple Pay session triggers merchant validation and provides a `validationURL` in the `onvalidatemerchant` event. The frontend sends this `validationURL` to the merchant backend. The server-side merchant validation flow must use the `validationURL` provided by the event.
* Request the merchant session from the backend: The merchant backend sends a POST request to the `validationURL` to obtain the merchant session object. This request must be made from your server, not the client, as it requires your Merchant Identity Certificate for mutual TLS authentication.
* Complete merchant validation in the frontend: Apple returns a merchant session object. The backend passes it to the frontend, which calls `session.completeMerchantValidation(merchantSession)` to complete validation and enable the Apple Pay sheet. The merchant session object is single-use and expires after five minutes.
* The customer authorizes the payment: The customer uses Face ID, Touch ID, or device passcode to authorize.
* Receive the encrypted Apple Pay payment token: The `onpaymentauthorized` event returns the Apple Pay payment data, including the encrypted payment token.
* Submit the encrypted payment data to CMP: The frontend passes `event.payment.token.paymentData` to the merchant backend, which submits it to CMP. CMP uses the configured Payment Processing Certificate to decrypt the token, extract the wallet card data, create and securely store the card, and return the created card object.

### Create Card request

To use Apple Pay Wallet Decryption, submit the encrypted Apple Pay payment token in the Create Card request instead of a decrypted PAN.

CMP uses the `key_hash` field to identify the correct Apple Pay payment processing certificate for decryption.

#### **Apple Pay token to CMP field mapping**

When constructing the Create Card API request, map the fields from `event.payment.token.paymentData` as follows:

| Apple Pay token field                   | CMP API field            | Notes                                                                                                        |
| --------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `paymentData.data`                      | `encrypted_payload_text` | Base64-encoded encrypted payload                                                                             |
| `paymentData.header.publicKeyHash`      | `key_hash`               | Used by CMP to identify the correct Payment Processing Certificate. Do not confuse with `ephemeralPublicKey` |
| `paymentData.header.ephemeralPublicKey` | `public_key`             | The ephemeral EC public key for this transaction                                                             |
| `paymentData.signature`                 | `digital_signature`      | Base64-encoded signature for payload verification                                                            |
| `paymentData.version`                   | `version`                | Must be `EC_v1`. CMP does not support `EC_v2`                                                                |
| `paymentData.header.transactionId`      | `wallet_transaction_id`  | Unique transaction identifier generated by Apple per payment authorization                                   |
| *(recommended to set explicitly)*       | `wallet_type`            | Set to `"apple_pay"`                                                                                         |

#### Supported encryption version

CMP currently supports Apple Pay tokens using the `EC_v1` encryption format.

### Create Card response

After decryption, CMP returns a card object containing the decrypted token and associated wallet metadata.

For Apple Pay card creation, the response can include wallet-related metadata such as:

* `wallet_type`
* `token_type`
* wallet payment method information
* `eci` is **optional**. The card network **may** add an ECI indicator to the payment data that the payment token includes. If you receive an ECI indicator, you must pass it on to your payment processor; otherwise, the transaction fails.
* masked card details such as BIN, first8, and last4

#### Response Behavior

* **Synchronous response:** Apple Pay Wallet Decryption uses a synchronous request-response flow. When you submit an encrypted Apple Pay token to the Create Card API, CMP processes the request and returns the created card object directly in the API response.
* **No webhook notifications are sent for this flow.** Customers should expect the result in the synchronous Create Card response only. The Create Card response contains all card data and wallet metadata immediately upon successful decryption and card creation.
* [**Card Attributes**](https://docs.verygoodsecurity.com/cmp/products-and-services/card-attributes)**:** If Card Attributes is enabled for the account, the Create Card response also includes advanced card attributes.

#### Cryptogram handling

For DPAN transactions, the Create Card response may include a cryptogram generated by the wallet at the time of payment.

Cryptogram behavior:

* the cryptogram is single-use
* it is intended only for the initial customer-initiated authorization
* it is not stored by CMP

The Create Card response includes cryptogram and ECI values for DPAN flows. For MPAN flows, instead of cryptogram/ECI, the response includes a `merchant_token_identifier` and `payment_data_type = "MerchantToken"`.

Because cryptogram and ECI are single-use transaction artifacts, they are not persisted and will not be returned in the GET Card response.

| Wallet    | Network                    | ECI value                       | Authentication / liability meaning                                                                                   | What it means when passed to processor                                                                                                                                                                                                                                                                  |
| --------- | -------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Apple Pay | Visa / Mastercard / others | Value may or may not be present | `eciIndicator` may be present, and the value is network-provided. Use processor/network-specific ECI interpretation. | `eciIndicator` is network-provided and may or may not be present. When present, VGS returns it as received and does not normalize or map it to Apple Pay-specific values. Customers should pass it to their processor unchanged, as altering or hardcoding the value may cause the transaction to fail. |

### Retrieve Card

When retrieving a card created from Apple Pay using `GET /cards/{id}`, CMP returns the stored card together with persisted Apple Pay metadata.

Wallet transaction artifacts are not persisted and are therefore not included in GET responses. These include:

* `cryptogram`
* transaction amount
* currency
* If [Card Attributes](https://docs.verygoodsecurity.com/cmp/products-and-services/card-attributes) is enabled for the account, the GET Card response also includes advanced card attributes

#### Limitations

Cards created using Apple Pay Wallet Decryption currently have the following limitations:

* **Meta object support is not available** for cards created through Apple Pay Wallet Decryption.
* **Duplicate card detection logic is not applied** when creating cards from encrypted Apple Pay tokens.
* **Network Token (NT)** services are not supported.
* **Account Updater (AU)** services are not supported.
* **3D Secure (3DS)** authentication is not currently supported for cards created from Apple Pay DPAN or MPAN tokens.

These limitations apply to cards created using Apple Pay Wallet Decryption regardless of whether the resulting token type is **DPAN** or **MPAN**.

Currently, CMP **supports Apple Pay decryption only**. Google Pay is not supported at this time, but the API structure is designed to support additional wallet types in the future.

#### Apple Pay Wallet Decryption Error Messages

<table><thead><tr><th width="124.60845947265625">HTTP Code</th><th width="196.1102294921875">Summary</th><th>Detail</th><th>Field</th></tr></thead><tbody><tr><td>422</td><td>must not be null</td><td>must not be null</td><td>encrypted_payload_text</td></tr><tr><td>422</td><td>size must be between 20 and 20000</td><td>size must be between 20 and 20000</td><td>encrypted_payload_text</td></tr><tr><td>422</td><td>Invalid input format</td><td>Must be a valid Base64-encoded string.</td><td>encrypted_payload_text</td></tr><tr><td>422</td><td>must not be null</td><td>must not be null</td><td>key_hash</td></tr><tr><td>422</td><td>size must be between 44 and 44</td><td>size must be between 44 and 44</td><td>key_hash</td></tr><tr><td>422</td><td>Invalid input format</td><td>Must be a valid Base64-encoded string.</td><td>key_hash</td></tr><tr><td>422</td><td>must not be null</td><td>must not be null</td><td>public_key</td></tr><tr><td>422</td><td>size must be between 20 and 2048</td><td>size must be between 20 and 2048</td><td>public_key</td></tr><tr><td>422</td><td>Invalid input format</td><td>Must be a valid Base64-encoded string.</td><td>public_key</td></tr><tr><td>422</td><td>size must be between 10 and 8192</td><td>size must be between 10 and 8192</td><td>digital_signature</td></tr><tr><td>422</td><td>Invalid input format</td><td>Must be a valid Base64-encoded string.</td><td>digital_signature</td></tr><tr><td>422</td><td>size must be between 1 and 256</td><td>size must be between 1 and 255</td><td>wallet_transaction_id</td></tr><tr><td>422</td><td>size must be between 1 and 255</td><td>size must be between 1 and 255</td><td>display_name</td></tr><tr><td>422</td><td>size must be between 1 and 255</td><td>size must be between 1 and 255</td><td>network</td></tr><tr><td>422</td><td>wallet_type is not supported for wallet decryption</td><td>wallet_type 'google_pay' is not supported for wallet decryption</td><td>wallet_type</td></tr><tr><td>422</td><td>size must be between 1 and 255</td><td>size must be between 1 and 255</td><td>type</td></tr><tr><td>422</td><td></td><td>Unable to decrypt the data provided. Please ensure it is valid and try again</td><td>The request contains invalid values for one or more of the following fields: <code>digital_signature</code>, <code>encrypted_payload_text</code>, <code>key_hash</code>, <code>public_key</code>.</td></tr><tr><td>400</td><td>Validation failed</td><td>Unexpected value 'EC_v2'</td><td>version</td></tr><tr><td>400</td><td>Validation failed</td><td>Unexpected value 'apple_pay1'</td><td>wallet_type</td></tr><tr><td>503</td><td><br></td><td>Service Unavailable. The downstream network is temporarily unavailable.</td><td></td></tr><tr><td>500</td><td></td><td>A problem has occurred with this request.</td><td></td></tr><tr><td>500</td><td><br></td><td>Decryption failed: Failed to decrypt Apple Pay token</td><td></td></tr></tbody></table>

#### Onboarding Requirements

To enable Wallet Decryption Flow support with CMP:

* Apple Pay wallet decryption support must be enabled for the account.
* Merchants must configure Apple Pay certificates:
  * Merchant Identity Certificate
  * Payment Processing Certificate
* The payment processing certificate is used by CMP to decrypt Apple Pay tokens. CMP identifies the correct certificate using the `key_hash` provided in the encrypted request payload.


# Google Pay

## **Storing Google Pay DPAN in CMP**

### **Create Card API Request**

CMP’s Create Card API also supports storing Google Pay digital wallet cards (DPANs), along with standard physical cards (PANs).

Cards classified as `dpan`  from Google Pay do **not** activate downstream services like Account Updater or Network Token provisioning, even if [onCreate enrollment type](/cmp/platform/cmp-account#on-create-enrollment) is enabled.

To add a Google Pay DPAN, include the wallet token in the `pan` field and provide the following fields in the card object:

* `wallet_type`: google\_pay
* `token_type`: dpan&#x20;

### **Google Pay Digital Wallet Fields**

CMP can store decrypted Google Pay DPAN cards securely. While stored like regular PANs, these cards are flagged to indicate their Google Pay source.

* `wallet_type`: google\_pay
* `token_type`: dpan

Merchants must use **lowercase** for these fields to pass validation checks.

**Important:** Google Pay wallet tokens are only accessible through `GET /cards/{id}`. Notifications will **not** include these cards, but the card object will clearly indicate DPAN using the `token_type` field.

#### **Create Card - Validation Rules for Google Pay**

* If creating a DPAN from Google Pay, the `wallet_type` field is **required**. Omitting it results in a **422 Unprocessable Entity** error.
* For physical PANs, both `wallet_type` and `token_type` are optional, but `token_type` always appears as `pan` in the response.
* You can also explicitly set `"token_type": "pan"` and `"wallet_type": "google_pay"` for a regular PAN. This allows you to indicate that the card is associated with Google Pay even if it isn’t a DPAN.
* Both fields must be lowercase. Variations such as `"Google Pay"` or `"google_Pay"` will fail validation. Uppercase `DPAN` will also fail and return **400 Bad Request**.

Sample request and response: **VGS Card Management API –** [**Create a Card**](/cmp/developer-resources/guides/testing/create-card).

#### **Retrieve Card (GET /cards/{id})**

Google Pay cards will return the `wallet_type` and `token_type` as originally sent (`wallet_type: google_pay`, `token_type: dpan`), confirming the card’s type and source.

Reference: **VGS Card Management API –** [**Get a Card**](/cmp/developer-resources/guides/testing/get-card).

#### **Google Pay ECI Indicator Reference**

| Wallet     | Network        | ECI value | Authentication / liability meaning                      | What it means when passed to processor                                                         |
| ---------- | -------------- | --------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Google Pay | Mastercard     | `"02"`    | Fully authenticated / successful authentication         | Issuer liability. This is the expected successful Mastercard Google Pay cryptogram case.       |
| Google Pay | Mastercard     | `"06"`    | Not fully authenticated / no issuer liability           | Merchant/acquirer liable. Auth can still be processed, but liability does not shift to issuer. |
| Google Pay | Mastercard     | Empty     | Not authenticated / no issuer liability                 | Merchant/acquirer liable. Auth can still be processed, but no ECI-based liability shift.       |
| Google Pay | Visa           | `"05"`    | Fully authenticated / successful authentication         | Issuer liability. This is the expected successful Visa Google Pay cryptogram case.             |
| Google Pay | Visa           | `"07"`    | Not authenticated / no issuer liability                 | Merchant/acquirer liable. Auth can still be processed, but liability does not shift to issuer. |
| Google Pay | Other networks | Empty     | Not authenticated or ECI not provided by wallet/network | Merchant/acquirer liable. Auth can still be processed, but no ECI-based liability shift.       |

#### **Onboarding Requirements**

No additional onboarding is required. Any customer already able to create cards in CMP can start storing Google Pay cards immediately.

#### Card Attributes

[Card Attributes](/cmp/products-and-services/card-attributes) are available for DPAN.&#x20;


# Bank Accounts

Bank Account Objects, including the United States, United Kingdom, Canada, and the European Union (SEPA) to start, are currently in the active design phase. If you are interested in learning more or participating as a design partner, please email <support@vgs.io>.


# Wallets

Wallet Objects such as PayPal, Amazon Pay, KakaoPay, and many more are currently in active design phase. If you are interested in learning more or participating as a design partner, please email <support@vgs.io>.


# Account Updater

## Product Overview <a href="#product-overview" id="product-overview"></a>

Account Updater bridges the gap between card issuers and merchants, seamlessly delivering updated card information directly into your hands. No more chasing customers for new details or wrangling with failed payments. This powerful network tool empowers you to:

* Boost authorization success rates: Minimize declined transactions and ensure smooth recurring payments for subscription models.
* Reduce customer churn: Offer a frictionless checkout experience that keeps customers happy and engaged.
* Simplify workflows: Eliminate manual updates and focus on building your business instead of chasing card details.
* Enhance security: Leverage secure and encrypted data exchange to protect both you and your customers. VGS Account Updater simplifies connection to payment networks, automatically fetching and delivering updated card information to merchants, ensuring seamless recurring payments and reducing customer churn.

### Account Updater with [Card Objects](/cmp/payment-credentials/cards) <a href="#account-updater-with-card-objects" id="account-updater-with-card-objects"></a>

The Card Management Platform is built to support subscribing individual Card Objects on a per-account basis, enabling effective account-level card management. Each Card Object is uniquely identified by a cardID. When the Account Updater service is activated for an account, the platform performs network lookups using the associated cardID. The service is compatible with Visa, Mastercard, American Express, and Discover networks.

### Account Updater Network Coverage <a href="#account-updater-via-cmp" id="account-updater-via-cmp"></a>

We support Account Updater for **Visa, Mastercard, American Express, and Discover** networks.

Please note:

* **American Express** and **Discover** support is available only for direct merchants.
* **Real-time Account Updater** is supported **only for Visa and Mastercard**.
* For **Amex** and **Discover**, **real-time updates** are returned **only for cards previously subscribed** by us.

Customers can choose one of two paths for facilitating Account Updater subscription.

#### On-Create Subscription: <a href="#on-create-enrollment" id="on-create-enrollment"></a>

This is the default and the automated subscription option. When a card is created, VGS automatically subscribes it in the Account Updater services that are enabled for the account.

* **Behavior:**
  * Card creation triggers automatic subscription in Account Updater.
  * A webhook notification is sent when the subscription is successful.
  * If updates are available from the networks at the time of subscription, they are delivered as part of the notification.
* **Best For:**
  * Customers who want automatic Account Updater tracking with minimal integration effort.

#### Manual Subscription: <a href="#manual-enrollment" id="manual-enrollment"></a>

Manual subscription gives customers fine-grained control over when and how a card is subscribed to Account Updater services. When an account is not set to subscribe onCreate, the creation of a card does not trigger a subscription.&#x20;

Manual subscriptions are processed through independent API endpoints and are normally synchronous, meaning a response is returned immediately. To ensure timely processing, VGS applies a 10-second timeout. If a response takes longer, the request is automatically handled asynchronously, with the result delivered via webhook. In such cases, the initial response will indicate: ‘*The request will be processed asynchronously*'.

* **Behavior:**
  * Cards are created without Account Updater subscription.
  * **To subscribe:**
    * Customers must explicitly subscribe cards using the subscription endpoint: `POST /cards/{CardID}/card-update-subscriptions`.
    * A confirmation response is returned immediately.
    * Enrollment-Type/Provisioning-Method: **Manual**.
  * **To unsubscribe:**
    * `DELETE /cards/{CardID}/card-update-subscriptions`.
    * Account Updater tracking is removed for the **specified card ID and all duplicate cards**, and they are marked as unenrolled within VGS systems.
    * Once unsubscribed, the Account Updater object is removed from the `GET /cards/{CardID}` response, and no further Account Updater updates will be delivered.
    * No further card updates will be fetched or delivered.
    * Enrollment-Type/Provisioning-Method: The card may have been subscribed to Account Updater either:
      * **Manually**, via the `/card-update-subscriptions` endpoint after card creation using the manual method , or
      * **Automatically**, if created using the oncreate method during card registration.
  * **Best For:**
    * Customers who want precise control over which cards are subscribed and when.

### On-Demand Updates <a href="#on-demand-updates" id="on-demand-updates"></a>

This flow allows customers to perform real-time Account Updater lookups **without subscribing the card** in ongoing tracking. This is a stateless request available only for **Visa** and **Mastercard**.

* **Behavior:**
  * Use the endpoint: `POST /cards/{CardID}/check`.
  * This retrieves current Account Updater data (if available) but does not subscribe the card for future updates.
  * On-demand requests are typically used in decisioning workflows or just-in-time processing.
  * Existing card object is **automatically updated** with the latest PAN and/or expiration date returned from an On-Demand API call.
  * Enrollment-Type/Provisioning-Method: **Manual**.
* **Limitations:**
  * **American Express** and **Discover** do not support real-time Account Updater lookups.
    * Amex: Updates are retrieved approximately every 30 minutes.
    * Discover: Updates are retrieved once daily.
  * Updates for Amex and Discover are handled through batch-based file processing and delivered via webhooks.
* **Best For:**
  * Customers who want real-time update visibility without long-term tracking.
  * Commonly used with Manual Subscription, but technically compatible with onCreate.

### AU Subscription and Update Attributes in `GET /cards/{id}` Response

When a card is **subscribed** to Account Updater, the `GET /cards/{id}` response will include two AU-related `type` attributes on the card:

* `"type"`: `"card_update_subscriptions"` — Indicates that the card is currently enrolled in AU and reflects its active subscription status.
* `"type"`: `"card_updates"` — Contains the most recent update details for the card, showing what changes (if any) have been received.

When the card is **unsubscribed** from Account Updater:

* The `"card_update_subscriptions"` attribute will no longer appear in the response.
* The `"card_updates"` attribute will still be returned, providing the last update information available for the card.

This ensures the API conveys both the current enrollment status and the last known update details without losing historical context.

### **Note:**&#x20;

* The [Get Card by ID](https://docs.verygoodsecurity.com/cmp/developer-resources/api/cards#get-cards-card_id) and Account Updater [Card-Check / On-Demand APIs](https://docs.verygoodsecurity.com/cmp/developer-resources/api/account-updater#post-cards-card_id-check) return the following Account Updater event types:
  * `updated` , `enrolled` ,  `expired` ,  `closed` , `non_participating` ,  `contact_cardholder_advice` ,  `opt_out` ,  `unknown`, and `enrollment-failed`.
* These correspond to the **same** Account Updater **events** sent via the [webhook notifications](https://docs.verygoodsecurity.com/cmp/products-and-services/account-updater#account-updater-events). However, webhook events are returned with the **`cmp_au_card.`** prefix in the `event` field (for example, `cmp_au_card.updated`, `cmp_au_card.closed`).
* For `updated` events, only fields that actually changed are returned as previous values. A PAN change does not necessarily mean the expiration date also changed.
* The **GET Card response reflects** only the most recent Account Updater event received for the card. The `changed_fields` and `updated_values` fields remain available until another update is received for the same card. When a new update occurs, the previous update details are replaced with the details from the latest event.
  * For example, if a PAN update is followed by an expiration update, the GET Card response will include only the expiration-related fields from the latest update. The PAN-related fields from the previous update will no longer be included.
  * Similarly, if the next event indicates that the card is closed or valid, the response will reflect that latest status and update information.

### Account Updater Notification Events <a href="#account-updater-events" id="account-updater-events"></a>

After a card has been enrolled for account updates, several events may occur that update the card's status. You may receive these status updates via our **webhook integration**. Here is a brief explanation of what each update means:

#### cmp\_au\_card.updated

* **Definition:** An event triggered when the card’s Primary Account Number (PAN) or other account details have changed. This can be due to a new account creation, a lost or stolen card, a cardholder upgrade (e.g., to Platinum), or a portfolio change (e.g., the card was moved from one bank to another). In some cases, only the PAN changes while the expiration date remains the same. **For example**, if a card is lost or misplaced and reissued, the issuer may issue a new card number but keep the same expiration date.
* **Implication:** The merchant’s stored card information may now be outdated. The new, correct card information is available. Only the fields that actually changed will be returned as changed values. If the PAN changes but the expiration date stays the same, the old expiration details will not be returned because that field did not change.
* **Action Required:** The merchant must use the updated card information (the new PAN and/or expiry date) to ensure transactions are successful.

#### cmp\_au\_card.expired

* **Definition:** An event triggered when the card's expiration date has been updated, but the Primary Account Number (PAN) remains the same.
* **Implication:** The merchant's stored expiration date is outdated. Using the old date will cause transaction failures.
* **Action Required:** The merchant must retrieve the new expiration date from the event and use them to ensure transactions are successful.

#### cmp\_au\_card.closed

* **Definition:** A notification from the issuer that the cardholder's account has been permanently closed and is no longer active.
* **Implication:** The stored card is permanently invalid. Any future transaction attempts will fail.
* **Action Required:** The merchant must stop attempting transactions with this card and contact the cardholder to obtain a completely new payment method.

#### cmp\_au\_card.non\_participating

* **Definition:** An event indicating that the card's BIN (the first 6-8 digits) is not part of the Account Updater service.
* **Implication:** The card is not eligible for automatic updates. Its status will not be monitored by the Account Updater service, and no future updates will be provided.
* **Action Required:** The merchant must rely on manual processes (e.g., contacting the customer upon transaction failure) to get updated card information when this card expires or updates.

#### cmp\_au\_card.contact\_cardholder\_advice

* **Definition:** This advice is provided when the issuer determines that the merchant should reach out directly to the cardholder for updated account information.
* **Implication:** It may be used in situations where the account status/update cannot be automatically provided through Account Updater for e.g. due to additional verification is required, account type changes occurred, or due to the issuer’s internal policies on certain card types.
* **Action Required:** Merchants are prompted to contact the cardholder to resolve any issues with payment credentials.

#### cmp\_au\_card.opt\_out

* **Definition:** Indicates that the cardholder has chosen not to participate in the Account Updater service.
* **Implication:** When a cardholder opts out, their account updates (such as a new account number or expiration date) are not shared with merchants or acquirers through Account Updater.
* **Action Required:** Merchants will not receive automatic updates for these accounts and may need to contact the cardholder directly for updated payment information if a transaction fails due to outdated credentials.

{% hint style="info" %}
**Note:** At a high level, `contact_cardholder_advice` and `opt_out` have similar functionality – the merchant is prompted to reach out to the cardholder for account information. Both events can occur *before* or *after* a card is enrolled in Account Updater.
{% endhint %}

#### cmp\_au\_card.unknown

* **Definition:** A temporary status indicating the card is from a participating BIN, but the network could not find a match at this time.
* **Implication:** The card is still successfully enrolled, but no update is available *yet*. The network will continue to check for updates periodically.
* **Action Required:** Treat the card as valid and continue to use it. No immediate merchant action is needed. The status will automatically change if an update (like `expired` or `closed`) is found later.

#### cmp\_au\_card.enrolled

* **Definition:** An event that confirms a card is successfully enrolled in the Account Updater service. It also serves as a "no change" notification, confirming that the stored PAN and expiration date are still correct.
* **Implication:** The card is active, valid, and being monitored for future updates.
* **Action Required:** No action is required. The merchant can continue to use the card with confidence.

#### cmp\_au\_card.enrollment.failed

* **Definition:** A failure event indicating the card could not be registered with the Account Updater service.
* **Implication:** The card will not be monitored for any updates. This could be due to invalid card data, a non-participating network, or other issues.
* **Action Required:** The merchant must rely on manual processes to get updates for this card.

### Setup Requirements <a href="#setup-requirements" id="setup-requirements"></a>

* Account Updater must be enabled on the customer's [CMP account](/cmp/platform/cmp-account).
* For manual workflows, `enrollment_type: manual` must be configured.


# Network Tokens

### Product Overview <a href="#product-overview" id="product-overview"></a>

Network tokens represent a significant advancement in payment processing. They serve as unique digital identifiers, replacing sensitive card details such as the Primary Account Number (PAN) with alphanumeric strings. Businesses seek secure payment methods that maximize checkout conversion rates and enhance the overall customer experience. Network tokens help meet both of those goals.

VGS simplifies payment management by automatically converting stored card numbers (PANs) into secure network tokens. If a customer's card is lost, stolen, or replaced, VGS receives updates from the card networks and automatically updates the tokens, ensuring uninterrupted payments without customer intervention.

### Concept of Tokenization <a href="#concept-of-tokenization" id="concept-of-tokenization"></a>

Tokenization emerged as part of the evolution of payment security and the need to protect sensitive cardholder data in an increasingly digital world. In the early stages, tokenization was used as a data protection mechanism. Companies began using tokens to replace sensitive card information, like Primary Account Numbers (PANs), to enhance security.

Fueled by the rapid growth of e-commerce, mobile payments, and digital wallets transactions, major card networks introduced network tokens. These tokens replace sensitive PANs with unique identifiers, significantly reducing fraud and marking a major advancement in payment security.

### Token Lifecycle Management

In order to ensure cardholder data was not only safe but also ready for use, the networks and issuers integrated lifecycle management into the ecosystem. Lifecycle management ensures that the card data linked to a network token is updated whenever the underlying card or token data changes.

#### Phases of a Token Lifecycle

1. **Create a token** - this is the first step and can have one of the following two outcomes:
   1. **Active**: the network token has been successfully provisioned and is ready for use
   2. **Failed**: the network token provisioning attempt was unsuccessful. Follow the instructions from the [error message documentation](/cmp/developer-resources/guides/testing/network-tokens-webhooks#network-token-provisioning-failure-reason-codes) to determine if retrying the attempt is appropriate.
2. **Lifecycle and Status update events** - once tokens are created, their status and/or the underlying metadata can be modified by the issuer or network. Review the [Network Token Events](/cmp/api-dev/network-token-events) for more information about these states.
   1. **Lifecycle event: Updated**
   2. **Status updates: Suspended, Activated, Deleted**

| State          | Meaning                                                                                                                                                                      | Recommendation                                                                          |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `activated`    | The network token has been reactivated after being suspended or updated                                                                                                      | Continue token usage.                                                                   |
| `suspended`    | <p>The network has temporarily disabled the token. </p><p></p><p>This typically occurs when new cards are being issued and may be followed by any of the other statuses.</p> | Stop using this token for transactions until you receive an `activated` event.          |
| `deleted`      | The token was removed by the bank or merchant.                                                                                                                               | Do not retry. You must re-enroll the card or ask the customer for a new payment method. |
| `card_updated` | Card metadata (e.g., expiry) changed. This is a lifecycle event update.                                                                                                      | Update your local database with the new details provided in the webhook payload.        |

### Network Token Provisioning Failures

#### Provisioning Failure Reason Codes

These reason codes occur when attempting to enroll a card for network tokenization. CMP includes these reason codes and reason texts from the network in both:

* The API response
* Webhook notifications

<table><thead><tr><th width="187.2421875">Reason Code</th><th width="168.3150634765625">Reason Text</th><th width="112.296875">Customer Retry?</th><th width="90.708251953125">VGS Retry?</th><th>Recommendation</th></tr></thead><tbody><tr><td><code>provisioning_failed</code></td><td>Invalid payment instrument or data associated with the payment instrument</td><td>No</td><td>No</td><td>Create a new card with the <strong>updated</strong> card information and use the new cardID to provision a new network token.</td></tr><tr><td><code>card_not_allowed</code></td><td>Card cannot be used for tokenization at this moment. Please try again later</td><td>Yes</td><td>No</td><td><p><strong>Customer:</strong> Wait for 90 days minimum to retry</p><p><br></p></td></tr><tr><td><code>card_not_allowed</code></td><td>The requested action is not allowed for a given PAN. This card is valid but cannot be used for tokenization.</td><td>No</td><td>No</td><td><p><strong>Hard Decline.</strong> This specific card is ineligible for tokenization. </p><p></p><p>Create a new card with the updated card information and use the new cardID to provision a new network token.</p><p><br></p></td></tr><tr><td><code>declined</code></td><td>This card is not eligible for tokenization at this moment with the Network; Retry at a later time.</td><td>Yes</td><td>No</td><td><strong>Customer:</strong> Wait for 90 days minimum to retry</td></tr><tr><td><code>declined</code></td><td>No further operations are allowed. Contact bank</td><td>No</td><td>No</td><td><p><strong>Hard decline.</strong> The issuer has blocked the action. User must contact their bank. </p><p></p><p>Create a new card with the updated card information and use the new cardID to provision a new network token.</p></td></tr><tr><td><code>service_unavailable</code></td><td>Downstream network/service unavailable</td><td>No</td><td>Yes</td><td><strong>VGS Retries</strong> automatically (up to 3 times in 12 hours).</td></tr><tr><td><code>rejected</code></td><td>This card is not eligible for tokenization at this moment with the Network; Retry later.</td><td>Yes</td><td>No</td><td>Similar to <code>declined</code>. Retry later using the new <code>cardID</code>.</td></tr></tbody></table>

#### 2. Retry & Maintenance Rules

* **VGS Automatic Retries:** VGS automatically retries provisioning **only** for `service_unavailable` errors. It attempts up to 3 retries within a 12-hour window. If all attempts fail, retries stop, no notification is sent, and the process stops.
* **Customer-Initiated Retries:** For reason codes marked **Customer Retry = Yes,** the merchant (you) must initiate the retry.&#x20;
  * **Important:** Use the dedicated network token endpoint with the existing cardID rather than creating a new card object to avoid duplicate card issues.
* **Duplicate Card Detection Behavior:** If Duplicate Card Detection is **enabled,** resending the same card details will return a 303 status. You must use the original cardID to attempt tokenization again.
* **Expiration Handling:**&#x20;
  * **Visa**: Tokens typically expire when the underlying PAN expires.
  * **Mastercard**: Tokens may remain valid for up to 36 months, even if the PAN expires.
  * **Action:** If a token expires:
    * It does **not** auto-provision.
    * Use **Account Updater** to refresh card details, then re-enroll the card for tokenization.

### Types of Tokens <a href="#types-of-tokens" id="types-of-tokens"></a>

#### Understanding Network Tokens Types: From Device Wallets to Controlled Commerce <a href="#understanding-network-tokens-types-from-device-wallets-to-controlled-commerce" id="understanding-network-tokens-types-from-device-wallets-to-controlled-commerce"></a>

The landscape of digital payments underwent a transformation with the introduction of network tokens in 2015, spearheaded by device-based wallets such as Apple Pay and Google Pay. Today, payment networks exert granular control over these tokens through domain controls. These configurations, set at the network level, determine precisely where, when, and how a network token can be used, thereby defining its context and the platform on which it is used.

Though terminology varies across networks, current network tokens broadly fall into these evolving categories, each subject to increasingly stringent domain controls:

* **Device Tokens (**[**Apple Pay**](/cmp/payment-credentials/apple-pay) **or** [**Google Pay**](/cmp/payment-credentials/google-pay)**:** These tokens enhance the security of digital commerce, specifically for mobile wallets.
  * **Secure Element (SE) Tokens:** Predominantly used with Apple Pay, SE tokens convert sensitive card credentials into a secure digital format. They are provisioned to a secure element in the cloud, primarily facilitating secure in-store contactless payments.
  * **Host Card Emulation (HCE) Tokens:** Similar in purpose to SE tokens, HCE tokens are largely associated with Google Pay. They tokenize card credentials and are provisioned as both cloud and device-bound. These tokens enable both in-store contactless payments and convenient in-app shopping experiences.
* **Card-on-File (COF) Tokens:** Designed to safeguard sensitive customer data for online merchants while enabling innovative shopping experiences. COF tokens are provisioned to the cloud and restricted to a specific merchant. They are utilized for both online and in-app purchases, supporting flexible payment options like Buy Now, Pay Later (BNPL), installment plans, and subscription services.
* **eCommerce (Enabler) Tokens:** These tokens streamline and secure the checkout process for consumers across a diverse range of merchants and wallets. They can be provisioned as cloud based and/or device-bound. Unlike Card-on-File Tokens, eCommerce Network Tokens were built to be passed from one entity to another. For instance, the token can be tied to a single Enabler (e.g. a wallet) that is then allowed to share the token to other merchants or platforms for their own processing.
  * **Wallet Enablement:** For online transactions, digital wallets like Google Pay, PayPal, and others utilize eCommerce Network Tokens to pass their tokens through to the underlying merchants.
  * **Additional Merchant Use Cases:** These tokens can also be used for various other use cases online and in-app purchase channels, including retail, fast food, rideshare services, and more.

#### VGS's Role in Streamlining Different Network Token Type Adoption <a href="#vgss-role-in-streamlining-different-network-token-type-adoption" id="vgss-role-in-streamlining-different-network-token-type-adoption"></a>

Token Service Providers (TSPs) must undergo a rigorous certification and testing process to support these diverse token types. VGS has successfully completed the necessary certifications for both **eCommerce** and **COF token** implementations, where applicable and supported by the networks. A Token Requester's enabled token types are determined by the network, aligning with its intended use case. While COF is the most common token type, any alternative requires network discussion and approval. VGS simplifies the integration process for Token Requesters, making it easier for them to support either or both COF and eCommerce token types. VGS continues to evaluate and develop to the latest specifications from the networks, including new innovative network token types.

### Network Tokens via CMP <a href="#network-tokens-via-cmp" id="network-tokens-via-cmp"></a>

As [customer accounts](/cmp/platform/cmp-account) are activated for network tokens after onboarding with networks. The customer has two paths for facilitating Network token enrollment.

#### On-Create Enrollment <a href="#on-create-enrollment" id="on-create-enrollment"></a>

This is the default setting. When a card object is created, the system automatically processes and activates the network token services enabled for the account. A webhook notification is sent with the result of the network token provisioning, whether it succeeds or fails.

#### Manual Enrollment: <a href="#manual-enrollment" id="manual-enrollment"></a>

With manual enrollment, card creation does not automatically trigger network token creation. The customer must explicitly invoke the network token individual service endpoints to create network tokenization. For greater control, clients can opt for a "manual" configuration, which creates a basic card object without automatic processing. This allows for granular control over service invocation using dedicated endpoints:

Manual provisionings are processed through independent API endpoints and are normally synchronous, meaning a response is returned immediately. To ensure timely processing, VGS applies a 10-second timeout. If a response takes longer, the request is automatically handled asynchronously, with the result delivered via webhook. In such cases, the initial response will indicate: ‘*The request will be processed asynchronously*'.

* **Manual Network Token Provisioning endpoint: `POST /cards/{CardID}/network-tokens`**
  * Provides flexibility to control when Network Tokens are created.
  * Use this endpoint to provision Network Token on individual cards after creation.
  * A confirmation response with the network token provisioning result is returned immediately in the synchronous response.
  * A webhook notification is sent upon a successful network token is created.
  * Enrollment-Type/Provisioning-Method: **Manual**.
  * For **the independent Network Token endpoint**, provisioning is attempted for a card using the Card ID. If provisioning succeeds, the token is returned with an `active` state. If provisioning fails, a failure message is returned instead. If NT provisioning is attempted for a card whose existing network token is in a suspended or deleted state in CMP, provisioning is attempted again with the network. The response will either return the token with an `active` state or a failure message.
  * For **GET Card by ID,** the Network Token object returns the latest token details available in our system with its current state: `active`, `deleted`, `failed`, or `suspended`.
* **Network Token Deletion endpoint: `DELETE /cards/{CardID}/network-tokens`**
  * By default, deleting a network token on a card ID removes network token **across all duplicate card records.**
  * The Network Token status is marked as deleted in VGS systems.
  * The Network Token becomes invalid and stops receiving updates.
  * Enrollment-Type/Provisioning-Method: The network token may have been provisioned to a card either:
    * **Manually**, via the `/network-tokens` endpoint after card creation using the manual method , or
    * **Automatically**, if created using the `oncreate` method during card registration.
  * Once a network token is deleted for a card:
    * Cryptogram requests (`POST /cards/{CardID}/cryptogram`) are no longer allowed.
    * The network token will no longer receive any lifecycle updates.
    * The deleted network token is inactive and cannot be used for any payment transactions.
    * When retrieving the card object (`GET /cards/{CardID}`), the Network Token object will no longer be present in the response.

### Limitations

* **America Express (Amex)**
  * VGS currently supports only Direct merchants. OptBlue merchants are not supported.&#x20;
  * For high provision success rate, clients are encouraged to add cardholders phone number or email address.
  * While American Express (Amex) does not currently support test cards in their sandbox environment Network Tokens, VGS provides mock cards designed to simulate various testing scenarios
  * VGS Mock Cards are internally built test cards that do not communicate with the networks.
* **Discover**&#x20;
  * When the Duplicate feature is enabled, for Discover cards, a new Network Token is created for each provisioning attempt on a given PAN. Discover NT supports multiple token provisioning even when a Network Token already exists for that PAN, and each Network Token's lifecycle can be managed independently.
  * Supported for only on US Discover MIDs.
  * Cryptogram generated for Discover network tokens are 3 digit values and should be used in the CVV/CVC field when submitted for authorization.

### Transacting with Network Tokens <a href="#transacting-with-network-tokens" id="transacting-with-network-tokens"></a>

To perform a transaction with network tokens, a cryptogram is needed. A network token cryptogram is a unique, one-time encrypted code generated for each transaction using a network token. It serves as a crucial security measure to authenticate and secure the transaction.

With Network token being created and mapped to the card ID , Customers need to invoke the Request Cryptogram endpoint to get the cryptogram which can be be used by the Customers in their authorization requests with their respective PSPs.

**Endpoint: `POST /cards/{CardID}/cryptogram`**

### Types of Cryptograms <a href="#types-of-cryptograms" id="types-of-cryptograms"></a>

**TAVV (Token Authentication Verification Value):**

* This is the most common type of network token cryptogram, used across Visa/MC networks.
  * Up to 32 characters.
  * Some networks require the transaction type when generating.
  * Cryptogram returned for these networks should be populated in the cryptogram field when submitting for authorization.
* When requesting for cryptogram, Discover will provide a 3-digit cryptogram. This cryptogram, returned as a TAVV in the VGS response, should be used in the CVV/CVC field during authorization.
* When a cryptogram is requested, Amex's DCSC cryptogram is returned as TAVV.

**DTVV (Dynamic Token Verification Value):**

* A short cryptogram resembling a 3-digit CVV.
* *Unique to Visa.*
* Must be explicitly enabled by VGS. Contact <support@vgs.io> to enable.

**Cryptogram Fetch - Best Practices:**

* Always generate a new, one-time-use cryptogram for each authorization.
* Do not store cryptograms after use.
* Ensure submitted values (TAVV/DTVV, ECI) remain unchanged during authorization.

**Key Features**

* Synchronous Cryptogram Generation: Receive network tokens via Crypto request instantly within the API response.
* Cryptogram Validity: Cryptogram is valid for 24 hours.
* Webhook Integration: Not applicable

### Network Token Notification Status

Once a network token has been provisioned, its status may change due to various events. We provide these status updates through our Webhook integration. Below is a explanation of what each update signifies:

#### cmp\_network\_token.provisioned

* **Definition:** A network token has been provisioned and is active.
* **Implication:** The token is active and valid for use. You can request cryptograms and processing transactions.
* **Action Required:** Update your internal database to reflect that this token is "Active." No further action is needed other than resuming normal payment flows.

#### **cmp\_network\_token.provisioning\_failed**

* **Definition:** The network token was not provisioned; the initial request was unsuccessful.
* **Implication:** No network token was created. This occurs due to eligibility issues, incorrect card data, or issuer rejection.
* **Action Required:** Review the specific failure reason. If the card is ineligible for a network token, fallback to processing via the standard PAN.

#### cmp\_network\_token.activated

* **Definition:** A network token has been moved back to an active state following a prior suspension.
* **Implication:** The token is once again valid for use. You can resume requesting cryptograms and processing transactions.
* **Action Required:** Update your internal database to reflect that this token is "Active." No further action is needed other than resuming normal payment flows.

#### **cmp\_network\_token.deleted**

* **Definition:** The network token has been permanently removed. This can be triggered manually via an API call or automatically by the issuing bank (e.g., if the credit card account is closed).
* **Implication:** The token is no longer valid and cannot be reactivated. Any attempt to use it will result in a hard decline.
* **Action Required:** Remove this token from your system or mark it as "Deleted." The customer must re-enroll or provide a new card to generate a new token.

#### **cmp\_network\_token.suspended**

* **Definition:** A network token has been suspended by the issuing card bank via the networks. This often occurs during fraud analysis or operational maintenance on the customer's account.
* **Implication:** The token is temporarily inactive. No new cryptograms can be requested while in this state.&#x20;
* **Action Required:** Monitor for an Activated event. Plan to avoid using this token for active transactions to prevent unnecessary declines.

#### **cmp\_card\_updated**

* **Definition:** The network has updated the card metadata associated with the token.
* **Implication:** The token remains valid, but underlying details (such as a new expiration date or card art) have changed.
* **Action Required:** Update your records with the new metadata to ensure your customer-facing information stays current.


# Card Art

#### Overview

Issuer card art involves displaying customized images or logos on payment cards issued by financial institutions like banks or credit card companies, offering a unique appearance to these cards. This feature is prominently showcased during the checkout process for both online and in-store purchases. Compliance with network branding requirements is essential for merchants when displaying issuer card art or network logos, particularly when customers save their credentials with a merchant. Card art is made available only when Network token is created.

#### Benefits of Card Art

Displaying issuer card art during checkout strengthens brand recognition and customer engagement. Financial institutions can reinforce their identity by showcasing their logos or branded images, building a stronger connection with their customers. This also fosters trust, as customers can easily recognize their card issuer during payment. Furthermore, issuer card art enhances the checkout experience, creating a visually appealing and seamless process that encourages customer loyalty.&#x20;

#### Card Art Integration

The card art feature can be enabled or disabled at the account level. When a network token is provisioned, upon card creation, the associated card art will be fetched and stored. A network token provisioned successful notification will be sent after the network token is provisioned.&#x20;

To retrieve card art, use the "Get Card by ID API", which returns the latest metadata returned by the network available from the network, including card art if available, post-notification. Customers can then download the card art image directly via the provided asset URL without requiring a barrier authorization token.

Card art URL expires in 6hrs. If the card art download URL expires, regenerate it by calling the "Get Card by ID" again.&#x20;

You can view a sample GET card response here:[ VGS Card Management API – Get a Card](/cmp/developer-resources/api).

#### Downloading Card Art

Card art can be downloaded using a simple HTTP GET request. The image URL is provided in the network\_token object of the GET Card by ID API response, under the meta.card\_art section. This is a secure, pre-signed URL hosted on an AWS-managed service. It is valid for a limited time and can be accessed from any platform—web, mobile, or backend service.

You can download the image using any standard HTTP client (e.g., curl, Postman, browser, etc.).&#x20;

**Example:**

```
curl "https://assets.calm.live.verygoodsecurity.com/live/calm/assets/9018116a-e0b7-4e5b-8227-d33615632856?Expires=1752083981&Signature=bJ-Lx89Vaqfadbx4-AhXoS~Q648Kl3oS6MGiKVUsIkAEdIV6x93uY24tdcxLT5IlLVMoOb3oJkTEwUtakpuDF2ZnA72Iy37bw-x86DWg4cOH-EZWEtERFbB~AFISArH62kxIgItR-CjSByuGxNFl~q-7X2Xo-xDG4D4LewUhNRiLy2zxUmHk5L5qFegJRRFOsz8NyUaGmf8BU8TDuUnyqNGu-G8FzahJ1QQSAS3UVqUlwiMuNZDOC~ySrZQrZ65Ij8QzAPeyLzTj2FhOXU66P6wFIoLCes~qDz~Z5lFZRjRbxrpRNhueKHjCU6vmwRKZ6mZV-qloHz0D8tszs5kN8w__&Key-Pair-Id=K14FU0X3LR21JX"
```

There is no difference in behavior whether the URL is accessed from a mobile device or a web browser. The download is fully platform-agnostic, as the service does not depend on the origin of the request.&#x20;

#### Card Art Sequence

* **Provisioning & Card Art Request**&#x20;
  * Customer
    * Calls Create Card or triggers Provision Network Token using the CMP API.
  * VGS
    * Initiates Network Token Provisioning with the Card Network.
      * Receives the Network Token from the Card Network.
      * Automatically fetches the associated Card Art for the token.
      * Receives the Card Art data.
      * Stores both the Token and Card Art securely.
      * Sends a "Network Token Successfully Provisioned" notification back to the customer.
* **Downloading Card Art (Customer-driven)**
  * Customer:
    * Makes a [GET /cards/{card-id}](/cmp/developer-resources/api/cards) request to retrieve card details.
  * VGS
    * Returns card metadata, including a pre-signed download\_url to retrieve the card art image.
  * Customer:
    * Uses the download\_url to download the card art image.<br>

**Note:**&#x20;

* The download\_url remains valid for 6 hours. After it expires, any access attempts will return a 404 error.&#x20;
* If the URL expires, you must repeat the [GET /cards/{card-id} ](/cmp/developer-resources/api/cards)call to obtain a new one.
* The card art metadata fields returned in the response may vary, as they depend on both the issuer and the network. Not all fields are guaranteed to be present.
* The latency to generate card art may vary depending on the image size and the response times from the networks.
* Discover Card Art is fixed and not dynamic.&#x20;

#### Merchant Expectations and Responsibilities

As part of the tokenization process, networks send the issuer’s card art (if provided by the issuer) during the token provisioning flow. This card art may be shown in cardholder-facing PAN display interactions. *Merchants should not rely on the VGS-hosted card art URL for real-time display. The URL is time-bound and intended for temporary access only. Instead, merchants are expected to download and store the image locally within their own systems for use in their front-end or checkout experiences.* If the actual card art images are unavailable, the card can be rendered using the color scheme provided by networks on behalf of the issuer. If the images cannot be rendered during the payment flow (e.g., on monochrome devices), or if the form-factor display is too small to render all the elements (e.g., smartwatches), either the Visa brand or a generic Visa-branded card must be displayed next to the last four digits of the card number. During the payment process, the merchant may include text to let the cardholder know that the PAN is being converted to a digital account number.&#x20;

#### Best Practices for Image Rendering

* The digital card art images that Visa provides to the token requester do not include the cardholder's name, PAN, or expiration date, either in generic form or using actual values.&#x20;
* The digital card art images will not include rounded corners; the corners will need to be rounded on the display.&#x20;
* The token requestor should round the corners of digital card art with a radius of 2.88–3.48 mm.&#x20;
* The last four digits of the card number or digital account number and cardholder name should be placed in the bottom left corner of the digital card art (if used).&#x20;
* No images or text, other than the last four digits of the card number or digital account number and/or cardholder name, may be placed over the card art.&#x20;
* The last four digits of the Visa card number and the digital account number must always be preceded by “Visa” (i.e., Visa 9876).&#x20;
* A generic card image should be rendered in the absence of an actual card image.&#x20;
* These should be used if and only if the card images cannot be rendered due to technical reasons.&#x20;
* Token requestors should be able to support PNG images for the card art.&#x20;

\
**Other Visa Branding Requirements**

* "Visa" should always be spelled with an initial capital ‘V’ and not in all caps.&#x20;
* Either the Visa Brand Mark or the Visa name in text may be used.&#x20;
* The approved Visa Brand Mark is available from your Visa representative.&#x20;
* Text must be provided along with the term “digital account number” to explain its role and relevance to the cardholder (if applicable).&#x20;

#### Card Art Ownership Disclaimer

This card art is provided to the token requestor, subject to certain issuer brand guidelines and other use restrictions set forth in the token requestor’s agreement with networks.&#x20;

VGS passes down the card art from the network as is; issuer may choose to decide what card art is given for the token requestor.

*Customers are required to adhere to the branding guidelines of the respective card networks (e.g., Visa and Mastercard) when displaying card art for facilitating digital payments.*

#### Onboarding Requirements

To receive and download card art assets, the following conditions must be met:

* **Network Tokenization** must be enabled for the account.
* **Card Art** must be enabled at the account level.

Must be explicitly enabled by VGS. Please contact  <support@vgs.io> or your designated VGS implementation representative to enable Card Art on your account.

**Reference:**

[Visa Branding Guidelines ](https://www.merchantsignage.visa.com/brandguidelines)

[Mastercard Branding Guidelines](https://www.mastercard.com/brandcenter/ca/en/brand-requirements.html)&#x20;


# Card Attributes

The VGS Card Attributes Service offers a robust and dynamic direct-to-network BIN (Bank Identification Number) database. Unlike standard, static BIN lookups, this service provides continuously updated and comprehensive card insights directly from the card networks. This empowers our clients with an unparalleled understanding of their customers and the intricate makeup of their payment cards. We continue to expand our data sources to ensure clients have access to the most up-to-date card information.

By providing deep visibility into card behavior, including issuer details, card type (credit, debit, prepaid), funding source, regional information, and recurring payment support, the VGS Card Attributes Service enables businesses to make exceptionally swift and informed decisions. This critical intelligence allows them to:

* **Optimize Payment Routing:** Intelligently direct transactions to the most efficient and cost-effective networks, leading to higher authorization rates and reduced processing fees.
* **Strengthen Fraud Prevention:** Leverage enriched card data to identify and mitigate potential fraud risks more accurately, by cross-referencing card attributes with transaction patterns and user behavior.
* **Enhance Customer Experience:** Streamline the checkout process by pre-populating fields, offer tailored promotions based on card benefits, and proactively manage subscription payments by identifying non-reloadable cards.
* **Ensure Regulatory Compliance:** Easily adhere to evolving payment regulations and regional mandates by having accurate and up-to-date card information at their fingertips.
* **Drive Business Growth:** Uncover valuable insights into customer spending habits and preferences, enabling more effective marketing strategies, loyalty programs, and product development.

In essence, the VGS Card Attributes Service offer a powerful, real-time intelligence layer that transforms raw card information into actionable insights, ultimately helping businesses protect their operations and unlock new avenues for growth.

#### Card Attributes via CMP <a href="#card-attributes-via-cmp" id="card-attributes-via-cmp"></a>

The Card Attributes service supports Visa, Mastercard, Discover and Amex cards and other additional networks. Enhanced card attributes will be visible in Create Card and GET Card API responses.

Clients will have to sign up to get comprehensive attributes by enabling attributes through account settings in CMP, or by contacting customer support **`(support@vgs.io)`**. These comprehensive attributes will also be visible in the Create Card and GET Card API responses.&#x20;

The Card Attributes service also supports `PAN` and `DPAN` BIN lookup. For DPAN, the data will be provided if available in our database.&#x20;

The Card Attribute Service response return 8-digit BINs for Mastercard and Visa, and 6-digit BINs for Discover and American Express (Amex).

**The comprehensive list of attributes and their definition**

<table data-header-hidden><thead><tr><th width="195.43896484375"></th><th width="200.7379150390625"></th><th width="216.789794921875"></th><th></th></tr></thead><tbody><tr><td><strong>Field Name</strong></td><td><strong>Description</strong></td><td><strong>Examples</strong></td><td><strong>Attributes Type</strong></td></tr><tr><td><code>card_number_length</code></td><td>The number of digits in the card number.</td><td>16</td><td>Enriched</td></tr><tr><td><code>card_brand</code></td><td>The name of the card brand.</td><td>MASTERCARD, VISA, DISCOVER, AMERICAN EXPRESS<br><br><a href="/pages/oQrI9dGIpimvjPVWHZtb">Full list here</a>.</td><td>Basic</td></tr><tr><td><code>card_type</code></td><td>The category of the card. </td><td>CREDIT, DEBIT, CHARGE CARD</td><td>Basic</td></tr><tr><td><code>card_segment_type</code></td><td>A classification that helps identify the cardholder's spending habits or income level.</td><td>PERSONAL, COMMERCIAL</td><td>Enriched</td></tr><tr><td><code>virtual_card</code></td><td>Indicates whether the card is a digital-only card without a physical plastic version.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>prepaid_card</code></td><td>Specifies if the card is a prepaid card, which is loaded with funds beforehand and isn't linked to a bank account.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>product_name</code></td><td>The specific name of the card product.</td><td>CLASSIC, STANDARD, CORPORATE, PLATINUM, SIGNATURE, TRADITIONAL REWARDS</td><td>Enriched</td></tr><tr><td><code>issuer_bin</code></td><td>The Bank Identification Number (BIN), which is the first 6 or 8 digits of a card number that identifies the issuing institution.</td><td>First 6 or 8 digits</td><td>Enriched</td></tr><tr><td><code>country_name</code></td><td>The full name of the country where the card was issued.<br><br>Tied to the The ISO 3166-1 numeric-3 codes for the country, but presented in a human readable format indicating the full name of the country. </td><td>UNITED STATES, GERMANY<br><br><a href="https://www.iso.org/obp/ui/#search/code/">Full list here.</a></td><td>Enriched</td></tr><tr><td><code>country_numeric</code></td><td>The ISO 3166-1 numeric-3 codes for the country.</td><td>840, 276<br><br><a href="https://www.iso.org/obp/ui/#search/code/">Full list here.</a></td><td>Enriched</td></tr><tr><td><code>reloadable</code></td><td>Indicates whether the prepaid card can be reloaded with additional funds.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>hsa</code></td><td>Indicates if the card is a Health Savings Account (HSA) card. This allows you to pay for eligible medical expenses with pre-tax money.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>fsa</code></td><td>Specifies if the card is a Flexible Spending Account (FSA) card, which is similar to an HSA but has different rules for fund rollovers and eligibility.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>ebt</code></td><td>Indicates if the card is an Electronic Benefits Transfer (EBT) card, used to deliver government benefits.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>issuer_name</code></td><td>The name of the financial institution that issued the card.</td><td>U.S. EQUITY ADVANTAGE, INC, FISERV SOLUTIONS</td><td>Enriched</td></tr><tr><td><code>issuer_phone_number</code></td><td>The phone number for the card issuer's customer service.</td><td>352-378-2125</td><td>Enriched</td></tr><tr><td><code>issuer_website</code></td><td>The website for the card issuer.</td><td><a href="http://www.suntrust.com/">http://www.suntrust.com/</a> </td><td>Enriched</td></tr><tr><td><code>commercial_level2</code></td><td>Indicator of Commercial Level 2 interchange rate eligibility.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>commercial_level3</code></td><td>Indicator of Commercial Level 3 interchange rate eligibility.</td><td>True, False</td><td>Enriched</td></tr><tr><td><code>regulated</code></td><td>Indicates the regulatory status of the card.</td><td>Y, N</td><td>Enriched</td></tr><tr><td><code>additional_card_brand</code></td><td>The name of the card brand.</td><td>BANCONTACT, CB<br><br><a href="/pages/oQrI9dGIpimvjPVWHZtb">Full list here</a>.</td><td>Enriched</td></tr></tbody></table>


# Data Elements

#### Card Brands

The `card_brand` field in the [Card Attributes API](/cmp/developer-resources/api/credential-management-v1-apis-calm/card-attributes-v1) is populated with enumerated values from an existing list of card brands.

See the below list for the compete set of potential values:

| AMERICAN EXPRESS          |
| ------------------------- |
| ARGENCARD                 |
| ATM CARD                  |
| AURA                      |
| BANCONTACT                |
| BANKCARD                  |
| BELKART                   |
| BP FUEL CARD              |
| CABAL                     |
| CARNET                    |
| CB                        |
| CHINA UNION PAY           |
| CHJONES FUEL CARD         |
| CIRRUS                    |
| CMI                       |
| CODENSA                   |
| DANKORT                   |
| DINACARD                  |
| DINERS CLUB INTERNATIONAL |
| DISCOVER                  |
| DUET                      |
| EBT                       |
| EFTPOS                    |
| ELO                       |
| EUROSHELL FUEL CARD       |
| FUEL CARD                 |
| GE CAPITAL                |
| GIROCARD                  |
| GLOBAL BC                 |
| HIPERCARD                 |
| HRG STORE CARD            |
| HUMOCARD                  |
| JCB                       |
| LANKAPAY                  |
| LOCAL BRAND               |
| LOYALTY CARD              |
| LUKOIL FUEL CARD          |
| MAESTRO                   |
| MAESTRO                   |
| MASTERCARD                |
| MEEZA                     |
| MIR                       |
| NEWDAY                    |
| NSPK                      |
| OUROCARD                  |
| PAGOBANCOMAT              |
| PAYPAK                    |
| PAYPAL                    |
| PHH FUEL CARD             |
| PRIVATE LABEL             |
| PROSTIR                   |
| RED FUEL CARD             |
| RED LIQUID FUEL CARD      |
| RUPAY                     |
| SBERCARD                  |
| SODEXO                    |
| STAR REWARDS              |
| TARJETA CENCOSUD          |
| TARJETA NARANJA           |
| TROY                      |
| UATP                      |
| UK FUEL CARD              |
| UZCARD                    |
| VERVE                     |
| VISA                      |
| VOYAGER                   |
| VPAY                      |
| WEXCARD                   |


# 3DS

### 3DS Overview

**3-D Secure (3DS)** is an industry-standard security protocol that provides an additional layer of protection for online credit and debit card payments, commonly referred to as Card-Not-Present (CNP) transactions. VGS supports the **3-D Secure protocol version 2.2.0 and above**.

Its primary goal is to confirm that the person making an online purchase is the legitimate cardholder, which significantly reduces fraud. In some markets, such as the European Union, 3DS is a critical framework businesses rely on to comply with **Strong Customer Authentication (SCA)** regulations. The "3-D" refers to the three parties (domains) that securely interact during this process:

1. **Acquirer:** The card acceptor's bank or payment provider (the merchant's side).
2. **Issuer:** The cardholder's bank (the payer's side).
3. **Interoperability:** The card networks (Visa, Mastercard, etc.), systems (the internet, terminals, etc.), and service providers (VGS, Cardinal Commerce, etc.)  that facilitate the exchange of data.

*Note: This documentation provides a general 3DS overview and is not legal or commercial advice. VGS operates solely as a connectivity platform to facilitate secure data passthrough between its customers and payment-related services; we are not a Payment Service Provider (PSP) or Acquirer. You are responsible for your own regulatory compliance and all authentication and transaction logic. The 3DS* [*standard and specifications*](https://www.emvco.com/emv-technologies/3-d-secure/) *are defined by EMVCo.*

### 3DS Authentication vs Data Sharing

There are two options available with VGS's 3DS service: Authentication and Data Sharing. While both leverage the 3DS protocol, they serve different purposes. Authentication prioritizes compliance and liability protection, while Data Sharing optimizes for a seamless user experience and improved approvals.

**Challenge Flow:**\
When a transaction requires step-up authentication, cardholders may be challenged by their issuing bank using methods such as OTP, mobile banking approval, or biometrics. Challenge flows are supported across **Visa, Mastercard, American Express, and Discover**.

**Data Sharing (Data-Only Authentication):**\
The data sharing authentication flow allows merchants to send transaction and device data to issuers without triggering a cardholder challenge. This capability is currently supported for **Visa and Mastercard transactions only**.

#### Why Use 3DS Authentication?

3DS Authentication adds a layer of stronger authentication to the baseline 3DS, such as one-time passwords, that enable businesses to reduce risk and comply with critical regulations.

1. **Chargeback Liability Shift:** When a transaction is successfully authenticated via 3DS, the liability for fraudulent chargebacks often shifts from your business to the card-issuing bank.
2. **Regulatory Compliance:** 3DS is a primary method to comply with global regulations, such as Strong Customer Authentication (SCA) under the European PSD2 directive, which mandates multi-factor authentication for many online payments.

#### Why Use 3DS Data Sharing?

3DS Data Sharing allows businesses to share rich risk data with issuers *without* triggering a cardholder challenge. This background exchange helps "prime" the issuer's decision-making process to trust the user. However, unlike 3DS Authentication, 3DS Data Sharing **usually** **does not shift chargeback liability to the issuer.**

1. **Authorization Uplift:** By sharing data points like the cardholder's browser information and transaction details, you provide a digital fingerprint of the user's device and give issuers the context they need to approve low-risk transactions. This transparency reduces false declines and helps improve authorization rates, even without a full authentication challenge.
2. **Seamless User Experience:** Data sharing is informational only, it eliminates the possibility of a cardholder challenge (e.g., OTP). This guarantees a seamless checkout experience that preserves your conversion funnel, making it ideal for transactions where speed and a frictionless checkout are the priority.

### 3DS Authentication Customer Experience: Frictionless vs. Challenge Flows

VGS customers can leverage the 3DS service within the CMP platform to perform cardholder authentication. The 3DS service utilizes **Risk-Based Authentication (RBA)** that can make an authentication decision based solely on the data provided upfront, or to "step-up" the flow with a challenge that the cardholder needs to complete. Qualifying transactions will proceed via one of two paths:

#### **1. Frictionless Flow**

In the frictionless flow, the authentication occurs silently in the background without any interruption to the customer.

* **How it Works:** Your system sends a rich set of data (including transaction details and a unique device fingerprint) to the cardholder's bank.
* **The Decision:** The card-issuing bank reviews this data. If the transaction is deemed low-risk, it is approved and authenticated without requiring any action from the customer.
* **Benefit:** This increases approval rates for legitimate customers and significantly reduces cart abandonment.

#### **2. Challenge Flow**&#x20;

The challenge flow is initiated only when the card-issuing bank is not fully confident in the transaction based on the data alone (e.g., a high-value purchase or new device).

* **How it Works:** The bank "challenges" the user to provide additional proof of identity. This is seamlessly embedded within your checkout page (no disruptive pop-ups).
* **Authentication Methods:** The customer verifies their identity using Strong Customer Authentication (SCA) methods, such as:
  * Entering a One-Time Passcode (OTP) sent to their phone.
  * Approving the purchase through their mobile banking app.
  * Using biometrics (fingerprint or facial recognition).
* **Benefit:** A successful challenge results in a liability shift for the merchant, providing the highest level of fraud protection.

### **3DS - Customer-Initiated Transaction vs Merchant-Initiated Transaction**

3DS Authentication is used to verify the cardholder and establish trust with the card. Depending on who initiates the transaction, it falls into one of two categories:

* **Customer-Initiated Transaction (CIT):** A cardholder is attempting to perform an individual card-not-present transaction.
* **Merchant-Initiated Transaction (MIT):** A merchant is attempting to perform a subsequent transaction with a card that was previously used in a CIT.&#x20;

#### 3DS Authentication During CIT&#x20;

* **Key Characteristics:**
  * **Initiated by:** Customer
  * **3DS required:** Yes
  * **Objective:** Authenticate the cardholder and securely store the card
* **Common Examples:**
  * One-time purchases
  * First-time subscription signups
  * Saving a card on file
  * Initial setup of recurring or usage-based plans
* **Important:** Flag the transaction as **CIT** and include the 3DS authentication response in your authorization request.

#### 3DS Authentication During MIT

In order to reduce friction, but retain the benefits of 3DS Authentication, ensure the merchant-initiated transactions are tied to a previously authenticated CIT.

This confirms to the bank that the MIT is based on a secure, previously authenticated transaction, and allows it to proceed without triggering 3DS again.

* **Key Characteristics:**
  * **Initiated by:** Merchant
  * **3DS required:** No
  * **Objective:** Collect payment based on a previously established agreement
* **Common Examples:**
  * Recurring subscription payments (e.g., streaming platforms)
  * Usage-based billing (electricity, cloud storage)
  * Delayed charges (such as post-checkout hotel charges)
  * No-show or cancellation fees
  * Installment payments
* **Important:** Flag the transaction as **Merchant-Initiated** and include references to the original CIT.

### Merchant Onboarding: Key Steps for 3DS Integration

1. **Acquirer Setup:**
   * The merchant must provide the Acquirer BIN registration information, obtained from their current acquirer, within the **`merchant_info`** object when submitting the 3DS authentication request.
   * The same Acquirer BIN should be used consistently for both authentication (3DS) and authorization flows.
2. **Production Activation:**
   * Before submitting any Authorization requests (3DS) in Production, merchants must confirm with their acquirer or Payment Service Provider (PSP) that authorization processing is fully activated to successfully pass the 3DS data through. This step is critical to ensure smooth 3DS processing and prevent transaction mismatches.
3. **Data Transmission:**
   * VGS 3DS data is widely accepted. Merchants must embed the 3DS authentication result within their Authorization or Purchase requests. However each PSP, however, has its own requirements for processing external 3DS authentication details. To correctly map these values, refer to the PSP’s documentation or contact their support. Typically, fields such as **ECI** and **CAVV** (cryptogram) are required, and in some cases, additional parameters from the transaction info such as **Directory Server or Access Control Server transaction IDs** etc. may also be used.
   * The acquirer, gateway, or PSP will then transmit this information to the card issuer, confirming a successful 3DS authentication.

#### Using 3DS with VGS

1. **Supported Transaction Type for 3DS:** For 3DS authentication, we currently support **only the Goods/Service Purchase** transaction type.
2. VGS does not provide a 3DS mobile SDK currently.
3. **Account Setup & Prerequisites:** Before you can use the 3DS APIs, your account must be configured.
   * **Enable 3DS on Your Account:** 3DS must be explicitly enabled for your VGS account. Please contact  <support@vgs.io> or your designated VGS implementation representative to have this feature activated.
     * To enable 3DS, provide the CMP account ID for the environment you want to enable, along with the merchant name, URL, and country.
   * **To configure 3DS on your account, please reach out to your VGS representative.**
   * **Configure Service Account:** Once 3DS is enabled, configure your Service Account with the necessary permissions, including the `3ds:read` and `3ds:write` scope (in addition to `cards:read` and `cards:write`).
4. **Merchant Information:**&#x20;
   * **Overview**
     * To perform 3D Secure (3DS) authentication through VGS, you must supply specific `merchant_info` values in the API request that identify the merchant to the card networks. This information is provided during acquirer onboarding and ensures that authentication requests are correctly recognized by issuers and aligned with your specific transaction processing setup.
     * **The core requirement is to maintain precise alignment across the transaction lifecycle.** The `merchant_info` values provided in the 3DS authentication request must match exactly with the acquirer and network identifiers you will use for the subsequent authorization of that transaction.
     * **For example,** if you generate a 3DS authentication cryptogram (CAVV) using a specific `acquirer_bin` and `acquirer_merchant_id`, the **CAVV created will work only with that specific acquirer.** Therefore, you must submit that resulting cryptogram for authorization through that exact same acquiring entity. Mismatched identifiers between the 3DS authentication step and the final authorization step for transaction processing can lead to declined transactions or liability disputes.
   * **Multi-Acquirer Merchants**
     * Merchants often choose to process their transactions through different acquirers based on factors like card network, region, or currency to optimize costs and approval rates. Consequently, critical identifiers like `acquirer_bin` and `acquirer_merchant_id` (MID) can vary per transaction.
     * Because these values can change at a transaction level, your system must dynamically populate the **`merchant_info`** blob in the 3DS request to specify exactly which acquirer identifiers will be used for the final authorization. Ensure your system selects the correct information based on:
       * The merchant account
       * The acquirer designated for transaction processing
       * The card network being authenticated
       * This ensures that each authentication request matches the values used later during the authorization.
   * **What You Need to Collect from Your Acquirer**
     * Each merchant must provide the following values for every card network they process. These fields map directly to the **`merchant_info`** object in the VGS 3DS Authenticate API. These values are required because issuers validate the merchant identity as part of 3DS processing. Using incorrect values can lead to authentication failures.

<table><thead><tr><th width="230.7109375">VGS Field Name</th><th>Description</th></tr></thead><tbody><tr><td><code>acquirer_bin</code></td><td>The network-assigned identifier for the acquirer. Acquirer BIN should be used consistently for both authentication and authorization flows.</td></tr><tr><td><code>acquirer_merchant_id</code></td><td>Unique merchant identifier (MID) registered with the acquirer for that network.</td></tr><tr><td><code>acquirer_country_code</code></td><td>Acquirer’s registered country (ISO 3166 alpha-3 format, e.g., "USA").</td></tr><tr><td><code>category_code</code></td><td>Merchant Category Code (MCC). Four-digit business category classification.</td></tr><tr><td><code>name</code></td><td>Merchant's official business name as registered with the acquirer.</td></tr><tr><td><code>country_code</code></td><td>Merchant's registered country (ISO 3166 alpha-3 format).</td></tr><tr><td><code>website_url</code></td><td>Merchant's official website URL.</td></tr></tbody></table>

* Some **networks** require extra data fields within the **`merchant_info`** object.

| Card Network                   | Field Name                | Requirement |
| ------------------------------ | ------------------------- | ----------- |
| American Express & Discover    | `acquirer_requestor_id`   | Required    |
|                                | `acquirer_requestor_name` | Required    |
| Visa & Mastercard (Production) | `acquirer_requestor_id`   | Optional    |
|                                | `acquirer_requestor_name` | Optional    |

#### Requestor Identifier Guidance per Network

* **For Visa and Mastercard**, `acquirer_requestor_id` and `acquirer_requestor_name` are optional fields. These fields do not need to be sent in the authentication request. However, if you choose to send them, VGS supports the following format:
  * `acquirer_requestor_id = ENT_VGS_<VGS_Account_ID>`
  * `acquirer_requestor_name = VGS_<MerchantName>`&#x20;
  * Please reach out to your VGS representative to obtain your CMP account ID.
* **For American Express and Discover**, `acquirer_requestor_id` and `acquirer_requestor_name` are required fields.
  * **For American Express**, `acquirer_requestor_id` and `acquirer_requestor_name` must be the scheme- or registration-specific requestor identifier associated with the merchant or entity for 3DS processing. This value depends on how the entity is registered for 3DS, such as merchant, aggregator, or another supported registration model. This value should not be generated arbitrarily. `acquirer_requestor_name` should follow the format:

    `acquirer_requestor_name = VGS_<MerchantName>`&#x20;
  * **For Discover**, `acquirer_requestor_id` and `acquirer_requestor_name` must be the registered requestor identifier associated with the merchant or entity under the acquirer for Discover 3DS processing. This value is received or coordinated during onboarding or registration and should not be generated arbitrarily. `acquirer_requestor_name` should follow the format:

    `acquirer_requestor_name = VGS_<MerchantName>`
* These values may also be referred to by the **card networks or 3DS providers** as `threeDSRequestorID` and `threeDSRequestorName`.

#### Testing in sandbox: Once your account is enabled for 3DS:

* Generate a service account with `cards:read, cards:write, and 3ds:write scopes`
* Generate a JWT auth token from that service account
* Use the token to first create a card in CMP
* Then use the generated cardID to invoke the VGS 3DS Initialize and Authenticate APIs
* The Sandbox uses a simplified, network-agnostic configuration for testing. All fields within **`merchant_info`** are required. Fixed, static values are provided for testing and must be used for all Sandbox transactions.

{% hint style="info" %}
Use [this link](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/3ds) to start your integration and testing. Please contact  <support@vgs.io> or your designated VGS implementation representative to begin the onboarding process and have this feature activated.
{% endhint %}

#### **Go-Live:**

1. Before going live with a new processor or acquirer, perform the following control testing for each card scheme:
2. **Verify your Account for 3DS:** Contact your acquirer or Payment Service Provider to ensure that authorization processing is activated for your account to pass the 3DS data through. This ensures smooth 3DS processing and avoids transaction mismatches.
3. **3DS Flow Test:** Run at least one successful challenge and frictionless flow tests per scheme (Visa, Mastercard, etc.). Each scheme must be tested separately.&#x20;
   1. VGS does not provide production test cards for 3DS validation. Any 3DS validation in production must be performed using real cards in live transactions. Before rolling out new `acquirer_requestor_id` or `acquirer_requestor_name` values broadly in production, validate the configuration with a production transaction.
4. **End-to-End Verification:** Conduct a full end-to-end authorization test to verify all components are working as expected before releasing full transaction volume.


# 3DS Data Sharing

### 3DS Data Sharing&#x20;

Data sharing is an optimized 3D Secure authentication flow that can determine a successful or failed outcome **without requiring the cardholder to complete an interactive challenge**. It consists of two distinct phases:

1. **Initialization** for device fingerprinting.
2. **Data-only Request** submitted via the Authentication endpoint.
3. **3DS Status Check Request** for real-time status of a 3DS authentication and device fingerprinting process.

**Assumption:** Customers card is already created with CMP and a `card_id` has been generated.

3DS Data Sharing (data-only authentication) is currently supported for **Visa and Mastercard** transactions.

For detailed API definitions and parameters, see the [3DS API Spec](/cmp/developer-resources/api/3d-secure-3ds).

### Initialize (Device Fingerprinting)

This is executed primarily on the Merchant Frontend to silently collect device-specific information from the cardholder’s browser. This process must be initiated when the checkout page first loads.

1. **Call the VGS Initialize Endpoint:**
   * **Action:** The Merchant Frontend sends a **POST** request to the VGS method endpoint (`/cards/{card_id}/3ds-initialize`).
   * **Data Required:** Include key identifiers such as `card_id, merchant_tx_id, and token_type.`
   * [Initialize API Spec](/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-initialize).
2. **Embed the Hidden Iframe:**
   * **Action:** Upon receiving the response, which contains the tDSMethodContent (an iframe payload), the **Merchant Frontend** must immediately **embed this content into a hidden iframe** on the page.
   * **Purpose:** This iframe executes the necessary script for silent device fingerprinting and must remain active for up to 10 seconds.
3. **Collect Browser Data:**
   * **Action:** Concurrently, the **Merchant Frontend** must collect standard, non-fingerprint browser details, such as the **user agent** and the user's **IP** address. This data will be required for the subsequent Authentication request.

<figure><img src="/files/qKHKxJqk1gH63ipykIVQ" alt=""><figcaption></figcaption></figure>

### Authentication (Data Sharing Request)

This is triggered when the cardholder confirms the payment, typically involving the Merchant Frontend passing data to the Merchant Backend for the final API call.

1. **Trigger Authentication:**
   * **Action:** When the user clicks the "Pay" button, the **Merchant Frontend** collects and transmits all necessary data (card data, purchase info, and the browser data from Phase 1, Step 3) to the **Merchant Backend.**
2. **Call VGS Authenticate:**
   * **Action:** The Merchant Backend sends the core transaction request to the VGS `/cards/{card_id}/3ds-authenticate endpoint.`
   * **Data Required:** Include all collected data, transaction details (`purchase_info`), and crucially, set the authentication type to `auth_type: "data-only"`.
   * [Frictionless API Spec](/cmp/developer-resources/api/3d-secure-3ds).
3. **Receive and Process Final Result:**
   * **Action:** The **Merchant Backend** receives the synchronous **Final Auth Result** from VGS.
   * **Key Data Received:** Since this is a data-only flow, the response is immediate. It contains the crucial authentication `status`, the cryptographic value (`cryptogram`), and `transaction_info`.
4. **Authorize Payment (Proceed with Transaction):**
   * **Action:** The **Merchant Backend** uses the received `status` to make the final risk decision. If the authentication was successful (frictionless flow achieved), the backend must immediately use the provided `cryptogram` to submit the final payment authorization request to the payment processor.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}

<figure><img src="/files/YXLlJIUNpj1LxsY3qwwu" alt=""><figcaption></figcaption></figure>

### **3DS Status Check**

The VGS 3DS Status Check endpoint allows merchants to retrieve the **real-time status** of a transaction’s 3DS authentication and device fingerprinting flow. It provides **immediate visibility** into the authentication process and can be used as a **synchronous alternative to webhooks**.

* **Endpoint to Check Initialize Device Fingerprint Status:** **`GET`** `/cards/{card_id}/3ds-check?`**`inti_received={true}`**`&xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **Endpoint to Check Authentication Status:** **`GET`** `/cards/{card_id}/3ds-check?xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **3DS Flow & Real-Time Status Retrieval**
  * **3DS Flow Overview** – During a 3DS transaction, the customer may go through device fingerprinting or a challenge questionnaire as part of the authentication process.
  * **Client Polling for Status** – While the transaction is in progress, the client polls the `/3ds-check` endpoint with the following parameters:
    * `cardID`
    * `xid`
    * `merchant_transaction_id`
    * `inti_received` (<kbd>conditional</kbd>)
  * **Behavior based on `inti_received`**:
    * **`inti_received=true`** – Returns device fingerprinting initialization status. Call this after the iframe from the synchronous initialize response is rendered and the form containing the iframe is submitted on the front end. This allows the issuer to collect the device fingerprinting.
    * **`inti_received=false` or omitted** – Returns authentication status after the challenge questionnaire/html is submitted by the user.
  * **Status Retrieval** – VGS responds with the most up-to-date status, enabling the merchant to take immediate next steps:

    * Proceed to authorization
    * Update internal transaction state

    #### Using 3ds-check for completed challenges

    * Once the user completes the challenge, they are redirected to the configured `redirect_url`. At that point, calling `3ds-check` is the fastest and most reliable way to retrieve the final authentication result.
    * **This is the recommended approach for successfully completed challenges.**

    #### Handling abandoned challenges

    * Challenge flows involve human interaction, such as entering an OTP or approving a push notification. Because of this, issuers typically keep the challenge session open for **10 to 15 minutes** to allow the user time to complete it.
    * If the user closes the challenge window or abandons the transaction, the issuer may not send a final timeout or failure result until the issuer-side session expires. Because of this, polling `3ds-check` after only a few seconds of inactivity is not recommended, since the response will often remain `404` until a final result is available.
    * **Recommended approach:**
      * Use `redirect_url` or the webhook as the primary completion signal.
      * If you are rendering the returned challenge HTML in your own frontend container, implement a frontend listener to detect whether the user manually closes the challenge modal or iframe. If they do, you can immediately treat the transaction as canceled on your end without waiting for the checkout timeout or issuer-side timeout.
      * Keep your own checkout timeout based on your UX needs. For example, if your current timeout is **5 minutes**, it is fine to keep that as-is. It does not need to match the issuer’s **10 to 15 minute** timeout.
      * If your checkout session expires before you receive the redirect or webhook, make one final call to `3ds-check`.
      * If the response is still `404`, you can safely treat the transaction as expired on your end, cancel the order, and release the cart or inventory.
      * If a delayed webhook arrives later after the issuer timeout expires, it can be ignored if the order has already been canceled or expired in your system.
      * For Out-of-Band (OOB) authentication flows, the cardholder may complete authentication in their banking application and never return to the browser. In these scenarios, the final authentication result will become available through both the webhook and the `3ds-check` endpoint once VGS receives the result from the issuer. If your checkout session remains active, you may continue waiting for the webhook. If your checkout expires before receiving the webhook, make a final call to `3ds-check` before treating the transaction as expired.

    #### Best practice

    * Use `3ds-check` after redirect for completed challenges, use webhooks as a secondary signal, and rely on your own checkout timeout to handle abandoned sessions.

    #### Additional note

    * When you see significantly later completion signals, those cases are typically due to the user abandoning the challenge, closing the challenge window, or taking longer to complete the issuer challenge. This is why implementing `3ds-check` is the recommended approach for handling these scenarios reliably.

#### Non-Payment Authentication (NPA) and Card-Add Flows

VGS 3DS currently supports standard Payment Authentication (PA) flows only. EMV 3DS 2.2 defines Non-Payment Authentication (NPA / `messageCategory: 02`) specifically for card-add and card-on-file enrollment use cases, but VGS does not currently expose NPA-specific indicators. NPA support is on the roadmap.

In the meantime, if you need to perform card verification or card-on-file enrollment that satisfies PSD2 SCA requirements, you can use the VGS PA flow as follows:

* Initiate the `/3ds-authenticate` call by passing a nominal verification amount in the `purchase_info` object — for example, `amount: 0` or `amount: 1.00` with the corresponding currency code (for example, `978` for EUR).
* The issuer will treat this as a standard payment authentication and may step up the user if additional verification is required. VGS will return a CAVV and ECI, which can then be passed into the verification authorization request sent to your PSP or acquirer.
* Because this runs through the standard PA flow, it uses standard Risk-Based Authentication (RBA). You will not be able to explicitly pass NPA-specific indicators such as "Add Card" or "Mandate Challenge." However, the resulting CAVV and ECI can be used as Strong Customer Authentication (SCA) evidence during card verification and card-on-file enrollment flows.
* Although the request is processed as a Payment Authentication rather than an NPA transaction, the returned authentication data can be used to satisfy PSD2 SCA requirements for card verification and card-on-file enrollment use cases.

**Note:** The CAVV generated during a PA flow is tied to that specific authentication event. If the customer later returns to make a new active purchase (CIT), a separate payment authentication should be performed for that transaction.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}


# 3DS Authentication

## 3DS Challenge Flow

Outlines the mandatory integration steps the Merchant (Frontend and Backend) must perform to execute a 3DS Authentication flow. The process is divided into two distinct phases:

* **Initialize** (device data collection).
* **Authentication** (final transaction submission).
* **3DS Status Check Request** for real-time status of a 3DS authentication and device fingerprinting process.

**Assumption:** Customers card is already created with CMP and a `card_id` has been generated.

For detailed API definitions and parameters, see the [3DS API Spec](/cmp/developer-resources/api/3d-secure-3ds).

### Initialize (Device Fingerprinting)

This is executed primarily on the Merchant Frontend to silently collect device-specific information from the cardholder’s browser. This process must be initiated when the checkout page first loads.

1. **Call the VGS Initialize Endpoint:**
   * **Action:** The Merchant Frontend sends a **POST** request to the VGS method endpoint (`/cards/{card_id}/3ds-initialize`).
   * **Data Required:** Include key identifiers such as `card_id, merchant_tx_id, and token_type.`
   * [Initialize API Spec](/cmp/developer-resources/api/3d-secure-3ds#post-cards-card_id-3ds-initialize).
2. **Embed the Hidden Iframe:**
   * **Action:** Upon receiving the response, which contains the tDSMethodContent (an iframe payload), the **Merchant Frontend** must immediately **embed this content into a hidden iframe** on the page.
   * **Purpose:** This iframe executes the necessary script for silent device fingerprinting and must remain active for up to 10 seconds.
3. **Collect Browser Data:**

   * **Action:** Concurrently, the **Merchant Frontend** must collect standard, non-fingerprint browser details, such as the **user agent** and the user's **IP** address. This data will be required for the subsequent Authentication request.

   <figure><img src="/files/x10afikQtVG8gcwDrupq" alt=""><figcaption></figcaption></figure>

### Authentication - Challenge Flow

This is triggered by the cardholder confirming the payment. Unlike the frictionless flow, the challenge flow introduces a mandatory user interaction step that must be handled by the Merchant Frontend.

1. **Trigger Authentication:**
   * **Action:** When the user clicks the "Pay" button, the **Merchant Frontend** collects and transmits all necessary data (card data, purchase info, and the browser data from Phase 1, Step 3) to the **Merchant Backend.**
2. **Call VGS Authenticate:**
   * **Action:** The **Merchant Backend** sends the core transaction request to the VGS `/cards/{card_id}/3ds-authenticate endpoint`.
   * **Data Required:** Include all collected data, transaction details (`purchase_info`), and set the type parameter to `challenge`.
   * [Challenge API Spec](/cmp/developer-resources/api/3d-secure-3ds#threeds-challenge).
3. **Receive Challenge HTML:**
   * **Action:** Instead of a final `status`, the Merchant Backend will receive an **Intermediate Response** (`status 'CHALLENGE_REQUIRED' or REJECTED`) containing the **Challenge HTML** (challengeHtml) and transaction IDs.
   * **Backend Responsibility:** The **Merchant Backend** must relay this Challenge HTML directly to the **Merchant Frontend**.
4. **Display the Challenge Window:**
   * **Action:** The **Merchant Frontend** must open a modal, pop-up, or dedicated iframe to display the received **Challenge HTML** to the cardholder.
   * **User Interaction:** The cardholder interacts directly with the **Issuer ACS** interface inside this challenge window (e.g., entering an OTP or password).
   * **Important - Rendering the Challenge HTML:**&#x20;
     * The `challengeHtml` returned by the VGS Authenticate API contains a redirect form generated by the issuer’s Access Control Server (ACS) and delivered through the 3DS server. This HTML initiates the cardholder challenge and must be rendered exactly as returned inside a browser context such as a modal, popup, or iframe.
     * The ACS redirect page may behave differently depending on the issuer implementation. Two common behaviors are possible:
       * The page displays a submit button that the cardholder must click to proceed to the issuer’s challenge screen.
       * The page automatically submits the form using JavaScript, immediately redirecting the browser to the issuer challenge without requiring any user interaction. In the auto-submit case, the “click here to continue” button only appears if JavaScript is blocked.
     * Both behaviors are valid and controlled entirely by the issuing bank. Your integration should not rely on the presence of a visible button or any specific UI elements within the challenge page.
     * **Implementation requirements:** When rendering the challenge HTML:
       * Treat the returned `challengeHtml` as opaque content and render it exactly as provided. Do not modify the form, scripts, or URLs contained within it.
       * Render the HTML inside a browser-capable environment (for example, an iframe, modal, popup window, or webview) that allows JavaScript execution and form redirects.
       * Allow the browser to follow any redirects initiated by the page.
       * After the form is submitted (either manually or automatically), the browser is redirected to the issuer’s ACS where the authentication may take place. Depending on the issuer’s risk decision, the cardholder may be presented with a challenge (for example OTP, banking app approval, or biometric verification), or the issuer may immediately return a final authentication result.
       * In some cases, the challenge UI may not appear even after the redirect. This can occur if the issuer makes a risk decision early in the authentication flow, or if there is a temporary technical issue with the ACS or a downstream service.
       * The final authentication result is determined by the issuer and delivered asynchronously. Once the authentication process is completed, abandoned, or times out, you will receive the final status via the VGS `cmp_threeds.challenge_result` webhook. Alternatively, you may retrieve the current status using the `/3ds-check` endpoint.
5. **Handle Challenge Completion (Client-Side Listener):**
   * **Action:** Once the user completes the challenge, the **Issuer ACS** redirects the browser within the frame to a VGS success/failure endpoint, which then passes the result to the Merchant’s pre-configured endpoint. The Merchant Frontend must have a listener or mechanism to detect when the challenge window closes or redirects.
6. **Receive Final Result (Asynchronous or Synchronous):**
   * **Action:** The **Merchant Backend** will receive an **asynchronous webhook** with the final success/failure `status` of the challenge, or if the challenge was abandoned/timed out, a final synchronous result may be returned. The backend must be configured to accept and process this final result.
   * **Key Data Received:** The final response contains the authentication `status` (e.g., `'APPROVED', 'UNABLE_TO_AUTHENTICATE'`), the cryptographic value (`cryptogram`), and `transaction_info`.
7. **Authorize Payment:**
   1. **Action:** The Merchant Backend uses the received final `status` to determine the final risk decision. If the challenge was successful (status `APPROVED` or equivalent), the backend must use the provided `cryptogram` to submit the final payment authorization request to the payment processor.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}

<figure><img src="/files/U8KOs2zcAiwvybQMizTr" alt=""><figcaption></figcaption></figure>

### **3DS Status Check**

The VGS 3DS Status Check endpoint allows merchants to retrieve the **real-time status** of a transaction’s 3DS authentication and device fingerprinting flow. It provides **immediate visibility** into the authentication process and can be used as a **synchronous alternative to webhooks**.

* **Endpoint to Check Initialize Device Fingerprint Status:** **`GET`** `/cards/{card_id}/3ds-check?`**`inti_received={true}`**`&xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **Endpoint to Check Authentication Status:** **`GET`** `/cards/{card_id}/3ds-check?xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **3DS Flow & Real-Time Status Retrieval**

  * **3DS Flow Overview** – During a 3DS transaction, the customer may go through device fingerprinting or a challenge questionnaire as part of the authentication process.
  * **Client Polling for Status** – While the transaction is in progress, the client polls the `/3ds-check` endpoint with the following parameters:
    * `cardID`
    * `xid`
    * `merchant_transaction_id`
    * `inti_received` (<kbd>conditional</kbd>)
  * **Behavior based on `inti_received`**:
    * **`inti_received=true`** – Returns device fingerprinting initialization status. Call this after the iframe from the synchronous initialize response is rendered and the form containing the iframe is submitted on the front end. This allows the issuer to collect the device fingerprinting.
    * **`inti_received=false` or omitted** – Returns authentication status after the challenge questionnaire/html is submitted by the user.
  * **Status Retrieval** – VGS responds with the most up-to-date status, enabling the merchant to take immediate next steps:
    * Proceed to authorization
    * Update internal transaction state

  #### Using 3ds-check for completed challenges

  * Once the user completes the challenge, they are redirected to the configured `redirect_url`. At that point, calling `3ds-check` is the fastest and most reliable way to retrieve the final authentication result.
  * **This is the recommended approach for successfully completed challenges.**

  #### Handling abandoned challenges

  * Challenge flows involve human interaction, such as entering an OTP or approving a push notification. Because of this, issuers typically keep the challenge session open for **10 to 15 minutes** to allow the user time to complete it.
  * If the user closes the challenge window or abandons the transaction, the issuer may not send a final timeout or failure result until the issuer-side session expires. Because of this, polling `3ds-check` after only a few seconds of inactivity is not recommended, since the response will often remain `404` until a final result is available.
  * **Recommended approach:**
    * Use `redirect_url` or the webhook as the primary completion signal.
    * If you are rendering the returned challenge HTML in your own frontend container, implement a frontend listener to detect whether the user manually closes the challenge modal or iframe. If they do, you can immediately treat the transaction as canceled on your end without waiting for the checkout timeout or issuer-side timeout.
    * Keep your own checkout timeout based on your UX needs. For example, if your current timeout is **5 minutes**, it is fine to keep that as-is. It does not need to match the issuer’s **10 to 15 minute** timeout.
    * If your checkout session expires before you receive the redirect or webhook, make one final call to `3ds-check`.
    * If the response is still `404`, you can safely treat the transaction as expired on your end, cancel the order, and release the cart or inventory.
    * If a delayed webhook arrives later after the issuer timeout expires, it can be ignored if the order has already been canceled or expired in your system.
    * For Out-of-Band (OOB) authentication flows, the cardholder may complete authentication in their banking application and never return to the browser. In these scenarios, the final authentication result will become available through both the webhook and the `3ds-check` endpoint once VGS receives the result from the issuer. If your checkout session remains active, you may continue waiting for the webhook. If your checkout expires before receiving the webhook, make a final call to `3ds-check` before treating the transaction as expired.

  #### Best practice

  * Use `3ds-check` after redirect for completed challenges, use webhooks as a secondary signal, and rely on your own checkout timeout to handle abandoned sessions.

  #### Additional note

  * When you see significantly later completion signals, those cases are typically due to the user abandoning the challenge, closing the challenge window, or taking longer to complete the issuer challenge. This is why implementing `3ds-check` is the recommended approach for handling these scenarios reliably.

#### Non-Payment Authentication (NPA) and Card-Add Flows

VGS 3DS currently supports standard Payment Authentication (PA) flows only. EMV 3DS 2.2 defines Non-Payment Authentication (NPA / `messageCategory: 02`) specifically for card-add and card-on-file enrollment use cases, but VGS does not currently expose NPA-specific indicators. NPA support is on the roadmap.

In the meantime, if you need to perform card verification or card-on-file enrollment that satisfies PSD2 SCA requirements, you can use the VGS PA flow as follows:

* Initiate the `/3ds-authenticate` call by passing a nominal verification amount in the `purchase_info` object — for example, `amount: 0` or `amount: 1.00` with the corresponding currency code (for example, `978` for EUR).
* The issuer will treat this as a standard payment authentication and may step up the user if additional verification is required. VGS will return a CAVV and ECI, which can then be passed into the verification authorization request sent to your PSP or acquirer.
* Because this runs through the standard PA flow, it uses standard Risk-Based Authentication (RBA). You will not be able to explicitly pass NPA-specific indicators such as "Add Card" or "Mandate Challenge." However, the resulting CAVV and ECI can be used as Strong Customer Authentication (SCA) evidence during card verification and card-on-file enrollment flows.
* Although the request is processed as a Payment Authentication rather than an NPA transaction, the returned authentication data can be used to satisfy PSD2 SCA requirements for card verification and card-on-file enrollment use cases.

**Note:** The CAVV generated during a PA flow is tied to that specific authentication event. If the customer later returns to make a new active purchase (CIT), a separate payment authentication should be performed for that transaction.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}


# Account Validation

### Overview&#x20;

The VGS Account Validation API allows merchants to determine if a particular cardholder’s account is valid and in good standing. The API currently provides four methods of account validation: Card Verification, Address Verification Service (AVS), Card Verification Code (CVC) Verification, and Account Name Inquiry (ANI). The ability to pre-validate an account increases the probability of a successful, seamless transaction flow.

Global coverage varies by issuer participation. &#x20;

### Benefits of Account Validation

Account Validation is a critical security and operational process that verifies a cardholder's account is legitimate and valid before a transaction is processed. Merchants leverage this service to prevent fraud, improve operational efficiency, and enhance the overall user experience.&#x20;

**1. Risk Mitigation & Fraud Prevention**

* Identity Assurance: By verifying that cardholder data aligns with the records on file, this service creates a robust barrier against the use of stolen credentials.
* Reduced Chargebacks: By validating accounts upfront, merchants proactively mitigate 'unauthorized transaction' claims. This leads to a significant reduction in costly chargeback fees and protects the business from associated merchant penalties.
* Pre-emptive Screening: It serves as a critical gatekeeper, intercepting fraudulent or invalid cards before they enter merchant's ecosystem or occupy space in their secure vault.

**2. Improved Operational Efficiency**

* Higher Authorization Rates: High-quality data minimizes declines. By submitting validated information, merchants provide issuing banks with greater transaction confidence, which directly translates to higher authorization and approval rates.
* Lower Administrative Costs: Manual resolution of payment failures is both costly and labor-intensive. By automating the validation process, merchants minimize the need for customer support intervention and streamline dunning cycles, allowing the team to focus on high-value tasks.
* Elimination of "Orphaned" Data: Validating cards prior to storage ensures your database contains only actionable, verified payment methods. This proactive approach maintains high data hygiene and optimizes the efficiency of your secure vault.

**3. Enhanced User Experience**

* Immediate Feedback: Real-time validation enables immediate feedback during onboarding and card linkage. By alerting customers to correct card details instantly, merchants prevent the frustration of delayed transaction failures and ensure a seamless experience.
* Reduced Friction: For recurring services (like subscriptions), successful validation ensures the first "real" billing cycle happens smoothly, preventing service interruptions for the customer.

### Methods of Account Validation

Generally, the `card ID`  is a required field in the request, which includes the Payment Account Number (PAN). The presence of other fields determines which checks are performed. See more in the [Account Validation Spec](https://docs.verygoodsecurity.com/cmp/developer-resources/api/account-validation).

1. **Card Verification:** This service verifies the account authenticity and integrity before authorization. It ensures the account is a legitimate, issued account with a valid check digit, and critically, confirms that it is an open account and not currently flagged as lost or stolen. This provides an essential foundation for fraud mitigation. **Performed by default.**
2. **CVC Verification:** The 3-4 digit Card Verification Code (CVC) is required if `CVC` validation is to be performed. This service is used to determine if the issuer of the account recognizes the `CVC` value given by the user. This will help verify that the cardholder has the physical card in their possession.
3. **Address Verification Service (AVS):** The service validates the provided billing address against the address on file with the card issuer. The resulting Address Verification Service (AVS) status provides critical data for assessing transaction authenticity.\
   `Postal code` is mandatory for all address validations. While a `postal code` can be validated as a standalone field, full address cannot be verified without `postal code`.
4. **Account Name Inquiry (ANI):** Enhances your card-not-present fraud mitigation with Real-Time Name Match. This service allows you to verify the account name information against participating Issuers before sending a full financial request, providing a robust, layered approach to account verification and risk management.&#x20;

   Name verification requires at least a `Last Name`. While a `Last Name` can be validated independently, a `First Name` must be accompanied by a `Last Name` to be verified.

### How it works with VGS

* The Account Validation (AV) service utilizes direct network connectivity to cross-reference merchant-supplied cardholder data against issuing bank records in real time upon each request.
* The Account Validation (AV) service is accessible through the VGS CMP. As a prerequisite, users must generate a `Card ID` via the card creation endpoint. This `Card ID` is then used to trigger the Account Validation endpoint.&#x20;
* The Account Validation API offers a modular approach, allowing merchants to access the full suite of services or specify individual features.&#x20;
* By default, the API performs standard Card Verification. If a cardholder’s name, billing address, or CVC are included in the request, they will be validated accordingly.&#x20;
  * Validation is performed on data explicitly provided in the API call; previously stored card object attributes are not utilized for these checks.&#x20;
  * Card IDs associated with expired PANs are considered ineligible for validation.
* See the Validation Response Codes reference [here](/cmp/products-and-services/account-validation/validation-response-codes).

<figure><img src="/files/kdMGwbKi7gZxmDd3EbDF" alt=""><figcaption></figcaption></figure>

### Onboarding

1. **Account Setup & Prerequisites:** Before merchants can use the Account Validation (AV), their account must be configured.
   1. **Enable Account Validation on Your Account:** Account Validation must be explicitly enabled for your VGS account. Please contact <support@vgs.io> or merchant-designated VGS implementation representative to have this feature activated.
   2. **Configure Service Account:** Once Account Validation is enabled, merchants should configure their Service Account with the necessary permissions, including the `account-validations:write`  and `account-validations:read` scopes (in addition to `cards:read` and `cards:write`).
2. Merchants are **required** to provide the following information during every request:
   1. Merchant Name&#x20;
   2. Merchant Address
      1. `city`
      2. `state`
      3. `country`
      4. `zip Code`&#x20;

### Supported Networks

<table><thead><tr><th width="217.7628173828125">Feature</th><th width="113.37652587890625">Visa</th><th width="122.5872802734375">Mastercard</th><th width="93.52398681640625">Amex</th><th width="114.5029296875">Discover</th></tr></thead><tbody><tr><td><code>Card Verification</code></td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><code>Address Verification Service (AVS)</code></td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><code>CVC Verification</code></td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td><code>Account Name Inquiry (ANI)</code></td><td>Yes</td><td>Yes</td><td>No</td><td>No</td></tr></tbody></table>

### Limitations

* Only Visa cards are currently supported for sandbox testing. Other card networks (Mastercard, Amex, and Discover) are not available in the sandbox environment.
* Sandbox testing coverage is limited. Some scenarios, including the CVC use case, are not yet supported in this environment. We are actively working with the network to make these available.


# Validation Response Codes

1. **Card Verification**: This service verifies the account authenticity and integrity before authorization. <br>

   <table><thead><tr><th width="195.14556884765625">Response</th><th>Description</th></tr></thead><tbody><tr><td><code>verified</code></td><td>Card was successfully verified. </td></tr><tr><td><code>not_verified</code></td><td>Card verification failed due to a number of reasons including:<br>- Lost card<br>- Stolen card<br>- Closed account</td></tr></tbody></table>

2. **Address Verification Service (AVS):** The service validates the provided billing address against the address on file with the card issuer. <br>

   <table><thead><tr><th width="196.54827880859375">Response</th><th>Description</th></tr></thead><tbody><tr><td><code>match</code></td><td>Address provided by card holder fully matches address on file with the card issuer.</td></tr><tr><td><code>no_match</code></td><td>Address provided by card holder does not match address on file with the card issuer.</td></tr><tr><td><code>partial_match</code></td><td><p>Address provided by card holder partially matches address on file with the card issuer for the following reasons:</p><p></p><ul><li>Partially match. Street address provided matches, but 5-digit postal code does not.</li><li>Partially match. 5-digit postal code matches, but street address does not.</li></ul></td></tr><tr><td><code>not_supported</code></td><td><ul><li>Address verification is not supported. </li><li>Address provided by card holder could not be verified against address on file with the card issuer.</li></ul></td></tr></tbody></table>

3. **CVC Verification :** This service facilitates the CVC validation status check with the card issuer.<br>

   <table><thead><tr><th width="204.33941650390625">Response</th><th>Description</th></tr></thead><tbody><tr><td><code>match</code></td><td>CVC provided by card holder passes verification.</td></tr><tr><td><code>no_match</code></td><td>CVC provided by card holder failed verification.</td></tr><tr><td><code>system_unavailable</code></td><td>Issuer's system is unavailable.</td></tr><tr><td><code>invalid_data</code></td><td>Malformed CVC value or unexpected characters.</td></tr><tr><td><code>non_participating</code></td><td>Issuer does not participate in CVC verification.</td></tr></tbody></table>

4. **Account Name Inquiry (ANI):** Enhances your card-not-present fraud mitigation with Real-Time Name Match. <br>

   <table><thead><tr><th width="203.84942626953125">Response</th><th>Description</th></tr></thead><tbody><tr><td><code>match</code></td><td>Name provided by card holder fully matches name on file with the card issuer.</td></tr><tr><td><code>no_match</code></td><td>Name provided by card holder does not match name on file with the card issuer.</td></tr><tr><td><code>partial_match</code></td><td>Name provided by card holder partially matches name on file with the card issuer. </td></tr><tr><td><code>not_performed</code></td><td>Name verification was not performed by the issuer or issuer is not participating in Name verification.</td></tr></tbody></table>


# Token Sync (beta)

## Overview <a href="#overview" id="overview"></a>

Token Sync is a VGS capability that allows merchants to create and manage PSP tokens from a single VGS card object. Instead of treating each PSP token as a separate integration artifact, merchants can use VGS as the canonical system for card storage, PSP-token provisioning, and token lifecycle management across providers such as Braintree, Adyen, and Stripe.

With Token Sync, a merchant can decide which PSP tokens should be available immediately, which should be created asynchronously in the background, and which should be issued on demand later. This gives merchants a flexible way to support primary payment routing, backup PSP coverage, failover strategies, and future token refresh flows without requiring the browser or merchant backend to recollect sensitive card data for each provider.

#### API Specifications

[Token Sync Draft OpenAPI Specifications](https://openapi.gitbook.com/o/hcowjO8ckQ1K5fm3NPZH/spec/token-sync.yaml)

## PSP Token Issuance Options <a href="#psp-token-issuance-options" id="psp-token-issuance-options"></a>

Merchants can choose between three PSP-token issuance patterns depending on which providers they need immediately and which providers they only need as backup or failover.

### 1. Synchronous issuance on `POST /cards` <a href="#id-1-synchronous-issuance-on-post-cards" id="id-1-synchronous-issuance-on-post-cards"></a>

In the first model, VGS issues one or more PSP tokens during the initial `POST /cards` request and returns them in the response.

This is the best fit when the merchant needs a specific PSP token immediately for the primary payment flow, for example:

* Braintree token required right away for the first authorization
* Adyen token required immediately for the primary region

In this mode, the merchant can treat the synchronously returned PSP token as the primary token it expects to use first.

### 2. Asynchronous Issuance After `POST /cards` <a href="#id-2-asynchronous-issuance-after-post-cards" id="id-2-asynchronous-issuance-after-post-cards"></a>

In the second model, `POST /cards` creates the card object immediately, but one or more PSP tokens are provisioned asynchronously after the card has already been created.

This is the best fit when the merchant wants:

* a fast card-creation response
* backup or failover PSP tokens created in the background
* secondary providers prepared without blocking the checkout or enrollment flow

For example, a merchant may want:

* Braintree returned synchronously as the primary PSP token
* Adyen and Stripe issued asynchronously as backup PSP tokens

In this mode, the merchant can retrieve the updated card later with `GET /cards/{card_id}` or receive a webhook when PSP token state changes.

### 3. Manual Issuance with `POST /cards/{card_id}/psp-tokens` <a href="#id-3-manual-issuance-with-post-cardscard_idpsp-tokens" id="id-3-manual-issuance-with-post-cardscard_idpsp-tokens"></a>

In the third model, the merchant explicitly triggers PSP token creation or refresh by calling `POST /cards/{card_id}/psp-tokens`.

This is the best fit when the merchant wants:

* precise control over when secondary PSP tokens are created
* a delayed provisioning step after user onboarding is complete
* targeted creation or refresh of only a subset of PSPs

For example, a merchant may:

* create the card first
* issue Braintree synchronously
* wait to issue Stripe until the card is actually needed for failover
* refresh Adyen and Stripe later if the card data changes

This endpoint can be used for all configured PSPs by default, or for a selected provider subset when the merchant wants manual control over which PSP tokens are created or refreshed.

### Choosing Primary and Backup PSP Tokens <a href="#choosing-primary-and-backup-psp-tokens" id="choosing-primary-and-backup-psp-tokens"></a>

These three issuance options can be mixed together.

A merchant can decide:

* which PSP tokens must be available immediately
* which PSP tokens should be prepared asynchronously as backup
* which PSP tokens should only be created on demand

Example strategy:

* issue Braintree synchronously on `POST /cards`
* issue Adyen asynchronously after card creation
* issue Stripe manually later through `POST /cards/{card_id}/psp-tokens`

With this approach, merchants can optimize for both:

* low-latency access to the primary PSP token they need right away
* durable backup coverage across secondary PSPs without forcing every provider to block the initial card creation flow

## Token Sync with Account Updater <a href="#token-sync-with-account-updater" id="token-sync-with-account-updater"></a>

Token Sync is not only about issuing PSP tokens when a card is first created. It is also meant to help merchants keep every downstream PSP token up to date over time as the underlying card changes.

VGS Account Updater and Token Sync can be used together as a continuous card-lifecycle model:

* VGS stores the canonical card object
* VGS Account Updater detects changes to the underlying card
* Token Sync uses the updated card state to refresh each configured PSP token
* VGS notifies the merchant whenever PSP token state changes

This combined model helps ensure that merchants do not have to manually track whether a Braintree, Adyen, or Stripe token has become stale after the underlying card changes.

The same propagation behavior should apply regardless of how the card change was introduced. If the canonical VGS card object is updated manually by an API call or operational workflow, Token Sync should still evaluate and propagate the change across all configured PSP tokens in the same way it would for an Account Updater-triggered update.

### How updates should work <a href="#how-updates-should-work" id="how-updates-should-work"></a>

When the canonical VGS card object changes, Token Sync should evaluate every PSP token associated with that card and determine whether each provider supports:

* updating the existing token in place
* issuing a replacement token
* deleting or retiring the token

The specific outcome depends on the provider behavior, but the merchant-facing expectation should stay consistent: VGS keeps the PSP-token layer aligned with the current card state.

### Examples of card changes that should trigger PSP token updates <a href="#examples-of-card-changes-that-should-trigger-psp-token-updates" id="examples-of-card-changes-that-should-trigger-psp-token-updates"></a>

* expiration date changes
* PAN changes
* card account moves to `closed`

#### Expiration date change <a href="#expiration-date-change" id="expiration-date-change"></a>

If the card expiration date changes, VGS should attempt to update each PSP token so that the provider reflects the current expiration month and year.

#### PAN change <a href="#pan-change" id="pan-change"></a>

If the PAN changes, VGS should attempt to update each PSP token. If a PSP does not support updating the existing token in place, VGS should create a new replacement token and mark the prior token as replaced or retired.

#### Card closed <a href="#card-closed" id="card-closed"></a>

If the underlying card account is moved to `closed`, VGS should delete, disable, or retire the related PSP tokens based on provider behavior and policy.

### Webhooks for PSP token lifecycle changes <a href="#webhooks-for-psp-token-lifecycle-changes" id="webhooks-for-psp-token-lifecycle-changes"></a>

VGS should send a webhook every time PSP token state changes as a result of Token Sync.

That webhook may represent:

* an actually updated PSP token
* a newly created replacement token when the PSP does not allow in-place updates
* a deleted or retired token when the card is closed

The merchant should not need to infer whether a provider performed an in-place update or issued a replacement token by comparing raw provider responses. VGS should normalize that into a stable event model.

### Merchant-facing event outcomes <a href="#merchant-facing-event-outcomes" id="merchant-facing-event-outcomes"></a>

The merchant-facing event model should clearly distinguish between:

* `updated`: the PSP token still exists and its linked card data was refreshed
* `replaced`: the prior PSP token could not be updated in place, so a new PSP token was created
* `deleted`: the PSP token was deleted, retired, or otherwise deactivated because the underlying card should no longer be used

### Operational expectation <a href="#operational-expectation" id="operational-expectation"></a>

With Token Sync and Account Updater working together, merchants can rely on VGS to:

* detect when the underlying card changed
* propagate those changes across all configured PSPs
* create replacement PSP tokens when necessary
* delete PSP tokens when a card is no longer valid
* emit webhooks whenever PSP token state changes

This is what allows Token Sync to function as an ongoing card-maintenance capability rather than a one-time token-issuance flow.

## Card Collection with Token Sync Implementation Models <a href="#merchant-token-sync-implementation" id="merchant-token-sync-implementation"></a>

This sample describes a generic merchant browser-led token-sync integration that can be shared across multiple merchants.

The merchant can support two front-end driven patterns:

1. `vgsCollect.createCard()` creates the VGS card object in the browser, then the browser manually submits that card object to the merchant backend.
2. `vgsCollect.submit()` sends card data from Collect through VGS and directly to the merchant backend, with VGS returning a card-object-shaped payload that includes PSP token data.

In both patterns:

* the raw PAN and CVC stay inside VGS Collect fields
* the merchant backend does not need to receive raw card data
* the merchant persists the VGS `card_id` as the canonical card reference
* VGS can include PSP token state when synchronous provisioning completes
* the key difference is whether the PSP token data returns to the browser first or is submitted directly to the merchant backend

### Option A: `vgsCollect.createCard()` returns PSP tokens to the browser <a href="#option-a-vgscollectcreatecard-returns-psp-tokens-to-the-browser" id="option-a-vgscollectcreatecard-returns-psp-tokens-to-the-browser"></a>

```mermaid
sequenceDiagram
    participant C as Cardholder
    participant B as Browser + VGS Collect
    participant V as VGS Cards API
    participant M as Merchant Backend
    participant P as PSP

    C->>B: Enter card details
    B->>V: createCard()
    V-->>B: Return card object with card_id and PSP token state
    B->>M: POST card object or normalized card payload
    M->>P: Submit payment using selected PSP token
    P-->>M: Return payment result
    M-->>B: Persist merchant payment method reference or payment result
```

#### 1. The browser collects card data with VGS Collect <a href="#id-1-the-browser-collects-card-data-with-vgs-collect" id="id-1-the-browser-collects-card-data-with-vgs-collect"></a>

The merchant renders the payment form with VGS Collect hosted fields.

```js
const form = await VGSCollect.session({
  vaultId: '<vault_id>',
  env: 'sandbox',
  formId: 'merchant-card-collect'
});

form.cardNumberField('#card-number');
form.cardholderNameField('#cardholder-name');
form.cardExpirationDateField('#card-expiration');
form.cardCVCField('#card-cvc');
```

#### 2. The browser creates the VGS card object directly <a href="#id-2-the-browser-creates-the-vgs-card-object-directly" id="id-2-the-browser-creates-the-vgs-card-object-directly"></a>

The browser calls `createCard()` and VGS returns the card object response directly to the front end. In this option, the browser is the first place where the card object and PSP token data are available.

```js
form.createCard(
  {},
  async function(status, cardObject) {
    console.log('VGS card object created', status, cardObject);
  },
  function(errors) {
    console.error('createCard failed', errors);
  }
);
```

#### 3. VGS returns the card object to the browser <a href="#id-3-vgs-returns-the-card-object-to-the-browser" id="id-3-vgs-returns-the-card-object-to-the-browser"></a>

The browser receives the canonical VGS card object. That object can already include PSP token state for Braintree, Adyen, and Stripe if provisioning completes inside the synchronous window.

```json
{
  "data": {
    "id": "CRD_merchant_12345",
    "type": "cards",
    "attributes": {
      "pan_alias": "tok_abcdefg",
      "cvc_alias": "tok_vwxyz",
      "token_type": "pan",
      "bin": "424242",
      "first8": "42424242",
      "last4": "4242",
      "exp_month": 12,
      "exp_year": 2028,
      "cardholder_name": "John Doe",
      "network_transaction_id": "0163125478900412"
    },
    "capabilities": [
      "psp-tokens"
    ],
    "included": [
      {
        "type": "psp-tokens",
        "attributes": {
          "braintree": {
            "attributes": {
              "token": "bt_tok_primary_123",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          },
          "adyen": {
            "attributes": {
              "token": "ady_tok_789",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          },
          "stripe": {
            "attributes": {
              "token": "pm_1RtExampleStripe",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          }
        }
      }
    ]
  }
}
```

#### 4. The browser manually posts the card object to the merchant <a href="#id-4-the-browser-manually-posts-the-card-object-to-the-merchant" id="id-4-the-browser-manually-posts-the-card-object-to-the-merchant"></a>

This is the integration point the merchant owns. The browser sends the VGS card object, or a normalized subset of it, to the merchant backend.

The merchant backend stores:

* `card_id`
* customer linkage
* card summary fields like `last4`, `exp_month`, and `exp_year`
* PSP token data for the providers it needs immediately

### Option B: `vgsCollect.submit()` sends the card object directly to the merchant backend through VGS <a href="#option-b-vgscollectsubmit-sends-the-card-object-directly-to-the-merchant-backend-through-vgs" id="option-b-vgscollectsubmit-sends-the-card-object-directly-to-the-merchant-backend-through-vgs"></a>

```mermaid
sequenceDiagram
    participant C as Cardholder
    participant B as Browser + VGS Collect
    participant V as VGS Proxy
    participant M as Merchant Backend
    participant P as PSP

    C->>B: Enter card details
    B->>V: submit()
    Note over B,V: VGS Collect captures raw card data
    V->>V: Create card object and issue PSP tokens
    V->>M: Submit card object directly to merchant backend
    M->>P: Submit payment using selected PSP token
    P-->>M: Return payment result
    M-->>V: Return merchant response
    V-->>B: Return merchant response to browser
```

#### 1. The browser submits through VGS <a href="#id-1-the-browser-submits-through-vgs" id="id-1-the-browser-submits-through-vgs"></a>

In this pattern, the browser uses `submit()` so VGS Collect captures the sensitive fields, VGS creates the card object, provisions PSP tokens, and then submits the resulting card-object payload directly to the merchant backend.

```js
form.submit(
  '/merchant/payment-methods',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    }
  },
  async function(status, response) {
    console.log('Merchant response received', status, response);
  },
  function(errors) {
    console.error('submit failed', errors);
  }
);
```

#### 2. VGS submits the card object directly to the merchant backend <a href="#id-2-vgs-submits-the-card-object-directly-to-the-merchant-backend" id="id-2-vgs-submits-the-card-object-directly-to-the-merchant-backend"></a>

This is the important difference from Option A. The browser does not need to manually forward the VGS card object after it is created. Instead, VGS acts as the proxy boundary:

* Collect captures the card data from the customer
* VGS creates the card object
* VGS issues any synchronous PSP tokens
* VGS submits the resulting card object directly to the merchant backend

#### 3. This is what the merchant back end will receive <a href="#id-3-this-is-what-the-merchant-back-end-will-receive" id="id-3-this-is-what-the-merchant-back-end-will-receive"></a>

The merchant backend receives a card-object-shaped payload that can include the canonical `card_id`, the shared `network_transaction_id`, and any PSP tokens that were issued synchronously.

```json
{
  "data": {
    "id": "CRD12345",
    "type": "cards",
    "attributes": {
      "pan_alias": "tok_abcdefg",
      "cvc_alias": "tok_vwxyz",
      "token_type": "pan",
      "bin": "424242",
      "first8": "42424242",
      "last4": "4242",
      "exp_month": 12,
      "exp_year": 2028,
      "cardholder_name": "John Doe",
      "network_transaction_id": "0163125478900412"
    },
    "capabilities": [
      "psp-tokens"
    ],
    "included": [
      {
        "type": "psp-tokens",
        "attributes": {
          "braintree": {
            "attributes": {
              "token": "bt_tok_primary_123",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          },
          "adyen": {
            "attributes": {
              "token": "ady_tok_789",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          },
          "stripe": {
            "attributes": {
              "token": "pm_1RtExampleStripe",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          }
        }
      }
    ]
  }
}
```

In this option, the merchant backend can persist the card object and PSP token data immediately, without requiring the browser to relay the payload after VGS has created it.

### Option C: VGS Routes create Card Objects and associate PSP Tokens

```mermaid
sequenceDiagram
    participant C as Cardholder
    participant B as Browser + VGS Collect
    participant I as VGS Inbound Route
    participant M as Merchant Backend
    participant O as VGS Outbound Route
    participant P as PSP

    C->>B: Enter card details
    B->>I: submit()
    Note over B,I: VGS Collect captures raw card data
    I->>I: Alias PAN and CVV, create or reference card object
    I->>M: Forward sanitized payload to merchant backend
    M->>O: Send tokenization or payment request
    O->>P: Reveal card data and call PSP
    P-->>O: Return PSP token or payment method id
    O->>O: Associate PSP token to existing card object
    O-->>M: Return PSP response
    M-->>I: Return merchant response
    I-->>B: Return merchant response
```

#### 1. The browser submits through VGS <a href="#id-1-the-browser-submits-through-vgs" id="id-1-the-browser-submits-through-vgs"></a>

This option is designed for merchants that want access to Account Updater, Network Tokens, and Token Syncing with minimal or no changes to the current integration. The customer still enters payment details through VGS Collect and submits them through the existing VGS inbound route.

```js
form.submit(
  '/merchant/payments',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    }
  },
  async function(status, response) {
    console.log('Merchant payment response received', status, response);
  },
  function(errors) {
    console.error('submit failed', errors);
  }
);
```

#### 2. The inbound route aliases the card data and establishes the canonical card object

When the inbound route receives the request, VGS accepts the submitted card data, aliases the PAN and CVV, and forwards the sanitized payload to the merchant backend. In this option, the canonical card object is also established at this stage so Token Sync has a stable VGS record to work with throughout the rest of the flow.

In this model, the inbound route is responsible for:

* capturing the sensitive fields from Collect
* creating or referencing the canonical VGS card object using the PAN and expiration date
* forwarding sanitized data to the merchant backend so the merchant can continue using its current payments architecture

If a matching card object already exists for the same PAN and expiration date, VGS should reference the existing card object instead of creating a duplicate.

#### 3. The merchant continues its normal PSP tokenization or payment flow through the outbound route

After the merchant backend receives the inbound request, it continues its normal payments flow. The merchant sends the aliased card data through the existing VGS outbound route, and VGS reveals the stored values only at the PSP boundary.

This is the path merchants already use to tokenize with PSPs or perform payments, so the main value of this option is that VGS can layer Token Syncing on top of that existing architecture.

#### 4. VGS associates the PSP token during the outbound response phase

This is the important difference from Options A and B. The PSP token does not need to be issued at the moment the card object is first created. Instead:

* the merchant completes the downstream PSP request through the outbound route using the VGS Card ID created in step 2
* the outbound response returns the PSP token or payment method identifier
* VGS associates that PSP token with the existing card object during the response flow

That keeps the VGS card object as the canonical record while still letting the PSP token originate from the merchant's existing payments architecture.

#### 5. Sample Stripe request and response through the outbound route

The merchant can keep using its existing Stripe `payment_methods` flow, but instead of sending the direct VGS Aliases, they send card-object references through the VGS outbound route.

This is what the merchant request can look like before VGS reveals the underlying PAN and CVC to Stripe:

```bash
curl -X POST https://api.stripe.com/v1/payment_methods \
  -u sk_live_xxxxxxxxxxxxxxxxxxxxx: \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'type=card' \
  --data-urlencode 'card[number]=CRD12345.pan' \
  --data-urlencode 'card[exp_month]=12' \
  --data-urlencode 'card[exp_year]=2028' \
  --data-urlencode 'card[cvc]=CRD12345.cvc' \
  --data-urlencode 'billing_details[name]=John Doe'
```

VGS resolves `{CRD12345}.pan` and `{CRD12345}.cvc` at the outbound boundary, Stripe provisions the payment method, and Stripe returns its payment method ID to the merchant response flow.

```json
{
  "id": "pm_1RtExampleStripe",
  "object": "payment_method",
  "type": "card",
  "card": {
    "brand": "visa",
    "last4": "4242",
    "exp_month": 12,
    "exp_year": 2028
  }
}
```

VGS can then associate the returned Stripe payment method ID with the existing card object as the Stripe PSP token for that card.

#### 6. The resulting card object reflects the PSP token learned from the outbound response

After the outbound response is processed, the same canonical card object can be updated so later `GET /cards/{card_id}` calls, token-sync workflows, or merchant reads reflect the PSP token that was actually created downstream.

```json
{
  "data": {
    "id": "CRD12345",
    "type": "cards",
    "attributes": {
      "pan_alias": "tok_abcdefg",
      "cvc_alias": "tok_vwxyz",
      "token_type": "pan",
      "bin": "424242",
      "first8": "42424242",
      "last4": "4242",
      "exp_month": 12,
      "exp_year": 2028,
      "cardholder_name": "John Doe",
      "network_transaction_id": "0163125478900412"
    },
    "capabilities": [
      "psp-tokens"
    ],
    "included": [
      {
        "type": "psp-tokens",
        "attributes": {
          "stripe": {
            "attributes": {
              "token": "pm_1RtExampleStripe",
              "state": "active",
              "last_sync_status": "provisioned"
            }
          }
        }
      }
    ]
  }
}
```

This option is a good fit when the merchant wants to preserve an existing VGS payment-architecture pattern where the PSP token is created as part of the downstream PSP interaction, but still wants VGS to keep the canonical card object synchronized with that PSP token afterward.


# API Reference

The VGS Card Management Platform (CMP) API

**Sandbox server:** `https://sandbox.vgsapi.com`

A sandbox environment server used for integration and testing purposes. Uses network sandboxes in addition to mocked data sources.

[**Card Management**](/cmp) **YAML Files for Sandbox Environment:**

* Download [card-management-api-dev ](https://openapi.gitbook.com/o/hcowjO8ckQ1K5fm3NPZH/spec/card-management-api-dev.yaml)

\
**Live server:** `https://vgsapi.com`

Live environment server used for production workloads.&#x20;

[**Card Management**](/cmp) **YAML Files for Live Environment:**

* Download [card-management-api](https://openapi.gitbook.com/o/hcowjO8ckQ1K5fm3NPZH/spec/card-management-api.yaml)<br>

**API Basics**

* All 4XX errors can be retried with appropriate changes made to the request to correct the error.
* 502/503/504s can be retried at a later time, as these are transient errors.
* 500s should not be retried unless advised by VGS, as these may require additional correction.

|     |                        |                                                                                                                                                                                                 |
| --- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 | bad-request            | There is a problem with your request. This error will potentially appear for issues with the formatting or content of your request that are not clearly identifiable by the server.             |
| 401 | unauthorized           | Your request lacks valid authentication credentials.                                                                                                                                            |
| 403 | forbidden              | The credentials provided do not possess the correct privileges to complete this action.                                                                                                         |
| 415 | unsupported-media-type | Your request is not using the proper media type. Requests to this API use the JSON:API media type ('application/vnd.api+json') in the Content-Type header.                                      |
| 422 | missing-required-field | A field which is required for a valid request is missing.                                                                                                                                       |
| 422 | validation-failed      | A field with specific validations is not valid.                                                                                                                                                 |
| 422 | failed-dependency      | The operation cannot be completed due to a dependent resource not being in the correct state. Used when attempting to interact with a Network Token that is missing or not in the ACTIVE state. |
| 500 | server-error           | An error occurred. This problem is not addressable by changing the request, and the request should not be reattempted.                                                                          |
| 502 | bad-gateway            | This error will not have the same structure as other errors, as it will be returned before the request has been processed by the application.                                                   |
| 503 | service-unavailable    | This error will not have the same structure as other errors, as it will be returned before the request has been processed by the application.                                                   |
| 504 | gateway-timeout        | This error will not have the same structure as other errors, as it will be returned before the request has been processed by the application.                                                   |


# Cards

## Create a card

> The Create Card Operation allows clients to register a card into the Card Management Platform (CMP) using a simple API call. This card object is linked to a specific account, supporting \[account-level management]\(<https://docs.verygoodsecurity.com/card-management/account-management>) and visibility. Each card is uniquely identified by a persistent Card ID, which does not change, even if updates are made to the underlying card data. This Approach enables businesses to manage card-related features like tokenization and account updates in a centralized, consistent way. (Read more about \[Duplicate Card Detection]\(<https://docs.verygoodsecurity.com/card-management/account-management/cards#duplicate-card-detection>) and \[Card Fingerprint]\(<https://docs.verygoodsecurity.com/card-management/account-management/cards#utilizing-fingerprint-with-vgs>)). CMP ensures secure handling and logical grouping of cards under customer accounts, offering a scalable and organized card management experience.\
> \
> The card object also supports \[user-defined metadata]\(<https://docs.verygoodsecurity.com/card-management/account-management/cards#user-defined-metadata>) through a meta object. This allows clients to attach structured, application-specific information to a card without affecting payment processing. Metadata can include any string key-value pairs to meet business needs — for example, linking a card to internal customer records, identifying the source system, or tagging the card with relevant attributes.\
> \
> PAN and Card Verification Code (CVC) tokens/aliases generated by VGS will be included as part of the response and the actual CVC can be included securely as part of a transaction. Only PCI-Compliant clients will be able to view the actual CVC, while non-PCI-Compliant clients will only be able to view an indicator that CVC was added as part of the transaction. Find more information on CVC \[here]\(<https://www.verygoodsecurity.com/docs/card-management/authentication#accessing-and-handling-cvc>).<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Cards"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardResourceRequest":{"type":"object","properties":{"data":{"type":"object","properties":{"attributes":{"$ref":"#/components/schemas/CardAttributes"},"meta":{"$ref":"#/components/schemas/CardResourceMetadata"}},"required":["attributes"]}},"description":"The card information.","additionalProperties":false,"required":["data"]},"CardAttributes":{"type":"object","properties":{"pan":{"type":"string","maxLength":19,"minLength":14,"title":"Primary Account Number","description":"The primary account number of the card."},"cvc":{"type":"string","maxLength":4,"minLength":3,"title":"Card Verification Code","description":"The card verification code of the card. It's a security measure, typically a three-digit number on the back of the card (or four digits on some cards like American Express).\n"},"cvc_status":{"type":"string","maxLength":10,"minLength":3,"title":"CVC Status","description":"The is an indicator that CVC was present during Create Card.\n"},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"},"cardholder":{"$ref":"#/components/schemas/Cardholder","description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"token_type":{"$ref":"#/components/schemas/TokenType"},"wallet_type":{"$ref":"#/components/schemas/WalletType"}},"required":["pan","exp_month","exp_year"]},"Cardholder":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"The cardholder name."},"company":{"type":"string","maxLength":255,"title":"Company","description":"Company name."},"phone":{"type":"string","maxLength":16,"title":"Phone","description":"The phone number related to the card."},"email":{"type":"string","format":"email","description":"Email address of the account holder."},"address":{"$ref":"#/components/schemas/Address"}},"description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"Address":{"properties":{"address1":{"type":"string","maxLength":255,"description":"The first line of the address related to the card."},"address2":{"type":"string","maxLength":255,"description":"The second line of the address related to the card."},"address3":{"type":"string","maxLength":255,"description":"The third line of the address related to the card."},"address4":{"type":"string","maxLength":255,"description":"The fourth line of the address related to the card."},"city":{"type":"string","maxLength":255,"description":"The city of the address related to the card."},"region":{"type":"string","maxLength":255,"description":"The region of the address related to the card."},"postal_code":{"type":"string","maxLength":10,"description":"The postal code of the address related to the card."},"country":{"type":"string","maxLength":3,"minLength":2,"description":"The country of the address related to the card. This must be the ISO 3166-1 alpha-2 or the ISO 3166-1 alpha-3 code. (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3]\n"}},"type":"object","title":"Address"},"TokenType":{"type":"string","description":"The type of token being used for the card.","enum":["dpan","mpan","pan"]},"WalletType":{"type":"string","description":"The digital wallet from which the card request originated.","enum":["apple_pay","google_pay"]},"CardResourceMetadata":{"type":"object","description":"Non-standard meta-information about the card resource."},"CardResourceResponse":{"title":"CardResourceResponse","type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/BaseResource"},{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"Type","default":"cards"},"attributes":{"$ref":"#/components/schemas/CardResourceAttributes"},"meta":{"$ref":"#/components/schemas/CardResourceMetadata"}},"type":"object"}]},"included":{"items":{"$ref":"#/components/schemas/IncludedResource"},"type":"array","title":"IncludedResources","description":"Complete resource objects for resources related to the primary data in the response."},"metadata":{"$ref":"#/components/schemas/MetadataResponse"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"additionalProperties":false,"required":["data"]},"BaseResource":{"properties":{"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}}},{"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"type":"object","title":"BaseResource"},"CardResourceAttributes":{"type":"object","title":"CardResourceAttributes","description":"Full card information with extra fields like bin, last4, capabilities etc","allOf":[{"$ref":"#/components/schemas/CardAttributes"},{"$ref":"#/components/schemas/CardAttributeAliases"},{"properties":{"bin":{"type":"string","minLength":6,"maxLength":8,"description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"first8":{"type":"string","minLength":8,"maxLength":8,"description":"8 character Bank Identification Number (BIN). The first8 field will be returned in the card object only for Visa and Mastercard cards."},"last4":{"type":"string","minLength":4,"maxLength":4,"description":"Last 4 characters of the primary account number (pan/fpan)"},"card_fingerprint":{"type":"string","description":"Card Fingerprint"},"cvc_status":{"type":"string","description":"CVC Status"},"capabilities":{"items":{"type":"string","enum":["card-updates","network-tokens"],"title":"CardCapabilities"},"type":"array","title":"Capabilities","description":"The capabilities a card has had activated during the creation process.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"card_brand":{"type":"string","description":"The name of the card brand."},"card_type":{"type":"string","description":"The card type (credit, debit or prepaid)."},"enriched_attributes":{"$ref":"#/components/schemas/EnrichedCardAttributes","description":"Enriched card attributes containing additional metadata about the card. \nThis data provides detailed information about the card's capabilities, issuer \ndetails, and transaction support features.\n"},"payment_account_reference":{"type":"string","title":"Payment Account Reference","description":"Payment Account Reference (PAR) most recently retrieved for this\ncard via `POST /cards/{card_id}/payment-account-references`.\nPresent once a successful PAR lookup has been performed.\n"},"enrollment_source":{"$ref":"#/components/schemas/EnrollmentSource","readOnly":true,"description":"Indicates whether the card was loaded from an existing backbook\nportfolio or newly tokenized. Set by the server based on the\n`processing` query parameter at card creation time; read-only.\n"}},"required":["bin","first8","last4","created_at","updated_at"],"type":"object"}]},"CardAttributeAliases":{"type":"object","properties":{"pan_alias":{"type":"string","title":"PAN Alias","description":"The PAN alias is a reference identifier that stores or securely holds the actual PAN value.\n"},"cvc_alias":{"type":"string","maxLength":35,"minLength":30,"title":"CVC Alias","description":"The CVC Alias is a reference identifier that stores or securely holds the actual CVC value.\n"}}},"EnrichedCardAttributes":{"type":"object","description":"Enriched card attributes from the card-attributes service","properties":{"card_properties":{"type":"object","properties":{"card_number_length":{"type":"integer","description":"The length of the Primary Account Number (PAN) printed on the front of the card. Available only for Card Attributes service subscribers.\n"},"card_segment_type":{"type":"string","description":"Indicator of Business, Consumer, Commercial, Government BINs. Available only for Card Attributes service subscribers."},"virtual_card":{"type":"boolean","description":"Indicates if the given BIN range supports virtual card creation. Available only for Card Attributes service subscribers.\n"},"prepaid_card":{"type":"boolean","description":"Indicates a fixed funding source for a card but not necessarily associated with the consumer's checking account. Available only for Card Attributes service subscribers.\n"},"product_name":{"type":"string","description":"The card product name according to the card brand (e.g., Visa Signature, Visa Infinite, Visa Classic). Available only for Card Attributes service subscribers.\n"},"issuer_bin":{"type":"string","description":"Bank Identification Number (BIN) of the issuer of the account. Available only for Card Attributes service subscribers."},"country_letter_code":{"type":"string","description":"ISO country letters that is associated with an ISO 3166-1 alpha-2 code."},"country_name":{"type":"string","description":"Name of the issuing country. Available only for Card Attributes service subscribers."},"country_numeric":{"type":"integer","description":"ISO 3166 numeric country code of the issuing country. Available only for Card Attributes service subscribers."}}},"card_capabilities":{"type":"object","properties":{"reloadable":{"type":"boolean","description":"Indicator of reloadable or non-reloadable prepaid. Available only for Card Attributes service subscribers."},"hsa":{"type":"boolean","description":"Indicates a card attached to a Health Savings Account. Available only for Card Attributes service subscribers."},"fsa":{"type":"boolean","description":"Indicates a card attached to Flexible Spending Account. Available only for Card Attributes service subscribers."},"ebt":{"type":"boolean","description":"Indicates the BIN has Electronic Benefits Transfer (EBT) capabilities. Available only for Card Attributes service subscribers."},"commercial_level2":{"type":"boolean","description":"Indicates the card supports Level 2 commercial data. Available only for Card Attributes service subscribers."},"commercial_level3":{"type":"boolean","description":"Indicates the card supports Level 3 commercial data. Available only for Card Attributes service subscribers."}}},"bank":{"type":"object","properties":{"issuer_name":{"type":"string","description":"Name of the issuing organization/bank."},"issuer_phone_number":{"type":"string","description":"Phone number of the issuing organization/bank. Available only for Card Attributes service subscribers."},"issuer_website":{"type":"string","description":"Website of the issuing organization/bank. Available only for Card Attributes service subscribers."}}},"additional_card_brands":{"type":"array","description":"Additional card brands, if any, associated with the card. Available only for Card Attributes service subscribers.","items":{"type":"object","required":["card_brand"],"properties":{"card_brand":{"type":"string","description":"The name of the additional card brand. Available only for Card Attributes service subscribers."}}}},"interchange":{"type":"object","properties":{"regulated":{"type":"string","description":"Indicator of the presence of an interchange regulation on a BIN. Available only for Card Attributes service subscribers."}}}}},"EnrollmentSource":{"type":"string","description":"Indicates whether the card was loaded from an existing backbook portfolio\nor newly tokenized. Set by the server based on the `processing` query\nparameter at card creation time and is read-only.\n","enum":["backbook","frontbook"]},"IncludedResource":{"allOf":[{"$ref":"#/components/schemas/BaseIncludedResource"},{"oneOf":[{"$ref":"#/components/schemas/CardUpdateResource"},{"$ref":"#/components/schemas/CardUpdateSubscriptionResource"},{"$ref":"#/components/schemas/NetworkTokenResource"}]}],"discriminator":{"propertyName":"type","mapping":{"card_updates":"#/components/schemas/CardUpdateResource","card_update_subscriptions":"#/components/schemas/CardUpdateSubscriptionResource","network_tokens":"#/components/schemas/NetworkTokenResource"}}},"BaseIncludedResource":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/IncludedResourceType"}}},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"CardUpdateResource":{"type":"object","description":"An event representing an update from the card network pertaining to the related card and card update subscription.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"occurred_at":{"type":"string","format":"datetime"},"reason_code":{"type":"string"},"reason_text":{"type":"string"},"changed_fields":{"type":"array","items":{"type":"string"}},"updated_values":{"type":"array","title":"CardUpdateResourceUpdatedValues","items":{"$ref":"#/components/schemas/UpdatedCardFieldResource"}},"event":{"type":"string","enum":["updated","expired","closed","non-participating","contact-cardholder-advice","unknown","enrolled","enrollment-failed","opt-out"],"description":"- updated - **Account number change message**: This event is triggered when a cardholder opens a new account with a participating issuer or when a new card is issued. For e.g. this could be due to new account creation, lost or stolen card, or when a card holder gets upgraded to Platinum or downgraded, or, due to a portfolio change (one bank to another).\n- expired - **Expiration date change** This event denotes an expiration date change event. Whenever the card expires but has the same PAN, then, a new expiration date is issued. This event is an indication that the card expired (and so a new date is issued). Typically, cards have an expiration date of 2, 3 or x years (it used to be 5 but we rarely see them these days). Sometimes, an issuer can have an expiration for 1 year (for brand new card holders as they do not have enough credit).\n- closed - **Closed account advice** This event is triggered when the issuer reports the closure of the cardholder's account i.e. cardholder's account associated with the particular card is no longer active/closed providing an important update for merchants to keep their records accurate and avoid attempting transactions with invalid or closed accounts.\n- non-participating - **Non-participating BIN** This event represents a non-participating BIN event, indicating that cards linked to these BINs will not receive updates through the account updater service. i.e. BIN of a particular card is not participating in the account updater service and merchants subscribed to account updater will not receive updates for cards associated with non-participating BINs.\n- contact-cardholder-advice - **Contact cardholder advice** This event indicates the issuer is letting the merchant know that something has changed and the merchant should force the customer to key enter the credential and the update will not be shared via the account updater channel for the merchant. In short the merchant must contact the cardholder for more information or clarification.\n- unknown - **Account not found response from a participating BIN** This event indicates that the card is eligible for automatic updates, but no match was found for this account.\n- enrolled - This event is triggered when a card is successfully enrolled in account updater or when the network confirms that the card status remains unchanged. **Successfully enrolled** - The card is successfully enrolled for updates from the networks. **Match made, account number and expiration date unchanged** - This event implies that the card is already enrolled for account updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.\n- enrollment-failed - This event is triggered when a card was unsuccessfully enrolled in account updater.\n- opt-out - **Cardholder Opt-Out Note** (Stop Advice) is placed on a card.\n"},"received_at":{"type":"string","format":"datetime","description":"Timestamp of when the event was received from the network."}},"required":["received_at","occurred_at","event","changed_fields","updated_values"],"title":"CardUpdateResourceAttributes"}},"additionalProperties":false},"UpdatedCardFieldResource":{"type":"object","title":"UpdatedCardFieldResource","properties":{"field_name":{"type":"string"},"old_value":{"type":"string"},"new_value":{"type":"string"}},"required":["field_name","old_value","new_value"]},"CardUpdateSubscriptionResource":{"type":"object","description":"An object representing a card account updater subscription. A card update subscription receives updates from the card network when the card is renewed or replaced.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"bin":{"type":"string","format":"\\d{6,10}","description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"created_at":{"type":"string","format":"date-time"},"state":{"type":"string","enum":["enrolled","failed"],"description":"State of the card update subscription."},"updated_at":{"type":"string","format":"date-time"}}}}},"NetworkTokenResource":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"$ref":"#/components/schemas/NetworkTokenAttributes"},"meta":{"type":"object","title":"meta","description":"Information about the card meta, including card art","properties":{"card_art":{"$ref":"#/components/schemas/CardArt","description":"Card art\n"}}},"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"additionalProperties":false,"type":"object","required":["id","type"],"title":"NetworkTokenResource"},"NetworkTokenAttributes":{"type":"object","properties":{"payment_account_reference":{"type":"string","title":"Payment Account Reference"},"network_token":{"type":"string","title":"The network token PAN","minLength":13,"maxLength":19},"last4":{"type":"string","title":"Network Token Last4","maxLength":4},"bin":{"type":"string","title":"Network Token Bin","minLength":6,"maxLength":10},"exp_month":{"type":"integer","title":"Expiration Month","minimum":1,"maximum":12},"exp_year":{"type":"integer","title":"Expiration Year","minimum":0,"maximum":99},"created_at":{"type":"string","title":"Created At","format":"date-time"},"updated_at":{"type":"string","title":"Updated At","format":"date-time"},"state":{"type":"string","title":"State"},"reason_code":{"type":"string"},"reason_text":{"type":"string"}},"required":["payment_account_reference","network_token","last4","bin","exp_month","exp_year","created_at","updated_at","state"],"title":"NetworkTokenSchema"},"CardArt":{"type":"object","description":"Card art","properties":{"background_color":{"type":"string","description":"Background color of card art"},"foreground_color":{"type":"string","description":"Foreground color of card art"},"label_color":{"type":"string","description":"Label color of card art"},"issuer_name":{"type":"string","description":"Issuer of the card"},"contact_website":{"type":"string","description":"Contact website of the card"},"contact_number":{"type":"string","description":"Contact phone number of the card"},"contact_name":{"type":"string","description":"Contact name of the card"},"short_description":{"type":"string","description":"Short description of the card"},"long_description":{"type":"string","description":"Long description of the card"},"assets":{"type":"array","items":{"$ref":"#/components/schemas/CardAsset"}}}},"CardAsset":{"type":"object","description":"Card asset","required":["type","download_url"],"properties":{"type":{"type":"string","description":"Type of card asset","enum":["CARD_SYMBOL","DIGITAL_CARD_ART","DIGITAL_CARD_ART_BACKGROUND"]},"mime_type":{"type":"string","description":"MIME type of the file"},"width":{"type":"integer","description":"Width of the image in pixel"},"height":{"type":"integer","description":"Height of the image in pixel"},"download_url":{"type":"string","description":"URL for downloading the image"}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards":{"post":{"tags":["Cards"],"summary":"Create a card","description":"The Create Card Operation allows clients to register a card into the Card Management Platform (CMP) using a simple API call. This card object is linked to a specific account, supporting [account-level management](https://docs.verygoodsecurity.com/card-management/account-management) and visibility. Each card is uniquely identified by a persistent Card ID, which does not change, even if updates are made to the underlying card data. This Approach enables businesses to manage card-related features like tokenization and account updates in a centralized, consistent way. (Read more about [Duplicate Card Detection](https://docs.verygoodsecurity.com/card-management/account-management/cards#duplicate-card-detection) and [Card Fingerprint](https://docs.verygoodsecurity.com/card-management/account-management/cards#utilizing-fingerprint-with-vgs)). CMP ensures secure handling and logical grouping of cards under customer accounts, offering a scalable and organized card management experience.\n\nThe card object also supports [user-defined metadata](https://docs.verygoodsecurity.com/card-management/account-management/cards#user-defined-metadata) through a meta object. This allows clients to attach structured, application-specific information to a card without affecting payment processing. Metadata can include any string key-value pairs to meet business needs — for example, linking a card to internal customer records, identifying the source system, or tagging the card with relevant attributes.\n\nPAN and Card Verification Code (CVC) tokens/aliases generated by VGS will be included as part of the response and the actual CVC can be included securely as part of a transaction. Only PCI-Compliant clients will be able to view the actual CVC, while non-PCI-Compliant clients will only be able to view an indicator that CVC was added as part of the transaction. Find more information on CVC [here](https://www.verygoodsecurity.com/docs/card-management/authentication#accessing-and-handling-cvc).\n","operationId":"create_card_cards_post","parameters":[{"name":"processing","in":"query","required":false,"schema":{"type":"string","enum":["backbook"]},"description":"Optional processing mode for the card creation request.\n\n**Example:** `POST /cards?processing=backbook`\n\n- `backbook`: network token and account updater enrollment are skipped, treating the card as backbook traffic.\n\n**Ignored on Wallet Decryption card creation requests.**\n"}],"requestBody":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceRequest"}}},"required":true},"responses":{"201":{"description":"Card created","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponse"}}}},"303":{"description":"The card you are trying to create already exists within the system.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Get a card

> The Get Card API allows clients to retrieve details for a specific card using its unique Card ID. This includes core card metadata and any associated account updater or network token information, if applicable.\
> This endpoint is useful for verifying enrollment status, accessing the current state of a card, or reviewing the card's lifecycle attributes. It provides a comprehensive snapshot of the card and its current relationships within CMP.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Cards"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardResourceResponse":{"title":"CardResourceResponse","type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/BaseResource"},{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"Type","default":"cards"},"attributes":{"$ref":"#/components/schemas/CardResourceAttributes"},"meta":{"$ref":"#/components/schemas/CardResourceMetadata"}},"type":"object"}]},"included":{"items":{"$ref":"#/components/schemas/IncludedResource"},"type":"array","title":"IncludedResources","description":"Complete resource objects for resources related to the primary data in the response."},"metadata":{"$ref":"#/components/schemas/MetadataResponse"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"additionalProperties":false,"required":["data"]},"BaseResource":{"properties":{"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}}},{"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"type":"object","title":"BaseResource"},"CardResourceAttributes":{"type":"object","title":"CardResourceAttributes","description":"Full card information with extra fields like bin, last4, capabilities etc","allOf":[{"$ref":"#/components/schemas/CardAttributes"},{"$ref":"#/components/schemas/CardAttributeAliases"},{"properties":{"bin":{"type":"string","minLength":6,"maxLength":8,"description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"first8":{"type":"string","minLength":8,"maxLength":8,"description":"8 character Bank Identification Number (BIN). The first8 field will be returned in the card object only for Visa and Mastercard cards."},"last4":{"type":"string","minLength":4,"maxLength":4,"description":"Last 4 characters of the primary account number (pan/fpan)"},"card_fingerprint":{"type":"string","description":"Card Fingerprint"},"cvc_status":{"type":"string","description":"CVC Status"},"capabilities":{"items":{"type":"string","enum":["card-updates","network-tokens"],"title":"CardCapabilities"},"type":"array","title":"Capabilities","description":"The capabilities a card has had activated during the creation process.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"card_brand":{"type":"string","description":"The name of the card brand."},"card_type":{"type":"string","description":"The card type (credit, debit or prepaid)."},"enriched_attributes":{"$ref":"#/components/schemas/EnrichedCardAttributes","description":"Enriched card attributes containing additional metadata about the card. \nThis data provides detailed information about the card's capabilities, issuer \ndetails, and transaction support features.\n"},"payment_account_reference":{"type":"string","title":"Payment Account Reference","description":"Payment Account Reference (PAR) most recently retrieved for this\ncard via `POST /cards/{card_id}/payment-account-references`.\nPresent once a successful PAR lookup has been performed.\n"},"enrollment_source":{"$ref":"#/components/schemas/EnrollmentSource","readOnly":true,"description":"Indicates whether the card was loaded from an existing backbook\nportfolio or newly tokenized. Set by the server based on the\n`processing` query parameter at card creation time; read-only.\n"}},"required":["bin","first8","last4","created_at","updated_at"],"type":"object"}]},"CardAttributes":{"type":"object","properties":{"pan":{"type":"string","maxLength":19,"minLength":14,"title":"Primary Account Number","description":"The primary account number of the card."},"cvc":{"type":"string","maxLength":4,"minLength":3,"title":"Card Verification Code","description":"The card verification code of the card. It's a security measure, typically a three-digit number on the back of the card (or four digits on some cards like American Express).\n"},"cvc_status":{"type":"string","maxLength":10,"minLength":3,"title":"CVC Status","description":"The is an indicator that CVC was present during Create Card.\n"},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"},"cardholder":{"$ref":"#/components/schemas/Cardholder","description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"token_type":{"$ref":"#/components/schemas/TokenType"},"wallet_type":{"$ref":"#/components/schemas/WalletType"}},"required":["pan","exp_month","exp_year"]},"Cardholder":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"The cardholder name."},"company":{"type":"string","maxLength":255,"title":"Company","description":"Company name."},"phone":{"type":"string","maxLength":16,"title":"Phone","description":"The phone number related to the card."},"email":{"type":"string","format":"email","description":"Email address of the account holder."},"address":{"$ref":"#/components/schemas/Address"}},"description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"Address":{"properties":{"address1":{"type":"string","maxLength":255,"description":"The first line of the address related to the card."},"address2":{"type":"string","maxLength":255,"description":"The second line of the address related to the card."},"address3":{"type":"string","maxLength":255,"description":"The third line of the address related to the card."},"address4":{"type":"string","maxLength":255,"description":"The fourth line of the address related to the card."},"city":{"type":"string","maxLength":255,"description":"The city of the address related to the card."},"region":{"type":"string","maxLength":255,"description":"The region of the address related to the card."},"postal_code":{"type":"string","maxLength":10,"description":"The postal code of the address related to the card."},"country":{"type":"string","maxLength":3,"minLength":2,"description":"The country of the address related to the card. This must be the ISO 3166-1 alpha-2 or the ISO 3166-1 alpha-3 code. (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3]\n"}},"type":"object","title":"Address"},"TokenType":{"type":"string","description":"The type of token being used for the card.","enum":["dpan","mpan","pan"]},"WalletType":{"type":"string","description":"The digital wallet from which the card request originated.","enum":["apple_pay","google_pay"]},"CardAttributeAliases":{"type":"object","properties":{"pan_alias":{"type":"string","title":"PAN Alias","description":"The PAN alias is a reference identifier that stores or securely holds the actual PAN value.\n"},"cvc_alias":{"type":"string","maxLength":35,"minLength":30,"title":"CVC Alias","description":"The CVC Alias is a reference identifier that stores or securely holds the actual CVC value.\n"}}},"EnrichedCardAttributes":{"type":"object","description":"Enriched card attributes from the card-attributes service","properties":{"card_properties":{"type":"object","properties":{"card_number_length":{"type":"integer","description":"The length of the Primary Account Number (PAN) printed on the front of the card. Available only for Card Attributes service subscribers.\n"},"card_segment_type":{"type":"string","description":"Indicator of Business, Consumer, Commercial, Government BINs. Available only for Card Attributes service subscribers."},"virtual_card":{"type":"boolean","description":"Indicates if the given BIN range supports virtual card creation. Available only for Card Attributes service subscribers.\n"},"prepaid_card":{"type":"boolean","description":"Indicates a fixed funding source for a card but not necessarily associated with the consumer's checking account. Available only for Card Attributes service subscribers.\n"},"product_name":{"type":"string","description":"The card product name according to the card brand (e.g., Visa Signature, Visa Infinite, Visa Classic). Available only for Card Attributes service subscribers.\n"},"issuer_bin":{"type":"string","description":"Bank Identification Number (BIN) of the issuer of the account. Available only for Card Attributes service subscribers."},"country_letter_code":{"type":"string","description":"ISO country letters that is associated with an ISO 3166-1 alpha-2 code."},"country_name":{"type":"string","description":"Name of the issuing country. Available only for Card Attributes service subscribers."},"country_numeric":{"type":"integer","description":"ISO 3166 numeric country code of the issuing country. Available only for Card Attributes service subscribers."}}},"card_capabilities":{"type":"object","properties":{"reloadable":{"type":"boolean","description":"Indicator of reloadable or non-reloadable prepaid. Available only for Card Attributes service subscribers."},"hsa":{"type":"boolean","description":"Indicates a card attached to a Health Savings Account. Available only for Card Attributes service subscribers."},"fsa":{"type":"boolean","description":"Indicates a card attached to Flexible Spending Account. Available only for Card Attributes service subscribers."},"ebt":{"type":"boolean","description":"Indicates the BIN has Electronic Benefits Transfer (EBT) capabilities. Available only for Card Attributes service subscribers."},"commercial_level2":{"type":"boolean","description":"Indicates the card supports Level 2 commercial data. Available only for Card Attributes service subscribers."},"commercial_level3":{"type":"boolean","description":"Indicates the card supports Level 3 commercial data. Available only for Card Attributes service subscribers."}}},"bank":{"type":"object","properties":{"issuer_name":{"type":"string","description":"Name of the issuing organization/bank."},"issuer_phone_number":{"type":"string","description":"Phone number of the issuing organization/bank. Available only for Card Attributes service subscribers."},"issuer_website":{"type":"string","description":"Website of the issuing organization/bank. Available only for Card Attributes service subscribers."}}},"additional_card_brands":{"type":"array","description":"Additional card brands, if any, associated with the card. Available only for Card Attributes service subscribers.","items":{"type":"object","required":["card_brand"],"properties":{"card_brand":{"type":"string","description":"The name of the additional card brand. Available only for Card Attributes service subscribers."}}}},"interchange":{"type":"object","properties":{"regulated":{"type":"string","description":"Indicator of the presence of an interchange regulation on a BIN. Available only for Card Attributes service subscribers."}}}}},"EnrollmentSource":{"type":"string","description":"Indicates whether the card was loaded from an existing backbook portfolio\nor newly tokenized. Set by the server based on the `processing` query\nparameter at card creation time and is read-only.\n","enum":["backbook","frontbook"]},"CardResourceMetadata":{"type":"object","description":"Non-standard meta-information about the card resource."},"IncludedResource":{"allOf":[{"$ref":"#/components/schemas/BaseIncludedResource"},{"oneOf":[{"$ref":"#/components/schemas/CardUpdateResource"},{"$ref":"#/components/schemas/CardUpdateSubscriptionResource"},{"$ref":"#/components/schemas/NetworkTokenResource"}]}],"discriminator":{"propertyName":"type","mapping":{"card_updates":"#/components/schemas/CardUpdateResource","card_update_subscriptions":"#/components/schemas/CardUpdateSubscriptionResource","network_tokens":"#/components/schemas/NetworkTokenResource"}}},"BaseIncludedResource":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/IncludedResourceType"}}},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"CardUpdateResource":{"type":"object","description":"An event representing an update from the card network pertaining to the related card and card update subscription.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"occurred_at":{"type":"string","format":"datetime"},"reason_code":{"type":"string"},"reason_text":{"type":"string"},"changed_fields":{"type":"array","items":{"type":"string"}},"updated_values":{"type":"array","title":"CardUpdateResourceUpdatedValues","items":{"$ref":"#/components/schemas/UpdatedCardFieldResource"}},"event":{"type":"string","enum":["updated","expired","closed","non-participating","contact-cardholder-advice","unknown","enrolled","enrollment-failed","opt-out"],"description":"- updated - **Account number change message**: This event is triggered when a cardholder opens a new account with a participating issuer or when a new card is issued. For e.g. this could be due to new account creation, lost or stolen card, or when a card holder gets upgraded to Platinum or downgraded, or, due to a portfolio change (one bank to another).\n- expired - **Expiration date change** This event denotes an expiration date change event. Whenever the card expires but has the same PAN, then, a new expiration date is issued. This event is an indication that the card expired (and so a new date is issued). Typically, cards have an expiration date of 2, 3 or x years (it used to be 5 but we rarely see them these days). Sometimes, an issuer can have an expiration for 1 year (for brand new card holders as they do not have enough credit).\n- closed - **Closed account advice** This event is triggered when the issuer reports the closure of the cardholder's account i.e. cardholder's account associated with the particular card is no longer active/closed providing an important update for merchants to keep their records accurate and avoid attempting transactions with invalid or closed accounts.\n- non-participating - **Non-participating BIN** This event represents a non-participating BIN event, indicating that cards linked to these BINs will not receive updates through the account updater service. i.e. BIN of a particular card is not participating in the account updater service and merchants subscribed to account updater will not receive updates for cards associated with non-participating BINs.\n- contact-cardholder-advice - **Contact cardholder advice** This event indicates the issuer is letting the merchant know that something has changed and the merchant should force the customer to key enter the credential and the update will not be shared via the account updater channel for the merchant. In short the merchant must contact the cardholder for more information or clarification.\n- unknown - **Account not found response from a participating BIN** This event indicates that the card is eligible for automatic updates, but no match was found for this account.\n- enrolled - This event is triggered when a card is successfully enrolled in account updater or when the network confirms that the card status remains unchanged. **Successfully enrolled** - The card is successfully enrolled for updates from the networks. **Match made, account number and expiration date unchanged** - This event implies that the card is already enrolled for account updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.\n- enrollment-failed - This event is triggered when a card was unsuccessfully enrolled in account updater.\n- opt-out - **Cardholder Opt-Out Note** (Stop Advice) is placed on a card.\n"},"received_at":{"type":"string","format":"datetime","description":"Timestamp of when the event was received from the network."}},"required":["received_at","occurred_at","event","changed_fields","updated_values"],"title":"CardUpdateResourceAttributes"}},"additionalProperties":false},"UpdatedCardFieldResource":{"type":"object","title":"UpdatedCardFieldResource","properties":{"field_name":{"type":"string"},"old_value":{"type":"string"},"new_value":{"type":"string"}},"required":["field_name","old_value","new_value"]},"CardUpdateSubscriptionResource":{"type":"object","description":"An object representing a card account updater subscription. A card update subscription receives updates from the card network when the card is renewed or replaced.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"bin":{"type":"string","format":"\\d{6,10}","description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"created_at":{"type":"string","format":"date-time"},"state":{"type":"string","enum":["enrolled","failed"],"description":"State of the card update subscription."},"updated_at":{"type":"string","format":"date-time"}}}}},"NetworkTokenResource":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"$ref":"#/components/schemas/NetworkTokenAttributes"},"meta":{"type":"object","title":"meta","description":"Information about the card meta, including card art","properties":{"card_art":{"$ref":"#/components/schemas/CardArt","description":"Card art\n"}}},"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"additionalProperties":false,"type":"object","required":["id","type"],"title":"NetworkTokenResource"},"NetworkTokenAttributes":{"type":"object","properties":{"payment_account_reference":{"type":"string","title":"Payment Account Reference"},"network_token":{"type":"string","title":"The network token PAN","minLength":13,"maxLength":19},"last4":{"type":"string","title":"Network Token Last4","maxLength":4},"bin":{"type":"string","title":"Network Token Bin","minLength":6,"maxLength":10},"exp_month":{"type":"integer","title":"Expiration Month","minimum":1,"maximum":12},"exp_year":{"type":"integer","title":"Expiration Year","minimum":0,"maximum":99},"created_at":{"type":"string","title":"Created At","format":"date-time"},"updated_at":{"type":"string","title":"Updated At","format":"date-time"},"state":{"type":"string","title":"State"},"reason_code":{"type":"string"},"reason_text":{"type":"string"}},"required":["payment_account_reference","network_token","last4","bin","exp_month","exp_year","created_at","updated_at","state"],"title":"NetworkTokenSchema"},"CardArt":{"type":"object","description":"Card art","properties":{"background_color":{"type":"string","description":"Background color of card art"},"foreground_color":{"type":"string","description":"Foreground color of card art"},"label_color":{"type":"string","description":"Label color of card art"},"issuer_name":{"type":"string","description":"Issuer of the card"},"contact_website":{"type":"string","description":"Contact website of the card"},"contact_number":{"type":"string","description":"Contact phone number of the card"},"contact_name":{"type":"string","description":"Contact name of the card"},"short_description":{"type":"string","description":"Short description of the card"},"long_description":{"type":"string","description":"Long description of the card"},"assets":{"type":"array","items":{"$ref":"#/components/schemas/CardAsset"}}}},"CardAsset":{"type":"object","description":"Card asset","required":["type","download_url"],"properties":{"type":{"type":"string","description":"Type of card asset","enum":["CARD_SYMBOL","DIGITAL_CARD_ART","DIGITAL_CARD_ART_BACKGROUND"]},"mime_type":{"type":"string","description":"MIME type of the file"},"width":{"type":"integer","description":"Width of the image in pixel"},"height":{"type":"integer","description":"Height of the image in pixel"},"download_url":{"type":"string","description":"URL for downloading the image"}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}":{"get":{"tags":["Cards"],"summary":"Get a card","description":"The Get Card API allows clients to retrieve details for a specific card using its unique Card ID. This includes core card metadata and any associated account updater or network token information, if applicable.\nThis endpoint is useful for verifying enrollment status, accessing the current state of a card, or reviewing the card's lifecycle attributes. It provides a comprehensive snapshot of the card and its current relationships within CMP.\n","operationId":"get_card_by_id_cards__card_id__get","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}},{"name":"include","in":"query","required":false,"schema":{"type":"string","title":"Comma-delimited list of resources and/or fields to include.","description":"Comma-delimited list of fields to include in the response."},"description":"Comma-delimited list of fields to include in the response."}],"responses":{"200":{"description":"Item requested by ID","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Delete a card

> The Delete Card API allows clients to permanently remove a card object from the CMP system using a unique Card ID.\
> This operation automatically removes all services associated with the card, such as Network Tokens and Account Updater.\
> Please note that this action is irreversible; once deleted, the card object cannot be recovered, and subsequent calls to the GET endpoint will return no data.\
> \
> Note:  Error responses currently omit payload previews; expect a standard JSON error object.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Cards"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}":{"delete":{"tags":["Cards"],"summary":"Delete a card","description":"The Delete Card API allows clients to permanently remove a card object from the CMP system using a unique Card ID.\nThis operation automatically removes all services associated with the card, such as Network Tokens and Account Updater.\nPlease note that this action is irreversible; once deleted, the card object cannot be recovered, and subsequent calls to the GET endpoint will return no data.\n\nNote:  Error responses currently omit payload previews; expect a standard JSON error object.\n","operationId":"delete_card_by_id","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"204":{"description":"Card deleted"},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Update a Card

> The Update Card API enables clients to modify specific fields on a card using its unique Card ID. The update endpoint only updates the card object; it does not automatically trigger any secondary services or processes. The endpoint response provides a comprehensive snapshot of the card object and its current relationships within CMP.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Cards"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardUpdateResourceRequest":{"type":"object","description":"Card update request payload","title":"CardUpdateResourceRequest","properties":{"data":{"type":"object","properties":{"attributes":{"$ref":"#/components/schemas/CardUpdateAttributes"}},"required":["attributes"]}},"additionalProperties":false,"required":["data"]},"CardUpdateAttributes":{"type":"object","description":"The attributes of the card to update.","title":"CardUpdateAttributes","properties":{"cvc":{"type":"string","maxLength":4,"minLength":3,"title":"Card Verification Code","description":"The card verification code (CVC) of the card."},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"}},"additionalProperties":false},"CardResourceResponse":{"title":"CardResourceResponse","type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/BaseResource"},{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"Type","default":"cards"},"attributes":{"$ref":"#/components/schemas/CardResourceAttributes"},"meta":{"$ref":"#/components/schemas/CardResourceMetadata"}},"type":"object"}]},"included":{"items":{"$ref":"#/components/schemas/IncludedResource"},"type":"array","title":"IncludedResources","description":"Complete resource objects for resources related to the primary data in the response."},"metadata":{"$ref":"#/components/schemas/MetadataResponse"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"additionalProperties":false,"required":["data"]},"BaseResource":{"properties":{"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}}},{"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"type":"object","title":"BaseResource"},"CardResourceAttributes":{"type":"object","title":"CardResourceAttributes","description":"Full card information with extra fields like bin, last4, capabilities etc","allOf":[{"$ref":"#/components/schemas/CardAttributes"},{"$ref":"#/components/schemas/CardAttributeAliases"},{"properties":{"bin":{"type":"string","minLength":6,"maxLength":8,"description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"first8":{"type":"string","minLength":8,"maxLength":8,"description":"8 character Bank Identification Number (BIN). The first8 field will be returned in the card object only for Visa and Mastercard cards."},"last4":{"type":"string","minLength":4,"maxLength":4,"description":"Last 4 characters of the primary account number (pan/fpan)"},"card_fingerprint":{"type":"string","description":"Card Fingerprint"},"cvc_status":{"type":"string","description":"CVC Status"},"capabilities":{"items":{"type":"string","enum":["card-updates","network-tokens"],"title":"CardCapabilities"},"type":"array","title":"Capabilities","description":"The capabilities a card has had activated during the creation process.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"card_brand":{"type":"string","description":"The name of the card brand."},"card_type":{"type":"string","description":"The card type (credit, debit or prepaid)."},"enriched_attributes":{"$ref":"#/components/schemas/EnrichedCardAttributes","description":"Enriched card attributes containing additional metadata about the card. \nThis data provides detailed information about the card's capabilities, issuer \ndetails, and transaction support features.\n"},"payment_account_reference":{"type":"string","title":"Payment Account Reference","description":"Payment Account Reference (PAR) most recently retrieved for this\ncard via `POST /cards/{card_id}/payment-account-references`.\nPresent once a successful PAR lookup has been performed.\n"},"enrollment_source":{"$ref":"#/components/schemas/EnrollmentSource","readOnly":true,"description":"Indicates whether the card was loaded from an existing backbook\nportfolio or newly tokenized. Set by the server based on the\n`processing` query parameter at card creation time; read-only.\n"}},"required":["bin","first8","last4","created_at","updated_at"],"type":"object"}]},"CardAttributes":{"type":"object","properties":{"pan":{"type":"string","maxLength":19,"minLength":14,"title":"Primary Account Number","description":"The primary account number of the card."},"cvc":{"type":"string","maxLength":4,"minLength":3,"title":"Card Verification Code","description":"The card verification code of the card. It's a security measure, typically a three-digit number on the back of the card (or four digits on some cards like American Express).\n"},"cvc_status":{"type":"string","maxLength":10,"minLength":3,"title":"CVC Status","description":"The is an indicator that CVC was present during Create Card.\n"},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"},"cardholder":{"$ref":"#/components/schemas/Cardholder","description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"token_type":{"$ref":"#/components/schemas/TokenType"},"wallet_type":{"$ref":"#/components/schemas/WalletType"}},"required":["pan","exp_month","exp_year"]},"Cardholder":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"The cardholder name."},"company":{"type":"string","maxLength":255,"title":"Company","description":"Company name."},"phone":{"type":"string","maxLength":16,"title":"Phone","description":"The phone number related to the card."},"email":{"type":"string","format":"email","description":"Email address of the account holder."},"address":{"$ref":"#/components/schemas/Address"}},"description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"Address":{"properties":{"address1":{"type":"string","maxLength":255,"description":"The first line of the address related to the card."},"address2":{"type":"string","maxLength":255,"description":"The second line of the address related to the card."},"address3":{"type":"string","maxLength":255,"description":"The third line of the address related to the card."},"address4":{"type":"string","maxLength":255,"description":"The fourth line of the address related to the card."},"city":{"type":"string","maxLength":255,"description":"The city of the address related to the card."},"region":{"type":"string","maxLength":255,"description":"The region of the address related to the card."},"postal_code":{"type":"string","maxLength":10,"description":"The postal code of the address related to the card."},"country":{"type":"string","maxLength":3,"minLength":2,"description":"The country of the address related to the card. This must be the ISO 3166-1 alpha-2 or the ISO 3166-1 alpha-3 code. (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3]\n"}},"type":"object","title":"Address"},"TokenType":{"type":"string","description":"The type of token being used for the card.","enum":["dpan","mpan","pan"]},"WalletType":{"type":"string","description":"The digital wallet from which the card request originated.","enum":["apple_pay","google_pay"]},"CardAttributeAliases":{"type":"object","properties":{"pan_alias":{"type":"string","title":"PAN Alias","description":"The PAN alias is a reference identifier that stores or securely holds the actual PAN value.\n"},"cvc_alias":{"type":"string","maxLength":35,"minLength":30,"title":"CVC Alias","description":"The CVC Alias is a reference identifier that stores or securely holds the actual CVC value.\n"}}},"EnrichedCardAttributes":{"type":"object","description":"Enriched card attributes from the card-attributes service","properties":{"card_properties":{"type":"object","properties":{"card_number_length":{"type":"integer","description":"The length of the Primary Account Number (PAN) printed on the front of the card. Available only for Card Attributes service subscribers.\n"},"card_segment_type":{"type":"string","description":"Indicator of Business, Consumer, Commercial, Government BINs. Available only for Card Attributes service subscribers."},"virtual_card":{"type":"boolean","description":"Indicates if the given BIN range supports virtual card creation. Available only for Card Attributes service subscribers.\n"},"prepaid_card":{"type":"boolean","description":"Indicates a fixed funding source for a card but not necessarily associated with the consumer's checking account. Available only for Card Attributes service subscribers.\n"},"product_name":{"type":"string","description":"The card product name according to the card brand (e.g., Visa Signature, Visa Infinite, Visa Classic). Available only for Card Attributes service subscribers.\n"},"issuer_bin":{"type":"string","description":"Bank Identification Number (BIN) of the issuer of the account. Available only for Card Attributes service subscribers."},"country_letter_code":{"type":"string","description":"ISO country letters that is associated with an ISO 3166-1 alpha-2 code."},"country_name":{"type":"string","description":"Name of the issuing country. Available only for Card Attributes service subscribers."},"country_numeric":{"type":"integer","description":"ISO 3166 numeric country code of the issuing country. Available only for Card Attributes service subscribers."}}},"card_capabilities":{"type":"object","properties":{"reloadable":{"type":"boolean","description":"Indicator of reloadable or non-reloadable prepaid. Available only for Card Attributes service subscribers."},"hsa":{"type":"boolean","description":"Indicates a card attached to a Health Savings Account. Available only for Card Attributes service subscribers."},"fsa":{"type":"boolean","description":"Indicates a card attached to Flexible Spending Account. Available only for Card Attributes service subscribers."},"ebt":{"type":"boolean","description":"Indicates the BIN has Electronic Benefits Transfer (EBT) capabilities. Available only for Card Attributes service subscribers."},"commercial_level2":{"type":"boolean","description":"Indicates the card supports Level 2 commercial data. Available only for Card Attributes service subscribers."},"commercial_level3":{"type":"boolean","description":"Indicates the card supports Level 3 commercial data. Available only for Card Attributes service subscribers."}}},"bank":{"type":"object","properties":{"issuer_name":{"type":"string","description":"Name of the issuing organization/bank."},"issuer_phone_number":{"type":"string","description":"Phone number of the issuing organization/bank. Available only for Card Attributes service subscribers."},"issuer_website":{"type":"string","description":"Website of the issuing organization/bank. Available only for Card Attributes service subscribers."}}},"additional_card_brands":{"type":"array","description":"Additional card brands, if any, associated with the card. Available only for Card Attributes service subscribers.","items":{"type":"object","required":["card_brand"],"properties":{"card_brand":{"type":"string","description":"The name of the additional card brand. Available only for Card Attributes service subscribers."}}}},"interchange":{"type":"object","properties":{"regulated":{"type":"string","description":"Indicator of the presence of an interchange regulation on a BIN. Available only for Card Attributes service subscribers."}}}}},"EnrollmentSource":{"type":"string","description":"Indicates whether the card was loaded from an existing backbook portfolio\nor newly tokenized. Set by the server based on the `processing` query\nparameter at card creation time and is read-only.\n","enum":["backbook","frontbook"]},"CardResourceMetadata":{"type":"object","description":"Non-standard meta-information about the card resource."},"IncludedResource":{"allOf":[{"$ref":"#/components/schemas/BaseIncludedResource"},{"oneOf":[{"$ref":"#/components/schemas/CardUpdateResource"},{"$ref":"#/components/schemas/CardUpdateSubscriptionResource"},{"$ref":"#/components/schemas/NetworkTokenResource"}]}],"discriminator":{"propertyName":"type","mapping":{"card_updates":"#/components/schemas/CardUpdateResource","card_update_subscriptions":"#/components/schemas/CardUpdateSubscriptionResource","network_tokens":"#/components/schemas/NetworkTokenResource"}}},"BaseIncludedResource":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/IncludedResourceType"}}},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"CardUpdateResource":{"type":"object","description":"An event representing an update from the card network pertaining to the related card and card update subscription.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"occurred_at":{"type":"string","format":"datetime"},"reason_code":{"type":"string"},"reason_text":{"type":"string"},"changed_fields":{"type":"array","items":{"type":"string"}},"updated_values":{"type":"array","title":"CardUpdateResourceUpdatedValues","items":{"$ref":"#/components/schemas/UpdatedCardFieldResource"}},"event":{"type":"string","enum":["updated","expired","closed","non-participating","contact-cardholder-advice","unknown","enrolled","enrollment-failed","opt-out"],"description":"- updated - **Account number change message**: This event is triggered when a cardholder opens a new account with a participating issuer or when a new card is issued. For e.g. this could be due to new account creation, lost or stolen card, or when a card holder gets upgraded to Platinum or downgraded, or, due to a portfolio change (one bank to another).\n- expired - **Expiration date change** This event denotes an expiration date change event. Whenever the card expires but has the same PAN, then, a new expiration date is issued. This event is an indication that the card expired (and so a new date is issued). Typically, cards have an expiration date of 2, 3 or x years (it used to be 5 but we rarely see them these days). Sometimes, an issuer can have an expiration for 1 year (for brand new card holders as they do not have enough credit).\n- closed - **Closed account advice** This event is triggered when the issuer reports the closure of the cardholder's account i.e. cardholder's account associated with the particular card is no longer active/closed providing an important update for merchants to keep their records accurate and avoid attempting transactions with invalid or closed accounts.\n- non-participating - **Non-participating BIN** This event represents a non-participating BIN event, indicating that cards linked to these BINs will not receive updates through the account updater service. i.e. BIN of a particular card is not participating in the account updater service and merchants subscribed to account updater will not receive updates for cards associated with non-participating BINs.\n- contact-cardholder-advice - **Contact cardholder advice** This event indicates the issuer is letting the merchant know that something has changed and the merchant should force the customer to key enter the credential and the update will not be shared via the account updater channel for the merchant. In short the merchant must contact the cardholder for more information or clarification.\n- unknown - **Account not found response from a participating BIN** This event indicates that the card is eligible for automatic updates, but no match was found for this account.\n- enrolled - This event is triggered when a card is successfully enrolled in account updater or when the network confirms that the card status remains unchanged. **Successfully enrolled** - The card is successfully enrolled for updates from the networks. **Match made, account number and expiration date unchanged** - This event implies that the card is already enrolled for account updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.\n- enrollment-failed - This event is triggered when a card was unsuccessfully enrolled in account updater.\n- opt-out - **Cardholder Opt-Out Note** (Stop Advice) is placed on a card.\n"},"received_at":{"type":"string","format":"datetime","description":"Timestamp of when the event was received from the network."}},"required":["received_at","occurred_at","event","changed_fields","updated_values"],"title":"CardUpdateResourceAttributes"}},"additionalProperties":false},"UpdatedCardFieldResource":{"type":"object","title":"UpdatedCardFieldResource","properties":{"field_name":{"type":"string"},"old_value":{"type":"string"},"new_value":{"type":"string"}},"required":["field_name","old_value","new_value"]},"CardUpdateSubscriptionResource":{"type":"object","description":"An object representing a card account updater subscription. A card update subscription receives updates from the card network when the card is renewed or replaced.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"bin":{"type":"string","format":"\\d{6,10}","description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"created_at":{"type":"string","format":"date-time"},"state":{"type":"string","enum":["enrolled","failed"],"description":"State of the card update subscription."},"updated_at":{"type":"string","format":"date-time"}}}}},"NetworkTokenResource":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"$ref":"#/components/schemas/NetworkTokenAttributes"},"meta":{"type":"object","title":"meta","description":"Information about the card meta, including card art","properties":{"card_art":{"$ref":"#/components/schemas/CardArt","description":"Card art\n"}}},"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"additionalProperties":false,"type":"object","required":["id","type"],"title":"NetworkTokenResource"},"NetworkTokenAttributes":{"type":"object","properties":{"payment_account_reference":{"type":"string","title":"Payment Account Reference"},"network_token":{"type":"string","title":"The network token PAN","minLength":13,"maxLength":19},"last4":{"type":"string","title":"Network Token Last4","maxLength":4},"bin":{"type":"string","title":"Network Token Bin","minLength":6,"maxLength":10},"exp_month":{"type":"integer","title":"Expiration Month","minimum":1,"maximum":12},"exp_year":{"type":"integer","title":"Expiration Year","minimum":0,"maximum":99},"created_at":{"type":"string","title":"Created At","format":"date-time"},"updated_at":{"type":"string","title":"Updated At","format":"date-time"},"state":{"type":"string","title":"State"},"reason_code":{"type":"string"},"reason_text":{"type":"string"}},"required":["payment_account_reference","network_token","last4","bin","exp_month","exp_year","created_at","updated_at","state"],"title":"NetworkTokenSchema"},"CardArt":{"type":"object","description":"Card art","properties":{"background_color":{"type":"string","description":"Background color of card art"},"foreground_color":{"type":"string","description":"Foreground color of card art"},"label_color":{"type":"string","description":"Label color of card art"},"issuer_name":{"type":"string","description":"Issuer of the card"},"contact_website":{"type":"string","description":"Contact website of the card"},"contact_number":{"type":"string","description":"Contact phone number of the card"},"contact_name":{"type":"string","description":"Contact name of the card"},"short_description":{"type":"string","description":"Short description of the card"},"long_description":{"type":"string","description":"Long description of the card"},"assets":{"type":"array","items":{"$ref":"#/components/schemas/CardAsset"}}}},"CardAsset":{"type":"object","description":"Card asset","required":["type","download_url"],"properties":{"type":{"type":"string","description":"Type of card asset","enum":["CARD_SYMBOL","DIGITAL_CARD_ART","DIGITAL_CARD_ART_BACKGROUND"]},"mime_type":{"type":"string","description":"MIME type of the file"},"width":{"type":"integer","description":"Width of the image in pixel"},"height":{"type":"integer","description":"Height of the image in pixel"},"download_url":{"type":"string","description":"URL for downloading the image"}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}":{"patch":{"tags":["Cards"],"summary":"Update a Card","description":"The Update Card API enables clients to modify specific fields on a card using its unique Card ID. The update endpoint only updates the card object; it does not automatically trigger any secondary services or processes. The endpoint response provides a comprehensive snapshot of the card object and its current relationships within CMP.\n","operationId":"update_card_by_id","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card ID"}}],"requestBody":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardUpdateResourceRequest"}}}},"responses":{"200":{"description":"Updated card","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


# Account Updater

## Subscribe

> To begin receiving automated updates for a card, it must be enrolled in account updater using the \*\*Subscribe\*\* operation. This API enables continuous tracking of card status with the issuing network. If the card is already subscribed, the system will automatically skip re-enrollment.\
> Subscribing ensures that your application will receive updates on card replacements, expiration changes, and other important lifecycle events, keeping your records accurate without customer input.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Account Updater"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardUpdateSubscriptionResourceResponse":{"title":"CardUpdateSubscriptionResourceResponse","type":"object","properties":{"data":{"$ref":"#/components/schemas/CardUpdateSubscriptionResource"}},"additionalProperties":false,"required":["data"]},"CardUpdateSubscriptionResource":{"type":"object","description":"An object representing a card account updater subscription. A card update subscription receives updates from the card network when the card is renewed or replaced.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"bin":{"type":"string","format":"\\d{6,10}","description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"created_at":{"type":"string","format":"date-time"},"state":{"type":"string","enum":["enrolled","failed"],"description":"State of the card update subscription."},"updated_at":{"type":"string","format":"date-time"}}}}},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/card-update-subscriptions":{"post":{"tags":["Account Updater"],"summary":"Subscribe","description":"To begin receiving automated updates for a card, it must be enrolled in account updater using the **Subscribe** operation. This API enables continuous tracking of card status with the issuing network. If the card is already subscribed, the system will automatically skip re-enrollment.\nSubscribing ensures that your application will receive updates on card replacements, expiration changes, and other important lifecycle events, keeping your records accurate without customer input.\n","operationId":"subscribe_card_for_au","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"200":{"description":"Card subscription details","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardUpdateSubscriptionResourceResponse"}}}},"201":{"description":"Card subscription details","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardUpdateSubscriptionResourceResponse"}}}},"400":{"description":"The request was invalid.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Valid credentials were provided, but they do not permit access to this resource.","content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Unsubscribe

> When a card is no longer needed for Account Update tracking, you can unsubscribe it from account updater using a DELETE call to the Card API. This removes account updater tracking from the specified card, and the system will no longer request or deliver updates for it.\
> After unsubscription:\
> &#x20; \- The account updater object is removed from the card’s metadata.\
> &#x20; \- No future updates will be received for this card.\
> &#x20; \- The card is considered unenrolled from account updater in the CMP system.\
> This is useful when cards are retired, no longer relevant for recurring billing, or should be managed manually.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Account Updater"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/card-update-subscriptions":{"delete":{"tags":["Account Updater"],"summary":"Unsubscribe","description":"When a card is no longer needed for Account Update tracking, you can unsubscribe it from account updater using a DELETE call to the Card API. This removes account updater tracking from the specified card, and the system will no longer request or deliver updates for it.\nAfter unsubscription:\n  - The account updater object is removed from the card’s metadata.\n  - No future updates will be received for this card.\n  - The card is considered unenrolled from account updater in the CMP system.\nThis is useful when cards are retired, no longer relevant for recurring billing, or should be managed manually.\n","operationId":"unsubscribe_card_by_id","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"204":{"description":"Card unsubscribed"},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"424":{"description":"Underlying service experiences high load","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## On-Demand updates

> The On-Demand Card Updates API offers a stateless, real-time way to check for the latest card information without enrolling the card in account updater. This feature supports Visa and Mastercard only and is ideal for one-time update lookups.\
> For American Express (AMEX) and Discover, updates are only available for cards that have already been enrolled in account updater via VGS. This API is useful for verifying card updates without committing to long-term account updater tracking. It returns the most current data available at the time of the request, helping businesses make decisions in real time without the overhead of subscription.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Account Updater"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardCheckResourceResponse":{"title":"CardCheckResourceResponse","type":"object","properties":{"data":{"$ref":"#/components/schemas/CardUpdateResource"},"metadata":{"$ref":"#/components/schemas/MetadataResponse"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"additionalProperties":false,"required":["data"]},"CardUpdateResource":{"type":"object","description":"An event representing an update from the card network pertaining to the related card and card update subscription.","properties":{"id":{"type":"string","description":"ID of card update subcription."},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"type":"object","properties":{"occurred_at":{"type":"string","format":"datetime"},"reason_code":{"type":"string"},"reason_text":{"type":"string"},"changed_fields":{"type":"array","items":{"type":"string"}},"updated_values":{"type":"array","title":"CardUpdateResourceUpdatedValues","items":{"$ref":"#/components/schemas/UpdatedCardFieldResource"}},"event":{"type":"string","enum":["updated","expired","closed","non-participating","contact-cardholder-advice","unknown","enrolled","enrollment-failed","opt-out"],"description":"- updated - **Account number change message**: This event is triggered when a cardholder opens a new account with a participating issuer or when a new card is issued. For e.g. this could be due to new account creation, lost or stolen card, or when a card holder gets upgraded to Platinum or downgraded, or, due to a portfolio change (one bank to another).\n- expired - **Expiration date change** This event denotes an expiration date change event. Whenever the card expires but has the same PAN, then, a new expiration date is issued. This event is an indication that the card expired (and so a new date is issued). Typically, cards have an expiration date of 2, 3 or x years (it used to be 5 but we rarely see them these days). Sometimes, an issuer can have an expiration for 1 year (for brand new card holders as they do not have enough credit).\n- closed - **Closed account advice** This event is triggered when the issuer reports the closure of the cardholder's account i.e. cardholder's account associated with the particular card is no longer active/closed providing an important update for merchants to keep their records accurate and avoid attempting transactions with invalid or closed accounts.\n- non-participating - **Non-participating BIN** This event represents a non-participating BIN event, indicating that cards linked to these BINs will not receive updates through the account updater service. i.e. BIN of a particular card is not participating in the account updater service and merchants subscribed to account updater will not receive updates for cards associated with non-participating BINs.\n- contact-cardholder-advice - **Contact cardholder advice** This event indicates the issuer is letting the merchant know that something has changed and the merchant should force the customer to key enter the credential and the update will not be shared via the account updater channel for the merchant. In short the merchant must contact the cardholder for more information or clarification.\n- unknown - **Account not found response from a participating BIN** This event indicates that the card is eligible for automatic updates, but no match was found for this account.\n- enrolled - This event is triggered when a card is successfully enrolled in account updater or when the network confirms that the card status remains unchanged. **Successfully enrolled** - The card is successfully enrolled for updates from the networks. **Match made, account number and expiration date unchanged** - This event implies that the card is already enrolled for account updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.\n- enrollment-failed - This event is triggered when a card was unsuccessfully enrolled in account updater.\n- opt-out - **Cardholder Opt-Out Note** (Stop Advice) is placed on a card.\n"},"received_at":{"type":"string","format":"datetime","description":"Timestamp of when the event was received from the network."}},"required":["received_at","occurred_at","event","changed_fields","updated_values"],"title":"CardUpdateResourceAttributes"}},"additionalProperties":false},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"UpdatedCardFieldResource":{"type":"object","title":"UpdatedCardFieldResource","properties":{"field_name":{"type":"string"},"old_value":{"type":"string"},"new_value":{"type":"string"}},"required":["field_name","old_value","new_value"]},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/check":{"post":{"tags":["Account Updater"],"summary":"On-Demand updates","description":"The On-Demand Card Updates API offers a stateless, real-time way to check for the latest card information without enrolling the card in account updater. This feature supports Visa and Mastercard only and is ideal for one-time update lookups.\nFor American Express (AMEX) and Discover, updates are only available for cards that have already been enrolled in account updater via VGS. This API is useful for verifying card updates without committing to long-term account updater tracking. It returns the most current data available at the time of the request, helping businesses make decisions in real time without the overhead of subscription.\n","operationId":"check_card_for_updates","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"200":{"description":"Card updates","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardCheckResourceResponse"}}}},"400":{"description":"The request was invalid.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"description":"Valid credentials were provided, but they do not permit access to this resource.","content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"424":{"description":"Underlying service experiences high load","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


# Network Tokens

## Provision

> When Network Tokens are enabled for an account, VGS automatically provisions a token for each card stored. This provisioned token is mapped to the Card ID and kept in sync with the card’s network lifecycle.\
> As the card is updated or reissued, network token metadata is refreshed, enabling businesses to maintain valid and up-to-date payment credentials with no extra effort. Provisioning Network Tokens offers merchants a future-proof, secure foundation for handling customer payments. The provisioning is skipped if there is an active network token already exists for the card. This provisioning process is applicable regardless of the network token type - Card on File or Ecommerce Network Token.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Network Tokens"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NetworkTokenResourceResponse":{"title":"NetworkTokenResourceResponse","type":"object","properties":{"data":{"$ref":"#/components/schemas/NetworkTokenResource"}},"additionalProperties":false,"required":["data"]},"NetworkTokenResource":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"$ref":"#/components/schemas/IncludedResourceType"},"attributes":{"$ref":"#/components/schemas/NetworkTokenAttributes"},"meta":{"type":"object","title":"meta","description":"Information about the card meta, including card art","properties":{"card_art":{"$ref":"#/components/schemas/CardArt","description":"Card art\n"}}},"relationships":{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object","title":"Relationships","description":"Information about other services or capabilities that are related to this network token.\n"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"}},"additionalProperties":false,"type":"object","required":["id","type"],"title":"NetworkTokenResource"},"IncludedResourceType":{"type":"string","enum":["card_updates","card_update_subscriptions","network_tokens"]},"NetworkTokenAttributes":{"type":"object","properties":{"payment_account_reference":{"type":"string","title":"Payment Account Reference"},"network_token":{"type":"string","title":"The network token PAN","minLength":13,"maxLength":19},"last4":{"type":"string","title":"Network Token Last4","maxLength":4},"bin":{"type":"string","title":"Network Token Bin","minLength":6,"maxLength":10},"exp_month":{"type":"integer","title":"Expiration Month","minimum":1,"maximum":12},"exp_year":{"type":"integer","title":"Expiration Year","minimum":0,"maximum":99},"created_at":{"type":"string","title":"Created At","format":"date-time"},"updated_at":{"type":"string","title":"Updated At","format":"date-time"},"state":{"type":"string","title":"State"},"reason_code":{"type":"string"},"reason_text":{"type":"string"}},"required":["payment_account_reference","network_token","last4","bin","exp_month","exp_year","created_at","updated_at","state"],"title":"NetworkTokenSchema"},"CardArt":{"type":"object","description":"Card art","properties":{"background_color":{"type":"string","description":"Background color of card art"},"foreground_color":{"type":"string","description":"Foreground color of card art"},"label_color":{"type":"string","description":"Label color of card art"},"issuer_name":{"type":"string","description":"Issuer of the card"},"contact_website":{"type":"string","description":"Contact website of the card"},"contact_number":{"type":"string","description":"Contact phone number of the card"},"contact_name":{"type":"string","description":"Contact name of the card"},"short_description":{"type":"string","description":"Short description of the card"},"long_description":{"type":"string","description":"Long description of the card"},"assets":{"type":"array","items":{"$ref":"#/components/schemas/CardAsset"}}}},"CardAsset":{"type":"object","description":"Card asset","required":["type","download_url"],"properties":{"type":{"type":"string","description":"Type of card asset","enum":["CARD_SYMBOL","DIGITAL_CARD_ART","DIGITAL_CARD_ART_BACKGROUND"]},"mime_type":{"type":"string","description":"MIME type of the file"},"width":{"type":"integer","description":"Width of the image in pixel"},"height":{"type":"integer","description":"Height of the image in pixel"},"download_url":{"type":"string","description":"URL for downloading the image"}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/network-tokens":{"post":{"tags":["Network Tokens"],"summary":"Provision","description":"When Network Tokens are enabled for an account, VGS automatically provisions a token for each card stored. This provisioned token is mapped to the Card ID and kept in sync with the card’s network lifecycle.\nAs the card is updated or reissued, network token metadata is refreshed, enabling businesses to maintain valid and up-to-date payment credentials with no extra effort. Provisioning Network Tokens offers merchants a future-proof, secure foundation for handling customer payments. The provisioning is skipped if there is an active network token already exists for the card. This provisioning process is applicable regardless of the network token type - Card on File or Ecommerce Network Token.\n","operationId":"provision_nt_for_card","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"200":{"description":"Card's network token","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/NetworkTokenResourceResponse"}}}},"201":{"description":"Card's network token","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/NetworkTokenResourceResponse"}}}},"400":{"description":"The request was invalid.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"description":"Valid credentials were provided, but they do not permit access to this resource.","content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Delete

> The Delete Network Token operation allows you to deactivate a previously provisioned network token on the card.\
> Once deleted -\
> &#x20; \- The Network Token becomes invalid and stops receiving updates.\
> &#x20; \- The card’s network token data is removed from the CMP system.\
> &#x20; \- Network Token-based operations like cryptogram generation (e.g., POST /cards/{CardID}/cryptogram) are no longer allowed.\
> This is typically done when the card is no longer in use, has been removed from the system, or must be de-tokenized for compliance reasons. When deleted, the Network Token is excluded from the card response object and becomes non-functional for payments.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Network Tokens"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/network-tokens":{"delete":{"tags":["Network Tokens"],"summary":"Delete","description":"The Delete Network Token operation allows you to deactivate a previously provisioned network token on the card.\nOnce deleted -\n  - The Network Token becomes invalid and stops receiving updates.\n  - The card’s network token data is removed from the CMP system.\n  - Network Token-based operations like cryptogram generation (e.g., POST /cards/{CardID}/cryptogram) are no longer allowed.\nThis is typically done when the card is no longer in use, has been removed from the system, or must be de-tokenized for compliance reasons. When deleted, the Network Token is excluded from the card response object and becomes non-functional for payments.\n","operationId":"delete_network_token_by_card_id","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"204":{"description":"Network token deleted"},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Request cryptogram

> Fetch Cryptogram by Card ID

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Network Tokens"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CryptoFetchRequest":{"type":"object","properties":{"data":{"type":"object","description":"The crypto fetch information.","properties":{"attributes":{"$ref":"#/components/schemas/CryptoFetchAttributes"}},"required":["attributes"]}},"additionalProperties":false,"required":["data"]},"CryptoFetchAttributes":{"type":"object","properties":{"currency_code":{"maxLength":3,"type":"string","description":"ISO 4217 alpha 3 currency code for the transaction","default":"USD"},"amount":{"type":"number","multipleOf":0.01,"format":"double","description":"Transaction amount","minimum":0},"transaction_type":{"type":"string","enum":["ECOM","AFT"],"default":"ECOM","description":"Transaction type (defaults ECOM).\n\n- ECOM - refers to an e-commerce transaction (online purchase)\n- AFT - stands for Account Funding Transaction (pulling funds from a card to another account). AFT is currently supported for Visa only.\n"},"cryptogram_type":{"type":"string","enum":["TAVV","DTVV"],"default":"TAVV","description":"Cryptogram type (defaults to TAVV)\n\nTAVV (Token Authentication Verification Value) and DTVV (Dynamic Token Verification Value) are cryptograms used to authenticate transactions and prevent fraud.\n\nCustomers can initiate transactions using VGS Network Tokens by generating a unique cryptogram.\n\n* TAVV: This cryptogram is specific to the network token and can be up to 32 characters long. When submitting transactions, networks may require merchants to specify the transaction type explicitly during cryptogram generation.\n* DTVV: Unlike TAVV, DTVV is a 3-characters long cryptogram that is currently supported only for Visa Network Tokens which can increase compatibility with some PSPs. To use DTVV, VGS must be enabled on a case-by-case basis. Merchants interested in enabling DTVV can reach out to support@verygoodsecurity.com for assistance.\n\nTo avoid declines, merchants and acquirers must ensure that:\n- TAVV and DTVV are new and unique for each authorization request\n- TAVV and DTVV are one-time use and not stored beyond the authorization request\n- The TAVV, DTVV, and electronic commerce indicator values provided by the token requester are unchanged when submitted for an authorization request\n"}}},"NetworkTokenAndCryptogramResource":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","enum":["network_tokens"]},"attributes":{"allOf":[{"type":"object","properties":{"cryptogram":{"$ref":"#/components/schemas/CryptogramAttributes"}}},{"$ref":"#/components/schemas/NetworkTokenAttributes"}]}}},"metadata":{"$ref":"#/components/schemas/MetadataResponse"}}},"CryptogramAttributes":{"type":"object","properties":{"type":{"type":"string","enum":["TAVV","DTVV"],"description":"Cryptogram type (defaults to TAVV)\n\nTAVV (Token Authentication Verification Value) and DTVV (Dynamic Token Verification Value) are cryptograms used to authenticate transactions and prevent fraud.\n\nCustomers can initiate transactions using VGS Network Tokens by generating a unique cryptogram.\n\n* TAVV: This cryptogram is specific to the network token and can be up to 32 characters long. When submitting transactions, networks may require merchants to specify the transaction type explicitly during cryptogram generation.\n* DTVV: Unlike TAVV, DTVV is a 3-characters long cryptogram that is currently supported only for Visa Network Tokens which can increase compatibility with some PSPs. To use DTVV, VGS must be enabled on a case-by-case basis. Merchants interested in enabling DTVV can reach out to support@verygoodsecurity.com for assistance.\n\nTo avoid declines, merchants and acquirers must ensure that:\n- TAVV and DTVV are new and unique for each authorization request\n- TAVV and DTVV are one-time use and not stored beyond the authorization request\n- The TAVV, DTVV, and electronic commerce indicator values provided by the token requester are unchanged when submitted for an authorization request\n"},"value":{"type":"string"},"eci":{"type":"string","description":"An Electronic Commerce Indicator (ECI) is a code that indicates the type of electronic transaction and the result of authentication for a payment.\n"}}},"NetworkTokenAttributes":{"type":"object","properties":{"payment_account_reference":{"type":"string","title":"Payment Account Reference"},"network_token":{"type":"string","title":"The network token PAN","minLength":13,"maxLength":19},"last4":{"type":"string","title":"Network Token Last4","maxLength":4},"bin":{"type":"string","title":"Network Token Bin","minLength":6,"maxLength":10},"exp_month":{"type":"integer","title":"Expiration Month","minimum":1,"maximum":12},"exp_year":{"type":"integer","title":"Expiration Year","minimum":0,"maximum":99},"created_at":{"type":"string","title":"Created At","format":"date-time"},"updated_at":{"type":"string","title":"Updated At","format":"date-time"},"state":{"type":"string","title":"State"},"reason_code":{"type":"string"},"reason_text":{"type":"string"}},"required":["payment_account_reference","network_token","last4","bin","exp_month","exp_year","created_at","updated_at","state"],"title":"NetworkTokenSchema"},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/cryptogram":{"post":{"tags":["Network Tokens"],"summary":"Request cryptogram","description":"Fetch Cryptogram by Card ID","operationId":"fetch-cryptogram","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"requestBody":{"required":false,"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CryptoFetchRequest"}}}},"responses":{"200":{"description":"Successful cryptogram fetch response","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/NetworkTokenAndCryptogramResource"}}}},"400":{"description":"The request was invalid.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"424":{"description":"Network Token Not Provisioned or Not Active","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"There was a failure in fetching the cryptogram, possibly due to external service issues or network failures\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


# Account Updater Events

{% openapi-webhook spec="card-management-api" name="account-updater-webhooks" method="post" %}
[card-management-api](https://4401d86825a13bf607936cc3a9f3897a.r2.cloudflarestorage.com/gitbook-x-prod-openapi/raw/833d2464716fa5da708fac399110f2cc8577362128000061ab970b36a03b925d.yaml?X-Amz-Algorithm=AWS4-HMAC-SHA256\&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD\&X-Amz-Credential=dce48141f43c0191a2ad043a6888781c%2F20260717%2Fauto%2Fs3%2Faws4_request\&X-Amz-Date=20260717T005302Z\&X-Amz-Expires=172800\&X-Amz-Signature=a5abc0d7c7773320338df038f64321148d2f875d400383278d70b8a0e5ba0a23\&X-Amz-SignedHeaders=host\&x-amz-checksum-mode=ENABLED\&x-id=GetObject)
{% endopenapi-webhook %}


# Network Token Events

{% openapi-webhook spec="card-management-api" name="network-tokens-webhooks" method="post" %}
[card-management-api](https://4401d86825a13bf607936cc3a9f3897a.r2.cloudflarestorage.com/gitbook-x-prod-openapi/raw/833d2464716fa5da708fac399110f2cc8577362128000061ab970b36a03b925d.yaml?X-Amz-Algorithm=AWS4-HMAC-SHA256\&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD\&X-Amz-Credential=dce48141f43c0191a2ad043a6888781c%2F20260717%2Fauto%2Fs3%2Faws4_request\&X-Amz-Date=20260717T005301Z\&X-Amz-Expires=172800\&X-Amz-Signature=bd1174b2680093a9c15f4d7ab9df698bd4117dc6a5e291f7853c89c2414c5486\&X-Amz-SignedHeaders=host\&x-amz-checksum-mode=ENABLED\&x-id=GetObject)
{% endopenapi-webhook %}


# Account Validation

Performs one or more validation checks for a given card, such as CVC, AVS, and cardholder name, in a synchronous (blocking) request. The presence of validation data in the request body implicitly specifies which checks are performed.

## Perform account validation checks

> Performs one or more validation checks for a given card, such as CVC, AVS, and cardholder name, in a synchronous (blocking) request. The presence of validation data in the request body implicitly specifies which checks are performed.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Account Validation","description":"Performs one or more validation checks for a given card, such as CVC, AVS, and cardholder name, in a synchronous (blocking) request. The presence of validation data in the request body implicitly specifies which checks are performed."}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":["account-validations:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"parameters":{"auth-header":{"in":"header","name":"Authorization","description":"Bearer token for authentication.","schema":{"type":"string"},"required":true},"content-type":{"in":"header","name":"Content-Type","description":"Content type of a request to CMP","schema":{"type":"string","enum":["application/vnd.api+json"]},"required":true}},"schemas":{"AccountValidationRequest":{"type":"object","description":"The request body to initiate account validations. A card verification is always performed; the presence of `cvc`, `cardholder_address`, or `cardholder_name` additionally requests the corresponding optional check (CVC, AVS, name match).","required":["data"],"properties":{"data":{"type":"object","required":["attributes"],"properties":{"type":{"type":"string","description":"The resource type.","enum":["account-validations"]},"attributes":{"type":"object","description":"Validation inputs. A card verification auth is always performed; including `cvc`, `cardholder_address`, or `cardholder_name` additionally requests that optional check.","required":["merchant"],"properties":{"cvc":{"type":"string","description":"The 3-4 digit Card Verification Code (CVC). If present, CVC validation is performed.","minLength":3,"maxLength":4},"cardholder_address":{"type":"object","description":"Cardholder billing address. If present, address validation (AVS) is performed. `postal_code` is required; `street` is optional.","required":["postal_code"],"properties":{"street":{"type":"string","description":"Street address line."},"postal_code":{"type":"string","description":"Postal/ZIP code.","minLength":1}}},"cardholder_name":{"type":"object","description":"Cardholder name. If present, name validation is performed.","properties":{"first_name":{"type":"string","description":"Cardholder first name."},"middle_name":{"type":"string","description":"Cardholder middle name or initial."},"last_name":{"type":"string","description":"Cardholder last name."}}},"merchant":{"type":"object","description":"Merchant associated with the validation.","required":["merchant_name","address"],"properties":{"merchant_name":{"type":"string","description":"Merchant name."},"address":{"type":"object","description":"Merchant address.","required":["city","state","country","postal_code"],"properties":{"city":{"type":"string","description":"City name."},"state":{"type":"string","description":"State or region code."},"country":{"type":"string","description":"ISO 3166-1 alpha-2 country code.","minLength":2,"maxLength":2},"postal_code":{"type":"string","description":"Postal/ZIP code."}}}}}}}}}}},"AccountValidationResponse":{"type":"object","description":"The response body for a successful synchronous validation.","required":["data"],"properties":{"data":{"type":"object","required":["id","type","attributes"],"properties":{"id":{"type":"string","description":"A unique identifier for this validation batch."},"type":{"type":"string","description":"The resource type.","enum":["account-validation-results"]},"attributes":{"type":"object","required":["attempted_at","card_verification_status"],"properties":{"transaction_identifier":{"type":"string","description":"Network-issued transaction identifier for the card verification batch. Absent when the network did not return one."},"attempted_at":{"type":"string","format":"date-time","description":"Timestamp when the validation was performed."},"card_verification_status":{"type":"string","enum":["verified","not_verified"],"description":"Outcome of the card verification, derived from the network response code. `verified` when the network confirmed the account; `not_verified` otherwise (and the default when the network response is missing or not in the recognized set)."},"validation_results":{"type":"array","description":"Results for each optional validation performed (CVC, address, name). `null` when no optional validations are requested. Order is not guaranteed.","items":{"$ref":"#/components/schemas/ValidationResult"}}}},"relationships":{"type":"object","description":"Links to related resources.","properties":{"card":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["cards"]},"id":{"type":"string","description":"The card ID for which validations were performed."}}}}}}},"links":{"type":"object","description":"Links related to this resource.","properties":{"self":{"type":"string","format":"uri","description":"Link to this validation result."}}}}},"meta":{"$ref":"#/components/schemas/MetadataResponse"}}},"ValidationResult":{"type":"object","description":"The result of an optional validation check (CVC, address, or cardholder name).","required":["type","status"],"properties":{"type":{"type":"string","enum":["cvc","address","name"],"description":"Which validation this result is for."},"status":{"type":"string","enum":["match","no_match","partial_match","not_supported","system_unavailable","invalid_data","non_participating"],"description":"Normalized outcome of the validation check, derived from the network response code. The legal subset depends on `type`: CVC uses `match` / `no_match` / `system_unavailable` / `invalid_data` / `non_participating`; name uses `match` / `no_match` / `partial_match`; address uses `match` / `no_match` / `partial_match` / `not_supported`. Default is `no_match`."},"detail":{"type":"object","description":"Per-component breakdown of the validation outcome. Only present when `type` is `address`; absent for `cvc` and `name`.","properties":{"street_address":{"type":"string","enum":["match","no_match"],"description":"Match status for the street address component."},"postal_code":{"type":"string","enum":["match","no_match"],"description":"Match status for the postal code component."}}}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}}},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"}}},"paths":{"/cards/{card_id}/validations":{"post":{"tags":["Account Validation"],"summary":"Perform account validation checks","description":"Performs one or more validation checks for a given card, such as CVC, AVS, and cardholder name, in a synchronous (blocking) request. The presence of validation data in the request body implicitly specifies which checks are performed.\n","operationId":"perform_account_validation","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card ID"}},{"$ref":"#/components/parameters/auth-header"},{"$ref":"#/components/parameters/content-type"}],"requestBody":{"description":"Account validation request payload.","required":true,"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/AccountValidationRequest"}}}},"responses":{"200":{"description":"SUCCESS: The validation was performed and results are in the response body.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/AccountValidationResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"description":"Forbidden. The client does not have permission to perform this action, or the vault context could not be determined from the request.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable. The downstream network is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


# 3D Secure (3DS)

For a fully optimized 3DS flow:

1. Call the *3ds-initialize* endpoint, which may return an iframe for device fingerprinting. If no iframe is returned, initialization isn’t required and authentication can proceed immediately.
2. Render the iframe on the front end as soon as it’s received from VGS. It can also be loaded as an invisible or background frame while the cardholder waits, so the client doesn’t pause for processing.
3. Submit the form contained in the iframe, this will start the device fingerprinting process.
4. Start a 10-second timer after receiving the iframe from VGS, and wait until you either get the asynchronous device fingerprinting response from VGS or the timer expires—-whichever happens first—-before sending the authenticate request to VGS.
5. Call the *3ds-authenticate* endpoint at the time of purchase. It may return the final authentication result synchronously, or it may trigger a user challenge-—in which case the final result will be delivered via the configured webhook notification.

## Initialize 3DS authentication

> Initial call to check if device fingerprinting is needed for subsequent\
> 3DS authentication.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"3D Secure (3DS)","description":"For a fully optimized 3DS flow:\n1. Call the _3ds-initialize_ endpoint, which may return an iframe for device fingerprinting. If no iframe is returned, initialization isn’t required and authentication can proceed immediately.\n2. Render the iframe on the front end as soon as it’s received from VGS. It can also be loaded as an invisible or background frame while the cardholder waits, so the client doesn’t pause for processing.\n3. Submit the form contained in the iframe, this will start the device fingerprinting process.\n4. Start a 10-second timer after receiving the iframe from VGS, and wait until you either get the asynchronous device fingerprinting response from VGS or the timer expires—-whichever happens first—-before sending the authenticate request to VGS.\n5. Call the _3ds-authenticate_ endpoint at the time of purchase. It may return the final authentication result synchronously, or it may trigger a user challenge-—in which case the final result will be delivered via the configured webhook notification.\n"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":["3ds:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"parameters":{"auth-header":{"in":"header","name":"Authorization","description":"Bearer token for authentication.","schema":{"type":"string"},"required":true},"content-type":{"in":"header","name":"Content-Type","description":"Content type of a request to CMP","schema":{"type":"string","enum":["application/vnd.api+json"]},"required":true}},"schemas":{"ThreeDSInitializeRequest":{"type":"object","description":"The request body to initiate 3DS authentication for a card.","required":["data"],"properties":{"data":{"type":"object","properties":{"attributes":{"type":"object","required":["transaction_info"],"properties":{"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoType"},"token_type":{"type":"string","description":"The type of token used. Defaults to PAN if not provided or if a network token isn’t available for the card.","default":"pan","enum":["pan","nt"]}}}}}}},"TransactionInfoType":{"type":"object","description":"Transaction Information for 3DS authentication requests","required":["xid","merchant_transaction_id"],"properties":{"xid":{"type":"string","minLength":28,"maxLength":28,"description":"Unique transaction reference. It can be the same across a series of transactions for a single user or recurring payments. Must be a base64 encoded sequence of 20 bytes."},"merchant_transaction_id":{"type":"string","minLength":1,"maxLength":40,"description":"The merchant_transaction_id is a unique identifier (UUID) assigned to each transaction. Its primary relevance becomes clear in scenarios involving 3RI (Merchant-Initiated Transactions), where merchants need to reference a previously successful transaction using identifiers such as acs_transaction_id and ds_transaction_id. In such cases, while the XID may remain the same across the initial and subsequent 3RI transactions, the merchant_transaction_id must be unique for each transaction.\nFor CIT (Customer-Initiated Transactions), both the XID and merchant_transaction_id can either be the same or different UUIDs — both approaches are acceptable."}}},"ThreeDSInitializeResponse":{"type":"object","description":"The response body for a successful 3DS initialization.","properties":{"data":{"type":"object","properties":{"attributes":{"type":"object","properties":{"card_id":{"type":"string","description":"Unique VGS identifier for the card"},"created_at":{"type":"string","format":"date-time"},"device_fingerprinting_html":{"type":"string","description":"An iframe which will perform device fingerprinting. This HTML content should be added to the front-end as soon as the content is received in the response from VGS. The iframe can be loaded as an invisible/background frame on the client side checkout page before the purchase is submitted so that the client doesn't have to wait for processing."},"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoResponseType"}}}}}}},"TransactionInfoResponseType":{"type":"object","description":"Transaction Information for 3DS authentication requests","properties":{"xid":{"type":"string","description":"Unique transaction reference used across a series of transactions, copied from the request."},"merchant_transaction_id":{"type":"string","description":"The merchant_transaction_id is a unique identifier (UUID) assigned to each transaction. Its primary relevance becomes clear in scenarios involving 3RI (Merchant-Initiated Transactions), where merchants need to reference a previously successful transaction using identifiers such as acs_transaction_id and ds_transaction_id. In such cases, while the XID may remain the same across the initial and subsequent 3RI transactions, the merchant_transaction_id must be unique for each transaction.\nFor CIT (Customer-Initiated Transactions), both the XID and merchant_transaction_id can either be the same or different UUIDs — both approaches are acceptable."},"transaction_id":{"type":"string","description":"A 3DSS/MPI generated ID against each unique authentication transaction"}}},"ThreeDSErrorResponse":{"type":"object","description":"The response body for a failed 3DS request.","properties":{"data":{"type":"object","properties":{"message":{"type":"string","description":"Error received from upstream."},"card_id":{"type":"string","description":"Unique VGS identifier for the card"},"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoType"}}},"meta":{"type":"object","title":"Meta","properties":{"observability":{"type":"object","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}}}}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ErrorForbiddenResponse":{"properties":{"errors":{"items":{"properties":{"status":{"type":"integer","title":"Status"},"details":{"type":"string","title":"Details"},"title":{"type":"string","title":"Title"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorForbiddenResponse"}}},"paths":{"/cards/{card_id}/3ds-initialize":{"post":{"tags":["3D Secure (3DS)"],"summary":"Initialize 3DS authentication","description":"Initial call to check if device fingerprinting is needed for subsequent\n3DS authentication.\n","operationId":"threeds-initialize","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card ID"}},{"$ref":"#/components/parameters/auth-header"},{"$ref":"#/components/parameters/content-type"}],"requestBody":{"description":"3DS initialize request payload","required":true,"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSInitializeRequest"}}}},"responses":{"200":{"description":"Successful initialization","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSInitializeResponse"}}}},"206":{"description":"Request successful. No iframe/data in the response means initialization isn’t needed, and authentication can continue immediately.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSInitializeResponse"}}}},"400":{"description":"Invalid request","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ErrorForbiddenResponse"}]}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"description":"Unprocessable Entity. The request was well-formed but contained semantic errors.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Perform 3DS authentication

> Main call to perform authentication. Required for payment transactions.\
> \
> How the 3DS Challenge Response Fields Are Used\
> When a cardholder needs to complete a challenge during authentication there are two ways to handle the process:\
> \- \*Use the prebuilt HTML form\* (\`challenge\_form\`):\
> &#x20;   This form already contains all necessary elements, including the ACS URL, the CReq data, and the session data.\
> &#x20;   You can return this form directly to the cardholder on your checkout page.\
> &#x20;   It will display the correct UI, including the payment scheme logo and any loading spinners,\
> &#x20;   and will automatically handle localization.\
> \- \*Build your own redirect form using individual fields\*:\
> &#x20;   If you would prefer to generate your own HTML form for the challenge, include the following fields from the response:\
> &#x20;     \- \`challenge\_url\`: The URL to which the cardholder should be redirected for the challenge\
> &#x20;     \- \`challenge\_request\`: The CReq data that must be sent to the ACS, included as a hidden field in the form\
> &#x20;     \- \`challenge\_session\_data\`: Include this as a hidden field if provided. It allows you to track the session and link it back to the specific transaction when the cardholder returns from the ACS.\
> After the cardholder completes the challenge, they will be redirected to your \`redirect\_url\`,\
> and you will receive the final challenge result along with the \`challenge\_session\_data\` so you can reconcile it with the transaction.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"3D Secure (3DS)","description":"For a fully optimized 3DS flow:\n1. Call the _3ds-initialize_ endpoint, which may return an iframe for device fingerprinting. If no iframe is returned, initialization isn’t required and authentication can proceed immediately.\n2. Render the iframe on the front end as soon as it’s received from VGS. It can also be loaded as an invisible or background frame while the cardholder waits, so the client doesn’t pause for processing.\n3. Submit the form contained in the iframe, this will start the device fingerprinting process.\n4. Start a 10-second timer after receiving the iframe from VGS, and wait until you either get the asynchronous device fingerprinting response from VGS or the timer expires—-whichever happens first—-before sending the authenticate request to VGS.\n5. Call the _3ds-authenticate_ endpoint at the time of purchase. It may return the final authentication result synchronously, or it may trigger a user challenge-—in which case the final result will be delivered via the configured webhook notification.\n"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":["3ds:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"parameters":{"accept-header":{"in":"header","name":"Accept","description":"Desired response media types.","required":true,"schema":{"type":"string"}},"accept-language-header":{"in":"header","name":"Accept-Language","description":"Language preference (IETF BCP47).","required":true,"schema":{"type":"string"}},"auth-header":{"in":"header","name":"Authorization","description":"Bearer token for authentication.","schema":{"type":"string"},"required":true},"content-type":{"in":"header","name":"Content-Type","description":"Content type of a request to CMP","schema":{"type":"string","enum":["application/vnd.api+json"]},"required":true}},"schemas":{"ThreeDSAuthenticateRequest":{"type":"object","description":"The request body for 3ds authentication for a card.","required":["data"],"properties":{"data":{"type":"object","properties":{"attributes":{"type":"object","required":["auth_type","browser_info","purchase_info","transaction_info"],"properties":{"token_type":{"type":"string","description":"The type of token used. Defaults to PAN if not provided or if a network token isn’t available for the card.","default":"pan","enum":["pan","nt"]},"auth_type":{"type":"string","description":"The type of 3DS flow requested.","enum":["data-only","challenge"]},"redirect_url":{"type":"string","description":"The URL to redirect the user to once the challenge is completed. **Required** only for challenge flow."},"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoType"},"purchase_info":{"type":"object","description":"Purchase information.","$ref":"#/components/schemas/PurchaseInfoType"},"browser_info":{"type":"object","description":"Browser information.","$ref":"#/components/schemas/BrowserInfoType"},"merchant_info":{"type":"object","description":"Merchant information.","$ref":"#/components/schemas/MerchantInfoType"}}}}}}},"TransactionInfoType":{"type":"object","description":"Transaction Information for 3DS authentication requests","required":["xid","merchant_transaction_id"],"properties":{"xid":{"type":"string","minLength":28,"maxLength":28,"description":"Unique transaction reference. It can be the same across a series of transactions for a single user or recurring payments. Must be a base64 encoded sequence of 20 bytes."},"merchant_transaction_id":{"type":"string","minLength":1,"maxLength":40,"description":"The merchant_transaction_id is a unique identifier (UUID) assigned to each transaction. Its primary relevance becomes clear in scenarios involving 3RI (Merchant-Initiated Transactions), where merchants need to reference a previously successful transaction using identifiers such as acs_transaction_id and ds_transaction_id. In such cases, while the XID may remain the same across the initial and subsequent 3RI transactions, the merchant_transaction_id must be unique for each transaction.\nFor CIT (Customer-Initiated Transactions), both the XID and merchant_transaction_id can either be the same or different UUIDs — both approaches are acceptable."}}},"PurchaseInfoType":{"type":"object","description":"Details about the transaction.","required":["purchase_currency","purchase_amount"],"properties":{"currency_code":{"type":"string","description":"ISO 4217 alpha 3 currency code for the transaction"},"amount":{"type":"number","multipleOf":0.01,"format":"double","description":"Transaction amount"}}},"BrowserInfoType":{"type":"object","description":"Device and browser information. These fields are required for browser-based requests.","required":["java_enabled","javascript_enabled","color_depth","screen_width","screen_height","tz"],"properties":{"java_enabled":{"type":"string","description":"Flag indicating whether the browser has java enabled, must be strings \"true\" or \"false\""},"javascript_enabled":{"type":"string","description":"Flag indicating whether the browser has javascript enabled must be strings \"true\" or \"false\""},"color_depth":{"type":"integer","description":"Bit depth of screen color palette"},"screen_width":{"type":"integer","description":"Screen width in pixels"},"screen_height":{"type":"integer","description":"Screen height in pixels"},"tz":{"type":"integer","description":"Time zone offset in minutes"}}},"MerchantInfoType":{"type":"object","description":"Merchant info for PSP mode auth request","required":["acquirer_bin","acquirer_country_code","acquirer_merchant_id","name","category_code","country_code","website_url"],"properties":{"acquirer_bin":{"type":"string","description":"Acquiring institution identification code (BIN). Numeric, length 1-11. Overrides default profile if present.","minLength":1,"maxLength":11},"acquirer_country_code":{"type":"string","description":"The code of the country where the acquiring institution is located (in accordance with ISO 3166-1 alpha 3-letter country code).","minLength":3,"maxLength":3},"acquirer_requestor_name":{"type":"string","description":"Name of the 3DS Requestor (Merchant). Length 1-40 characters. Required for AMEX/Discover requests.","minLength":1,"maxLength":40},"acquirer_requestor_id":{"type":"string","description":"Unique identifier assigned to the 3DS Requestor by the DS or Scheme. Length 1-35 characters. Required for AMEX/Discover requests.","minLength":1,"maxLength":35},"acquirer_merchant_id":{"type":"string","description":"Acquirer-assigned Merchant Identifier. Length 1-35 characters. Overrides default profile if present.","minLength":1,"maxLength":35},"name":{"type":"string","description":"Merchant Name to be displayed to the cardholder. Length 1-40 characters. Overrides default profile if present.","minLength":1,"maxLength":40},"category_code":{"type":"string","description":"Merchant Category Code (MCC). 4-digit numeric. Overrides default profile if present.","minLength":4,"maxLength":4},"country_code":{"type":"string","description":"Merchant Country Code. ISO 3166-1 alpha 3-letter code. Overrides default profile if present.","minLength":3,"maxLength":3},"website_url":{"type":"string","format":"uri","description":"Fully qualified URL of the 3DS Requestor website or customer care site. Max 2048 characters."}}},"ThreeDSAuthenticateResponse":{"type":"object","description":"*Successful Authentication*: Authentication is considered successful if the response contains one of the following statuses:\n- `APPROVED`: Indicates a successful authentication. The response will include a `cavv` and an `eci` value (typically 05, 06, or 07).\n- For Data-Only flows, `INFORMATIONAL_ONLY` is returned for `Visa` and includes a `cavv` with an `eci` value of \"07\", while `UNABLE_TO_AUTHENTICATE` (unavailable for standard authentication) is returned for `Mastercard` and includes a `cavv` with an `eci` value of \"04\".\n- `CHALLENGE_REQUIRED`: Indicates that the authentication requires user interaction. The response will contain the necessary challenge details (either `challenge_html` or `challenge_form`, `challenge_session_data`, and `challenge_url`).\n\n*Failed Authentication*: Authentication is considered failed if the response contains one of the following statuses:\n- `DENIED`\n- `REJECTED`\n- `ATTEMPTS_PERFORMED`\n- `UNABLE_TO_AUTHENTICATE` (without `cavv`/`eci` in response):\nIn failure cases, the specific reason for the failure will typically be provided in the message field of the response.\n","properties":{"data":{"type":"object","properties":{"attributes":{"type":"object","properties":{"card_id":{"type":"string","description":"Unique VGS identifier for the card"},"created_at":{"type":"string","format":"date-time"},"message":{"type":"string","description":"Human readable description of the response\nVisa:\n- Success: \"Informational response only\"\n- Failure: A message such as \"Authentication Failed\" or an iReqDetail containing \"Visa DAF program not supported by the ACS\"\nMastercard:\n  - Success: A message indicating the outcome of the frictionless response is returned\n  - Failure: \"Authentication Failed\"\nAmex/Discover:\n  - Success: A message indicating an authenticated transaction.\n  - Failure: \"Authentication Failed\"\n"},"status":{"type":"string","description":"The EMV 3DS result code\n- APPROVED\n  - Code: Y\n  - Authentication Successful\n- DENIED\n  - Code: N\n  - Authentication Failed - DAF unsupported\n- UNABLE_TO_AUTHENTICATE\n  - Code: U\n  - Unable to Authenticate\n  - Data Only Transactions (e.g., Mastercard messageCategory=80) → DS does not pass AReq data to the ACS, hence returns transStatus=U.\n  - Card Range Not Updated → If the PAN is not part of the DS’s range, the DS may respond with transStatus=U.\n  - Other Component Non-Communication → If any 3DS component (e.g., DS, ACS) doesn’t communicate with the next in chain, the result may be transStatus=U.\n- ATTEMPTS_PERFORMED\n  - Code: A\n  - Attempts Processing Only - Issuer fallback - Not commonly used\n- REJECTED\n  - Code: R\n  - Authentication Rejected - Rejected by ACS\n- INFORMATIONAL_ONLY\n  Code: I\n  Information-Only\n- CHALLENGE_REQUIRED\n  - Code: C\n  - Challenge Required - Step-up Challenge\n","enum":["APPROVED","DENIED","UNABLE_TO_AUTHENTICATE","ATTEMPTS_PERFORMED","REJECTED","INFORMATIONAL_ONLY","CHALLENGE_REQUIRED"]},"acs_info":{"type":"object","description":"Access Control Server (ACS) information. The auth response may sometimes return an empty acs_info field.","$ref":"#/components/schemas/ACSInfoType"},"cryptogram":{"type":"object","description":"Cryptogram information","$ref":"#/components/schemas/CryptogramType"},"transaction_info":{"type":"object","description":"Transaction information","$ref":"#/components/schemas/TransactionFullInfoResponseType"},"challenge_info":{"type":"object","description":"Challenge information","$ref":"#/components/schemas/ChallengeInfoType"}}}}}}},"ACSInfoType":{"type":"object","description":"Information about the Access Control Server (ACS).","properties":{"acs_reference_number":{"type":"string","description":"A reference number from the ACS for the transaction"},"acs_operator_id":{"type":"string","description":"Unique ACS identifies that is provided by payment scheme for the operator of the service."}}},"CryptogramType":{"type":"object","description":"Cryptogram information","properties":{"eci":{"type":"string","description":"An Electronic Commerce Indicator (ECI) is a code that indicates the type of electronic transaction and the result of authentication for a payment."},"cavv":{"type":"string","description":"Cardholder Authentication Verification Value. Present on successful authentications and must be sent in the authorization."}}},"TransactionFullInfoResponseType":{"type":"object","description":"Transaction Information for 3DS authentication requests","properties":{"xid":{"type":"string","description":"Unique transaction reference used across a series of transactions, copied from the request."},"merchant_transaction_id":{"type":"string","description":"The merchant_transaction_id is a unique identifier (UUID) assigned to each transaction. Its primary relevance becomes clear in scenarios involving 3RI (Merchant-Initiated Transactions), where merchants need to reference a previously successful transaction using identifiers such as acs_transaction_id and ds_transaction_id. In such cases, while the XID may remain the same across the initial and subsequent 3RI transactions, the merchant_transaction_id must be unique for each transaction.\nFor CIT (Customer-Initiated Transactions), both the XID and merchant_transaction_id can either be the same or different UUIDs — both approaches are acceptable."},"transaction_id":{"type":"string","description":"A 3DSS/MPI generated ID against each unique authentication transaction"},"acs_transaction_id":{"type":"string","description":"The transaction ID generated by the Access Control Server (ACS)"},"ds_transaction_id":{"type":"string","description":"The transaction ID generated by the Directory Server"},"3ds_server_transaction_id":{"type":"string","description":"The transaction ID generated by the 3DS Server"}}},"ChallengeInfoType":{"type":"object","description":"Information about the challenge.","properties":{"challenge_req":{"type":"string","description":"The base64-encoded challenge request (CReq) that must be sent to the ACS."},"challenge_url":{"type":"string","description":"The URL of the ACS where the challenge will be sent."},"challenge_session_data":{"type":"string","description":"The base64-encoded session data that must be sent to the ACS for the challenge."},"challenge_form":{"type":"string","description":"An HTML form that can be directly rendered in the browser to initiate the challenge."}}},"ThreeDSErrorResponse":{"type":"object","description":"The response body for a failed 3DS request.","properties":{"data":{"type":"object","properties":{"message":{"type":"string","description":"Error received from upstream."},"card_id":{"type":"string","description":"Unique VGS identifier for the card"},"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoType"}}},"meta":{"type":"object","title":"Meta","properties":{"observability":{"type":"object","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}}}}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"}}},"paths":{"/cards/{card_id}/3ds-authenticate":{"post":{"tags":["3D Secure (3DS)"],"summary":"Perform 3DS authentication","description":"Main call to perform authentication. Required for payment transactions.\n\nHow the 3DS Challenge Response Fields Are Used\nWhen a cardholder needs to complete a challenge during authentication there are two ways to handle the process:\n- *Use the prebuilt HTML form* (`challenge_form`):\n    This form already contains all necessary elements, including the ACS URL, the CReq data, and the session data.\n    You can return this form directly to the cardholder on your checkout page.\n    It will display the correct UI, including the payment scheme logo and any loading spinners,\n    and will automatically handle localization.\n- *Build your own redirect form using individual fields*:\n    If you would prefer to generate your own HTML form for the challenge, include the following fields from the response:\n      - `challenge_url`: The URL to which the cardholder should be redirected for the challenge\n      - `challenge_request`: The CReq data that must be sent to the ACS, included as a hidden field in the form\n      - `challenge_session_data`: Include this as a hidden field if provided. It allows you to track the session and link it back to the specific transaction when the cardholder returns from the ACS.\nAfter the cardholder completes the challenge, they will be redirected to your `redirect_url`,\nand you will receive the final challenge result along with the `challenge_session_data` so you can reconcile it with the transaction.\n","operationId":"threeds-authenticate","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card ID"}},{"$ref":"#/components/parameters/accept-header"},{"$ref":"#/components/parameters/accept-language-header"},{"$ref":"#/components/parameters/auth-header"},{"$ref":"#/components/parameters/content-type"}],"requestBody":{"description":"3DS authenticate request payload","required":true,"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSAuthenticateRequest"}}}},"responses":{"200":{"description":"Successful authentication","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSAuthenticateResponse"}}}},"400":{"description":"Invalid request","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"description":"Forbidden. The client does not have permission to perform this action, or the vault context could not be determined from the request.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"description":"Unprocessable Entity. The request was well-formed but contained semantic errors.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Perform 3DS Status Check

> Check the 3DS authentication status of a card.  \
> \
> \*\*Endpoint to Check Initialize Device Fingerprint Status\*\*: \`GET /cards/{card\_id}/3ds-check?init\_received=true\&xid={xid}\&merchant\_transaction\_id={merchant\_transaction\_id}\`  \
> \
> \*\*Endpoint to Check Authentication Status\*\*: \`GET /cards/{card\_id}/3ds-check?xid={xid}\&merchant\_transaction\_id={merchant\_transaction\_id}\`<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"3D Secure (3DS)","description":"For a fully optimized 3DS flow:\n1. Call the _3ds-initialize_ endpoint, which may return an iframe for device fingerprinting. If no iframe is returned, initialization isn’t required and authentication can proceed immediately.\n2. Render the iframe on the front end as soon as it’s received from VGS. It can also be loaded as an invisible or background frame while the cardholder waits, so the client doesn’t pause for processing.\n3. Submit the form contained in the iframe, this will start the device fingerprinting process.\n4. Start a 10-second timer after receiving the iframe from VGS, and wait until you either get the asynchronous device fingerprinting response from VGS or the timer expires—-whichever happens first—-before sending the authenticate request to VGS.\n5. Call the _3ds-authenticate_ endpoint at the time of purchase. It may return the final authentication result synchronously, or it may trigger a user challenge-—in which case the final result will be delivered via the configured webhook notification.\n"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources.\n"},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads.\n"}],"security":[{"bearerAuth":["3ds:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"parameters":{"auth-header":{"in":"header","name":"Authorization","description":"Bearer token for authentication.","schema":{"type":"string"},"required":true}},"schemas":{"ThreeDSCheckResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"attributes":{"type":"object","properties":{"details":{"$ref":"#/components/schemas/ThreeDSCheckDetails"},"event":{"type":"string","description":"The type of event that occurred."},"org_id":{"type":"string"},"tenant":{"type":"string"},"timestamp":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of when the event occurred."}}}}}}},"ThreeDSCheckDetails":{"type":"object","properties":{"acs_operator_id":{"type":"string","description":"Unique identifier of the ACS operator assigned by the card scheme (e.g., Visa/Mastercard)."},"acs_reference_number":{"type":"string","description":"ACS reference number identifying the ACS product/version certified with the Directory Server."},"acs_transaction_id":{"type":"string","format":"uuid","description":"ACS transaction ID (`acsTransID`) for this EMV 3DS transaction."},"card_id":{"type":"string"},"cavv":{"type":"string","description":"Cardholder Authentication Verification Value produced by EMV 3DS; base64-encoded. Include in payment authorization. Also known as AEVV/UCAF for some networks."},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp when CMP recorded the 3DS challenge result."},"ds_transaction_id":{"type":"string","format":"uuid","description":"Directory Server transaction ID (`dsTransID`)."},"eci":{"type":"string","description":"Electronic Commerce Indicator returned by the scheme (e.g., 05/06/07) and used during authorization."},"init_received":{"type":"boolean","description":"Indicates if the 3DS initialization callback was received for this transaction and webhook sent."},"merchant_transaction_id":{"type":"string","description":"Merchant-supplied transaction identifier used to correlate initialize/authenticate/check calls."},"message":{"type":"string","description":"Human-readable status or instructions from the ACS/3DS Server (e.g., challenge URL or outcome note)."},"status":{"type":"string","enum":["APPROVED","UNABLE_TO_AUTHENTICATE","DENIED","REJECTED","ATTEMPTS_PERFORMED"],"description":"Mapped EMV 3DS authentication outcome for this transaction."},"3ds_server_transaction_id":{"type":"string","format":"uuid","description":"3DS Server transaction ID (`threeDSServerTransID`)."},"tx_id":{"type":"string","description":"Provider transaction identifier used for internal tracking by the 3DS gateway/vendor."},"xid":{"type":"string","description":"Transaction reference (`XID`); base64-encoded (28 chars). Used by some schemes for correlation."}}},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"},"fingerprint":{"type":"string","title":"string"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["summary","detail","error_code"]},"meta":{"anyOf":[{"type":"object"}],"title":"Meta"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}]},"type":"object"}],"title":"Links"},"included":{"anyOf":[{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"attributes":{"anyOf":[{"properties":{},"additionalProperties":true,"type":"object","title":"LubeAttributes","description":"Members of the LubeAttributes object (\"attributes\") represent information about the resource object in which it's defined.\n\n\nThe keys for Attributes MUST NOT be:\n\n\n    relationships\n    links\n    id\n    type\n"},{"type":"null"}]},"relationships":{"anyOf":[{"additionalProperties":{"properties":{"links":{"anyOf":[{"properties":{"self":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"relationship link"},"related":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"null"}],"title":"related resource link"}},"type":"object","title":"LubeRelationLink"},{"type":"null"}]},"data":{"anyOf":[{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},{"items":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"type","description":"Resource type"},"meta":{"type":"object","title":"meta"},"lid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lid"}},"type":"object","required":["id","type"],"title":"LubeResourceId","description":"JSON:API Resource Identifier"},"type":"array"},{"type":"null"}],"title":"Data"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","title":"LubeRel","description":"JSON:API Relationship"},"type":"object"},{"type":"null"}],"title":"Relationships"},"links":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"properties":{"href":{"anyOf":[{"type":"string","minLength":1,"format":"uri"},{"type":"null"}],"title":"href"},"rel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link relation type"},"describedby":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link to a description of the link relation type\n"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link title"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"link media type"},"hreflang":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"link language"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"meta"}},"type":"object","title":"LubeLink","description":"JSON:API Link"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Links"},"meta":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Meta"}},"type":"object","required":["id","type"],"title":"LubeResource","description":"A single resource. The only JSON:API required field is type"},"type":"array"}],"title":"Included"},"jsonapi":{"$ref":"#/components/schemas/JsonApiVersion"}},"type":"object","title":"ErrorResponse"},"JsonApiVersion":{"properties":{"version":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Version","default":1.1},"ext":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Ext"}]},"profile":{"anyOf":[{"items":{"type":"string","minLength":1,"format":"uri"},"type":"array"},{"type":"null","title":"Profile"}]},"meta":{"type":"object","title":"Meta"}},"title":"JsonApi"},"ThreeDSErrorResponse":{"type":"object","description":"The response body for a failed 3DS request.","properties":{"data":{"type":"object","properties":{"message":{"type":"string","description":"Error received from upstream."},"card_id":{"type":"string","description":"Unique VGS identifier for the card"},"transaction_info":{"type":"object","description":"Transaction information.","$ref":"#/components/schemas/TransactionInfoType"}}},"meta":{"type":"object","title":"Meta","properties":{"observability":{"type":"object","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}}}}}}},"TransactionInfoType":{"type":"object","description":"Transaction Information for 3DS authentication requests","required":["xid","merchant_transaction_id"],"properties":{"xid":{"type":"string","minLength":28,"maxLength":28,"description":"Unique transaction reference. It can be the same across a series of transactions for a single user or recurring payments. Must be a base64 encoded sequence of 20 bytes."},"merchant_transaction_id":{"type":"string","minLength":1,"maxLength":40,"description":"The merchant_transaction_id is a unique identifier (UUID) assigned to each transaction. Its primary relevance becomes clear in scenarios involving 3RI (Merchant-Initiated Transactions), where merchants need to reference a previously successful transaction using identifiers such as acs_transaction_id and ds_transaction_id. In such cases, while the XID may remain the same across the initial and subsequent 3RI transactions, the merchant_transaction_id must be unique for each transaction.\nFor CIT (Customer-Initiated Transactions), both the XID and merchant_transaction_id can either be the same or different UUIDs — both approaches are acceptable."}}}}},"paths":{"/cards/{card_id}/3ds-check":{"get":{"tags":["3D Secure (3DS)"],"summary":"Perform 3DS Status Check","description":"Check the 3DS authentication status of a card.  \n\n**Endpoint to Check Initialize Device Fingerprint Status**: `GET /cards/{card_id}/3ds-check?init_received=true&xid={xid}&merchant_transaction_id={merchant_transaction_id}`  \n\n**Endpoint to Check Authentication Status**: `GET /cards/{card_id}/3ds-check?xid={xid}&merchant_transaction_id={merchant_transaction_id}`\n","operationId":"threeds-check","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card ID","description":"Unique identifier for the card being authenticated."}},{"name":"merchant_transaction_id","in":"query","required":true,"description":"Generated by the merchant. Must be a unique identifier assigned to each transaction.","schema":{"type":"string"}},{"name":"xid","in":"query","required":true,"schema":{"type":"string","minLength":28,"maxLength":28,"description":"Generated by the merchant. Can be the same across a series of transactions for a single user or recurring payments. Must be a base64-encoded sequence of 20 bytes."}},{"name":"init_received","in":"query","required":false,"allowEmptyValue":true,"description":"Boolean flag controlling which status is returned:\n- Required with **init_received=true** if you want to retrieve device fingerprinting initialization status. Invoke /3ds-check after the iframe from the synchronous initialize response is rendered and the form containing the iframe is submitted on the front end. This allows the issuer to collect the device fingerprinting.\n- **init_received=false** or not provided: Returns authentication status after the challenge questionnaire/html is submitted by the user in the 3DS challenge flow.\n","schema":{"type":"boolean","default":false}},{"$ref":"#/components/parameters/auth-header"}],"responses":{"200":{"description":"Successful check","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSCheckResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"description":"Forbidden. The client does not have permission to perform this action, or the vault context could not be determined from the request.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"500":{"description":"An unexpected error occurred.","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ThreeDSErrorResponse"}}}},"503":{"description":"Service Unavailable. The downstream network is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

{% openapi-webhook spec="card-management-api" name="threeds-challenge" method="post" %}
[card-management-api](https://4401d86825a13bf607936cc3a9f3897a.r2.cloudflarestorage.com/gitbook-x-prod-openapi/raw/833d2464716fa5da708fac399110f2cc8577362128000061ab970b36a03b925d.yaml?X-Amz-Algorithm=AWS4-HMAC-SHA256\&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD\&X-Amz-Credential=dce48141f43c0191a2ad043a6888781c%2F20260717%2Fauto%2Fs3%2Faws4_request\&X-Amz-Date=20260717T005303Z\&X-Amz-Expires=172800\&X-Amz-Signature=2edf9a8594bfe251cf1ae8fa72c22c09723f46c549fa35886e8ea1ac6d13eb51\&X-Amz-SignedHeaders=host\&x-amz-checksum-mode=ENABLED\&x-id=GetObject)
{% endopenapi-webhook %}

{% openapi-webhook spec="card-management-api" name="threeds-callback" method="post" %}
[card-management-api](https://4401d86825a13bf607936cc3a9f3897a.r2.cloudflarestorage.com/gitbook-x-prod-openapi/raw/833d2464716fa5da708fac399110f2cc8577362128000061ab970b36a03b925d.yaml?X-Amz-Algorithm=AWS4-HMAC-SHA256\&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD\&X-Amz-Credential=dce48141f43c0191a2ad043a6888781c%2F20260717%2Fauto%2Fs3%2Faws4_request\&X-Amz-Date=20260717T005303Z\&X-Amz-Expires=172800\&X-Amz-Signature=2edf9a8594bfe251cf1ae8fa72c22c09723f46c549fa35886e8ea1ac6d13eb51\&X-Amz-SignedHeaders=host\&x-amz-checksum-mode=ENABLED\&x-id=GetObject)
{% endopenapi-webhook %}


# Wallet Decryption

## Create a card

> The Create Card allows clients to register a digital wallet credential in the Credential Management Platform (CMP) using an encrypted wallet payment token. Supported wallet types include Apple Pay.\
> \
> The request accepts the encrypted wallet payload, which is securely decrypted by VGS to extract the underlying credential details and create a card linked to a specific account. Each request results in the creation of a new card and returns a 201 response with a new Card ID, even if the same DPAN or MPAN is submitted multiple times. Duplicate detection and deduplication logic are not supported for this card type.\
> \
> The \`payment\_method\` object (\`display\_name\`, \`network\`, \`type\`) is optional in the request. If these fields are provided, their values will be echoed back in the response. If they are not included in the request, they will not be returned.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API - POST /cards (encrypted only)","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Wallet Decryption"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources."},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads."}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EncryptedCardResourceRequest":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["attributes"],"properties":{"attributes":{"$ref":"#/components/schemas/EncryptedCardAttributes"}}}}},"EncryptedCardAttributes":{"type":"object","additionalProperties":false,"required":["encrypted_payment_data"],"properties":{"encrypted_payment_data":{"$ref":"#/components/schemas/EncryptedPaymentData"}}},"EncryptedPaymentData":{"type":"object","additionalProperties":false,"required":["encrypted_payload_text","public_key","key_hash"],"properties":{"digital_signature":{"type":"string","minLength":10,"maxLength":8192,"description":"Base64-encoded wallet signature."},"encrypted_payload_text":{"type":"string","minLength":20,"maxLength":20000,"description":"Base64-encoded encrypted wallet payload."},"key_hash":{"type":"string","minLength":44,"maxLength":44,"description":"Base64-encoded SHA-256 hash of the wallet public key. Apple Pay only."},"public_key":{"type":"string","minLength":20,"maxLength":2048,"description":"Base64-encoded ephemeral public key."},"version":{"$ref":"#/components/schemas/EncryptedPaymentDataVersion","default":"EC_v1"},"wallet_type":{"$ref":"#/components/schemas/WalletType","default":"apple_pay"},"wallet_transaction_id":{"type":"string","description":"transaction identifier","minLength":1,"maxLength":255},"payment_method":{"$ref":"#/components/schemas/WalletPaymentMethod"}}},"EncryptedPaymentDataVersion":{"type":"string","description":"The version of the encrypted payment data format used for the card request.","enum":["EC_v1"]},"WalletType":{"type":"string","description":"The digital wallet from which the card request originated.","enum":["apple_pay"]},"WalletPaymentMethod":{"type":"object","description":"Details about the payment method used","additionalProperties":false,"properties":{"display_name":{"type":"string","maxLength":255,"minLength":1,"description":"Human-readable payment method description"},"network":{"type":"string","maxLength":255,"minLength":1,"description":"Payment card network"},"type":{"type":"string","maxLength":255,"minLength":1,"description":"Card type"}}},"CardResourceResponse":{"title":"CardResourceResponse","type":"object","properties":{"data":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"Type","default":"cards"},"attributes":{"$ref":"#/components/schemas/CardResourceAttributes"}},"type":"object","required":["id","type","attributes"]},"metadata":{"$ref":"#/components/schemas/MetadataResponse"}},"additionalProperties":false,"required":["data","metadata"]},"CardResourceAttributes":{"type":"object","title":"CardResourceAttributes","description":"Full card information with extra fields like bin, last4, capabilities etc","properties":{"pan":{"type":"string","maxLength":19,"minLength":14,"title":"Primary Account Number","description":"The primary account number of the card. This field is omitted from non-PCI scope payload responses."},"cvc_status":{"type":"string","maxLength":10,"minLength":3,"title":"CVC Status","description":"The is an indicator that CVC was present during Create Card.\n"},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"},"cardholder":{"$ref":"#/components/schemas/Cardholder","description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"token_type":{"$ref":"#/components/schemas/TokenType"},"wallet_type":{"$ref":"#/components/schemas/WalletType"},"pan_alias":{"type":"string","title":"PAN Alias","description":"The PAN alias is a reference identifier that stores or securely holds the actual PAN value.\n"},"cvc_alias":{"type":"string","maxLength":35,"minLength":30,"title":"CVC Alias","description":"The CVC Alias is a reference identifier that stores or securely holds the actual CVC value.\n"},"bin":{"type":"string","minLength":6,"maxLength":8,"description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"first8":{"type":"string","minLength":8,"maxLength":8,"description":"8 character Bank Identification Number (BIN). The first8 field will be returned in the card object only for Visa and Mastercard cards."},"last4":{"type":"string","minLength":4,"maxLength":4,"description":"Last 4 characters of the primary account number (pan/fpan)"},"card_fingerprint":{"type":"string","description":"Card Fingerprint"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"card_brand":{"type":"string","description":"The name of the card brand."},"card_type":{"type":"string","description":"The card type (credit, debit or prepaid)."},"enrollment_source":{"$ref":"#/components/schemas/EnrollmentSource"},"enriched_attributes":{"$ref":"#/components/schemas/EnrichedCardAttributes","description":"Enriched card attributes containing additional metadata about the card. This data provides detailed information about the card's capabilities, issuer details, and transaction support features."},"wallet_details":{"$ref":"#/components/schemas/WalletDetails","description":"Details about the digital wallet associated with the card."}},"required":["cvc_status","exp_month","exp_year","token_type","wallet_type","pan_alias","bin","first8","last4","card_fingerprint","card_brand","card_type","created_at","updated_at","wallet_details"]},"Cardholder":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"The cardholder name."},"company":{"type":"string","maxLength":255,"title":"Company","description":"Company name."},"phone":{"type":"string","maxLength":16,"title":"Phone","description":"The phone number related to the card."},"email":{"type":"string","format":"email","description":"Email address of the account holder."},"address":{"$ref":"#/components/schemas/Address"}},"description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"Address":{"properties":{"address1":{"type":"string","maxLength":255,"description":"The first line of the address related to the card."},"address2":{"type":"string","maxLength":255,"description":"The second line of the address related to the card."},"address3":{"type":"string","maxLength":255,"description":"The third line of the address related to the card."},"address4":{"type":"string","maxLength":255,"description":"The fourth line of the address related to the card."},"city":{"type":"string","maxLength":255,"description":"The city of the address related to the card."},"region":{"type":"string","maxLength":255,"description":"The region of the address related to the card."},"postal_code":{"type":"string","maxLength":10,"description":"The postal code of the address related to the card."},"country":{"type":"string","maxLength":3,"minLength":2,"description":"The country of the address related to the card. This must be the ISO 3166-1 alpha-2 or the ISO 3166-1 alpha-3 code. (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3]\n"}},"type":"object","title":"Address"},"TokenType":{"type":"string","description":"The type of token being used for the card.","enum":["dpan","mpan"]},"EnrollmentSource":{"type":"string","description":"Indicates whether the card was loaded from an existing backbook portfolio\nor newly tokenized. Set by the server based on the `processing` query\nparameter at card creation time and is read-only.\n","enum":["backbook","frontbook"]},"EnrichedCardAttributes":{"type":"object","description":"Enriched card attributes from the card-attributes service","properties":{"card_properties":{"type":"object","properties":{"card_number_length":{"type":"integer","description":"The length of the Primary Account Number (PAN) printed on the front of the card. Available only for Card Attributes service subscribers.\n"},"card_segment_type":{"type":"string","description":"Indicator of Business, Consumer, Commercial, Government BINs. Available only for Card Attributes service subscribers."},"level_2":{"type":"boolean","description":"Indicator of Level 2 interchange rate eligibility.\n"},"level_3":{"type":"boolean","description":"Indicator of Level 3 interchange rate eligibility.\n"},"virtual_card":{"type":"boolean","description":"Indicates if the given BIN range supports virtual card creation. Available only for Card Attributes service subscribers.\n"},"prepaid_card":{"type":"boolean","description":"Indicates a fixed funding source for a card but not necessarily associated with the consumer's checking account. Available only for Card Attributes service subscribers.\n"},"product_name":{"type":"string","description":"The card product name according to the card brand (e.g., Visa Signature, Visa Infinite, Visa Classic). Available only for Card Attributes service subscribers.\n"},"issuer_bin":{"type":"string","description":"Bank Identification Number (BIN) of the issuer of the account. Available only for Card Attributes service subscribers."},"country_letter_code":{"type":"string","description":"ISO country letters that is associated with an ISO 3166-1 alpha-2 code."},"country_name":{"type":"string","description":"Name of the issuing country. Available only for Card Attributes service subscribers."},"country_numeric":{"type":"integer","description":"ISO 3166 numeric country code of the issuing country. Available only for Card Attributes service subscribers."}}},"card_capabilities":{"type":"object","properties":{"reloadable":{"type":"boolean","description":"Indicator of reloadable or non-reloadable prepaid. Available only for Card Attributes service subscribers."},"hsa":{"type":"boolean","description":"Indicates a card attached to a Health Savings Account. Available only for Card Attributes service subscribers."},"fsa":{"type":"boolean","description":"Indicates a card attached to Flexible Spending Account. Available only for Card Attributes service subscribers."},"ebt":{"type":"boolean","description":"Indicates the BIN has Electronic Benefits Transfer (EBT) capabilities. Available only for Card Attributes service subscribers."}}},"bank":{"type":"object","properties":{"issuer_name":{"type":"string","description":"Name of the issuing organization/bank."},"issuer_phone_number":{"type":"string","description":"Phone number of the issuing organization/bank. Available only for Card Attributes service subscribers."},"issuer_website":{"type":"string","description":"Website of the issuing organization/bank. Available only for Card Attributes service subscribers."}}},"additional_card_brands":{"type":"array","description":"Additional card brands, if any, associated with the card. Available only for Card Attributes service subscribers.","items":{"type":"object","required":["card_brand"],"properties":{"card_brand":{"type":"string","description":"The name of the additional card brand. Available only for Card Attributes service subscribers."}}}},"interchange":{"type":"object","properties":{"regulated":{"type":"string","description":"Indicator of the presence of an interchange regulation on a BIN. Available only for Card Attributes service subscribers."}}}}},"WalletDetails":{"type":"object","properties":{"currency_code":{"type":"string","maxLength":3,"minLength":3,"description":"ISO 4217 alpha 3 currency code for the transaction"},"amount":{"type":"integer","description":"Transaction amount in the given currency code's minor unit (e.g. cents for USD)","minimum":0},"device_manufacturer_identifier":{"type":"string","description":"Device manufacturer identifier for the card in the wallet."},"payment_data_type":{"$ref":"#/components/schemas/PaymentDataType"},"cryptogram":{"$ref":"#/components/schemas/CryptogramAttributes"},"merchant_token_identifier":{"type":"string","description":"Identifier for the merchant token associated with the wallet transaction"},"payment_method":{"$ref":"#/components/schemas/WalletPaymentMethod"},"transaction_id":{"type":"string","description":"Identifier for the wallet transaction"}}},"PaymentDataType":{"type":"string","description":"Type of the payment data encoding","enum":["3DSecure","MerchantToken"]},"CryptogramAttributes":{"type":"object","properties":{"type":{"type":"string","enum":["TAVV","DTVV"],"description":"Cryptogram type (defaults to TAVV)\n\nTAVV (Token Authentication Verification Value) and DTVV (Dynamic Token Verification Value) are cryptograms used to authenticate transactions and prevent fraud.\n\nCustomers can initiate transactions using VGS Network Tokens by generating a unique cryptogram.\n\n* TAVV: This cryptogram is specific to the network token and can be up to 32 characters long. When submitting transactions, networks may require merchants to specify the transaction type explicitly during cryptogram generation.\n* DTVV: Unlike TAVV, DTVV is a 3-characters long cryptogram that is currently supported only for Visa Network Tokens which can increase compatibility with some PSPs. To use DTVV, VGS must be enabled on a case-by-case basis. Merchants interested in enabling DTVV can reach out to support@verygoodsecurity.com for assistance.\n\nTo avoid declines, merchants and acquirers must ensure that:\n- TAVV and DTVV are new and unique for each authorization request\n- TAVV and DTVV are one-time use and not stored beyond the authorization request\n- The TAVV, DTVV, and electronic commerce indicator values provided by the token requester are unchanged when submitted for an authorization request\n"},"value":{"type":"string"},"eci":{"type":"string","description":"An Electronic Commerce Indicator (ECI) is a code that indicates the type of electronic transaction and the result of authentication for a payment.\n"}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}},"required":["observability"]},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}},"required":["trace_id","client_id","vault_id","account_id","fingerprint"]},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["detail","error_code"]},"meta":{"$ref":"#/components/schemas/MetadataResponse","title":"Meta"}},"type":"object","title":"ErrorResponse","required":["errors","meta"]}}},"paths":{"/cards":{"post":{"tags":["Wallet Decryption"],"summary":"Create a card","description":"The Create Card allows clients to register a digital wallet credential in the Credential Management Platform (CMP) using an encrypted wallet payment token. Supported wallet types include Apple Pay.\n\nThe request accepts the encrypted wallet payload, which is securely decrypted by VGS to extract the underlying credential details and create a card linked to a specific account. Each request results in the creation of a new card and returns a 201 response with a new Card ID, even if the same DPAN or MPAN is submitted multiple times. Duplicate detection and deduplication logic are not supported for this card type.\n\nThe `payment_method` object (`display_name`, `network`, `type`) is optional in the request. If these fields are provided, their values will be echoed back in the response. If they are not included in the request, they will not be returned.\n","requestBody":{"required":true,"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/EncryptedCardResourceRequest"}}}},"responses":{"201":{"description":"Card created","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponse"}}}},"400":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request was invalid."},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"422":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The server was unable to process the request because it contains invalid data."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```

## Get a card

> The Get API allows clients to retrieve details for a specific digital wallet credential using its unique cardID.\
> \
> The response returns the stored card attributes derived from the decrypted wallet payload, including last four digits, expiration details, and any request-level attributes persisted at creation (such as \`payment\_method\`, if provided). If \`payment\_method\` fields were included during creation, they will be returned in the response. If not provided, they will not be present.\
> \
> \`cryptogram\`, \`currencyCode\`, \`transactionId\`, and \`amount\` are not returned in the GET response, as these are single-use wallet artifacts and are not persisted.<br>

```json
{"openapi":"3.1.0","info":{"title":"VGS Card Management Platform (CMP) API - POST /cards (encrypted only)","version":"doc version 2.2.9 | API version 1.0.0"},"tags":[{"name":"Wallet Decryption"}],"servers":[{"url":"https://sandbox.vgsapi.com","description":"Sandbox environment server used for integration and testing. Uses network sandboxes in addition to mocked data sources."},{"url":"https://vgsapi.com","description":"Live environment server used for production workloads."}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CardResourceResponseGet":{"title":"CardResourceResponseGet","type":"object","properties":{"data":{"properties":{"id":{"type":"string","title":"id","description":"Resource ID"},"type":{"type":"string","title":"Type","default":"cards"},"attributes":{"$ref":"#/components/schemas/CardResourceAttributesGet"}},"type":"object","required":["id","type","attributes"]},"metadata":{"$ref":"#/components/schemas/MetadataResponse"}},"additionalProperties":false,"required":["data","metadata"]},"CardResourceAttributesGet":{"type":"object","title":"CardResourceAttributesGet","description":"Full card information with extra fields like bin, last4, capabilities etc","properties":{"pan":{"type":"string","maxLength":19,"minLength":14,"title":"Primary Account Number","description":"The primary account number of the card. This field is omitted from non-PCI scope payload responses."},"cvc_status":{"type":"string","maxLength":10,"minLength":3,"title":"CVC Status","description":"The is an indicator that CVC was present during Create Card.\n"},"exp_month":{"type":"integer","maximum":12,"minimum":1,"title":"Expiration Month","description":"The expiration month of the card, as an integer between 1 and 12, where 1 is January, and 12 is December.\n"},"exp_year":{"type":"integer","maximum":99,"minimum":0,"title":"Expiration Year","description":"The expiration year of the card, as a 1-2 digit integer representing the decade portion of the year.\n"},"cardholder":{"$ref":"#/components/schemas/Cardholder","description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"token_type":{"$ref":"#/components/schemas/TokenType"},"wallet_type":{"$ref":"#/components/schemas/WalletType"},"pan_alias":{"type":"string","title":"PAN Alias","description":"The PAN alias is a reference identifier that stores or securely holds the actual PAN value.\n"},"cvc_alias":{"type":"string","maxLength":35,"minLength":30,"title":"CVC Alias","description":"The CVC Alias is a reference identifier that stores or securely holds the actual CVC value.\n"},"bin":{"type":"string","minLength":6,"maxLength":8,"description":"The leading six or eight digits of the related card are the issuer identification number (IIN) sometimes referred to as the bank identification number (BIN)."},"first8":{"type":"string","minLength":8,"maxLength":8,"description":"8 character Bank Identification Number (BIN). The first8 field will be returned in the card object only for Visa and Mastercard cards."},"last4":{"type":"string","minLength":4,"maxLength":4,"description":"Last 4 characters of the primary account number (pan/fpan)"},"card_fingerprint":{"type":"string","description":"Card Fingerprint"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"card_brand":{"type":"string","description":"The name of the card brand."},"card_type":{"type":"string","description":"The card type (credit, debit or prepaid)."},"enrollment_source":{"$ref":"#/components/schemas/EnrollmentSource"},"enriched_attributes":{"$ref":"#/components/schemas/EnrichedCardAttributes","description":"Enriched card attributes containing additional metadata about the card. This data provides detailed information about the card's capabilities, issuer details, and transaction support features."},"wallet_details":{"$ref":"#/components/schemas/WalletDetailsGet","description":"Details about the digital wallet associated with the card."}},"required":["cvc_status","exp_month","exp_year","token_type","wallet_type","pan_alias","bin","first8","last4","card_fingerprint","card_brand","card_type","created_at","updated_at","wallet_details"]},"Cardholder":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"The cardholder name."},"company":{"type":"string","maxLength":255,"title":"Company","description":"Company name."},"phone":{"type":"string","maxLength":16,"title":"Phone","description":"The phone number related to the card."},"email":{"type":"string","format":"email","description":"Email address of the account holder."},"address":{"$ref":"#/components/schemas/Address"}},"description":"Information about the cardholder, including name, email, address, and phone number. To achieve a high success rate with Amex Network Tokens, include card holder phone number and email address.\n"},"Address":{"properties":{"address1":{"type":"string","maxLength":255,"description":"The first line of the address related to the card."},"address2":{"type":"string","maxLength":255,"description":"The second line of the address related to the card."},"address3":{"type":"string","maxLength":255,"description":"The third line of the address related to the card."},"address4":{"type":"string","maxLength":255,"description":"The fourth line of the address related to the card."},"city":{"type":"string","maxLength":255,"description":"The city of the address related to the card."},"region":{"type":"string","maxLength":255,"description":"The region of the address related to the card."},"postal_code":{"type":"string","maxLength":10,"description":"The postal code of the address related to the card."},"country":{"type":"string","maxLength":3,"minLength":2,"description":"The country of the address related to the card. This must be the ISO 3166-1 alpha-2 or the ISO 3166-1 alpha-3 code. (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3]\n"}},"type":"object","title":"Address"},"TokenType":{"type":"string","description":"The type of token being used for the card.","enum":["dpan","mpan"]},"WalletType":{"type":"string","description":"The digital wallet from which the card request originated.","enum":["apple_pay"]},"EnrollmentSource":{"type":"string","description":"Indicates whether the card was loaded from an existing backbook portfolio\nor newly tokenized. Set by the server based on the `processing` query\nparameter at card creation time and is read-only.\n","enum":["backbook","frontbook"]},"EnrichedCardAttributes":{"type":"object","description":"Enriched card attributes from the card-attributes service","properties":{"card_properties":{"type":"object","properties":{"card_number_length":{"type":"integer","description":"The length of the Primary Account Number (PAN) printed on the front of the card. Available only for Card Attributes service subscribers.\n"},"card_segment_type":{"type":"string","description":"Indicator of Business, Consumer, Commercial, Government BINs. Available only for Card Attributes service subscribers."},"level_2":{"type":"boolean","description":"Indicator of Level 2 interchange rate eligibility.\n"},"level_3":{"type":"boolean","description":"Indicator of Level 3 interchange rate eligibility.\n"},"virtual_card":{"type":"boolean","description":"Indicates if the given BIN range supports virtual card creation. Available only for Card Attributes service subscribers.\n"},"prepaid_card":{"type":"boolean","description":"Indicates a fixed funding source for a card but not necessarily associated with the consumer's checking account. Available only for Card Attributes service subscribers.\n"},"product_name":{"type":"string","description":"The card product name according to the card brand (e.g., Visa Signature, Visa Infinite, Visa Classic). Available only for Card Attributes service subscribers.\n"},"issuer_bin":{"type":"string","description":"Bank Identification Number (BIN) of the issuer of the account. Available only for Card Attributes service subscribers."},"country_letter_code":{"type":"string","description":"ISO country letters that is associated with an ISO 3166-1 alpha-2 code."},"country_name":{"type":"string","description":"Name of the issuing country. Available only for Card Attributes service subscribers."},"country_numeric":{"type":"integer","description":"ISO 3166 numeric country code of the issuing country. Available only for Card Attributes service subscribers."}}},"card_capabilities":{"type":"object","properties":{"reloadable":{"type":"boolean","description":"Indicator of reloadable or non-reloadable prepaid. Available only for Card Attributes service subscribers."},"hsa":{"type":"boolean","description":"Indicates a card attached to a Health Savings Account. Available only for Card Attributes service subscribers."},"fsa":{"type":"boolean","description":"Indicates a card attached to Flexible Spending Account. Available only for Card Attributes service subscribers."},"ebt":{"type":"boolean","description":"Indicates the BIN has Electronic Benefits Transfer (EBT) capabilities. Available only for Card Attributes service subscribers."}}},"bank":{"type":"object","properties":{"issuer_name":{"type":"string","description":"Name of the issuing organization/bank."},"issuer_phone_number":{"type":"string","description":"Phone number of the issuing organization/bank. Available only for Card Attributes service subscribers."},"issuer_website":{"type":"string","description":"Website of the issuing organization/bank. Available only for Card Attributes service subscribers."}}},"additional_card_brands":{"type":"array","description":"Additional card brands, if any, associated with the card. Available only for Card Attributes service subscribers.","items":{"type":"object","required":["card_brand"],"properties":{"card_brand":{"type":"string","description":"The name of the additional card brand. Available only for Card Attributes service subscribers."}}}},"interchange":{"type":"object","properties":{"regulated":{"type":"string","description":"Indicator of the presence of an interchange regulation on a BIN. Available only for Card Attributes service subscribers."}}}}},"WalletDetailsGet":{"type":"object","properties":{"device_manufacturer_identifier":{"type":"string","description":"Device manufacturer identifier for the card in the wallet."},"payment_data_type":{"$ref":"#/components/schemas/PaymentDataType"},"merchant_token_identifier":{"type":"string","description":"Identifier for the merchant token associated with the wallet transaction"},"payment_method":{"$ref":"#/components/schemas/WalletPaymentMethod"}},"additionalProperties":false},"PaymentDataType":{"type":"string","description":"Type of the payment data encoding","enum":["3DSecure","MerchantToken"]},"WalletPaymentMethod":{"type":"object","description":"Details about the payment method used","additionalProperties":false,"properties":{"display_name":{"type":"string","maxLength":255,"minLength":1,"description":"Human-readable payment method description"},"network":{"type":"string","maxLength":255,"minLength":1,"description":"Payment card network"},"type":{"type":"string","maxLength":255,"minLength":1,"description":"Card type"}}},"MetadataResponse":{"type":"object","title":"MetadataResponse","properties":{"observability":{"$ref":"#/components/schemas/Observability"}},"required":["observability"]},"Observability":{"type":"object","title":"Observability","properties":{"trace_id":{"type":"string"},"client_id":{"type":"string"},"vault_id":{"type":"string"},"account_id":{"type":"string"},"fingerprint":{"type":"string"}},"required":["trace_id","client_id","vault_id","account_id","fingerprint"]},"ErrorResponse":{"properties":{"errors":{"items":{"properties":{"path":{"type":"string","title":"Path"},"summary":{"type":"string","title":"Summary"},"detail":{"type":"string","title":"Detail"},"error_code":{"type":"string","title":"Error Code"}},"type":"object","title":"Error"},"type":"array","title":"Errors","description":"A list of errors","required":["detail","error_code"]},"meta":{"$ref":"#/components/schemas/MetadataResponse","title":"Meta"}},"type":"object","title":"ErrorResponse","required":["errors","meta"]}}},"paths":{"/cards/{card_id}":{"get":{"tags":["Wallet Decryption"],"summary":"Get a card","description":"The Get API allows clients to retrieve details for a specific digital wallet credential using its unique cardID.\n\nThe response returns the stored card attributes derived from the decrypted wallet payload, including last four digits, expiration details, and any request-level attributes persisted at creation (such as `payment_method`, if provided). If `payment_method` fields were included during creation, they will be returned in the response. If not provided, they will not be present.\n\n`cryptogram`, `currencyCode`, `transactionId`, and `amount` are not returned in the GET response, as these are single-use wallet artifacts and are not persisted.\n","parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","title":"Card Id"}}],"responses":{"200":{"description":"Item requested by ID","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/CardResourceResponseGet"}}}},"401":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No credentials were provided, or the provided credentials were expired."},"403":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Valid credentials were provided, but they do not permit access to this resource."},"404":{"content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Resource not found."},"500":{"description":"Internal Server Error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}
```


# Credential Management V1 APIs (CALM)


# Network Tokens - V1

{% hint style="warning" %}
**Important Notice:**\
This document exists as reference documentation for clients already integrated with the V1 API. Clients are encouraged to use our latest Card Management API to access and transact with Network Tokens.
{% endhint %}

## Network Tokens Overview - V1 (Legacy)

Network tokens represent a significant advancement in payment processing. They act as unique digital identifiers that replace sensitive card details like the Primary Account Number (PAN) with alphanumeric strings. Businesses want secure payments that maximize conversion and improve customer experience. Network tokens help meet both of those goals.

VGS simplifies payment management by automatically converting stored card numbers (PANs) into secure network tokens. If a customer's card is lost, stolen, or replaced, VGS receives updates from the card networks and automatically updates the tokens, ensuring uninterrupted payments without customer intervention.

#### Concept of Tokenization

Tokenization emerged as part of the evolution of payment security and the need to protect sensitive cardholder data in an increasingly digital world. In the early stages, tokenization was used as a data protection mechanism. Companies began using tokens to replace sensitive card information, like Primary Account Numbers (PANs), to enhance security.

Fueled by the rapid growth of e-commerce, mobile payments, and digital wallet transactions, major card networks introduced network tokens. These tokens replace sensitive PANs with unique identifiers, significantly reducing fraud and marking a major advancement in payment security.

#### The difference between Network Tokens and VGS Alias

At VGS, a token is called a Record, and the reference identifier is called an Alias, and it stores a Value. A Record can have one or many Aliases, allowing you to represent a single element of sensitive data in many ways depending on the permissions use-case, or the sensitivity of the data. The stored value can be network tokens.

#### Benefits of using Network Tokens with VGS

* **Increased Authorization Rates:** Merchants can boost authorization rates by 2-3%\*. When a card is lost, stolen, or expires, issuers update the token with the new card details. This allows payments to process seamlessly even if the customer hasn't updated their card information with the merchant. This is particularly helpful for recurring payments or subscriptions. VGS Network tokens and Card Account Updater also work together to maximize authorization rates and optimize checkout conversion.
* **Reduced Processing Fees:** Card networks incentivize the use of network tokens by offering interchange discounts. For example, Visa offers a 10 basis points (bps) discount for certain merchants on eligible transactions using network tokens. These benefits can vary depending on the merchant, region, country, and card type.
* **Enhanced Fraud Prevention and Security:** By removing PAN data from the payment flow, network tokenization significantly reduces the risk of payment card fraud and data breaches. This decrease in exposure leads to fewer chargebacks and higher authorization rates, as issuers have greater confidence in tokenized transactions. This increased confidence stems from the reduced risk of compromised card details.
* **Streamlined Transactions:** Network token often requires a one-time cryptogram that needs to be fetched from the networks. As a result, network tokens can be prone to high additional latency compared to using PANs. VGS has optimized its infrastructure to minimize this delay, ensuring high payment success rates.
* **Reduced PCI DSS Scope:** By minimizing the handling of sensitive card data, merchants can reduce their compliance burden under the Payment Card Industry Data Security Standard (PCI DSS).

### How does VGS provide Network Tokens?

VGS maintains direct integrations with card networks to facilitate the use of Network tokens. Please contact [support](mailto:support@vgs.io) for further inquiries.

### What are the steps to using Network Token?

{% stepper %}
{% step %}

### Merchant Onboarding

* Merchants register for Network Tokens directly with VGS.
* VGS transmits information to the networks.
* Networks issue the client a unique "Token Requester ID" (TRID).
  {% endstep %}

{% step %}

### Enroll Cards

* With the TRID, merchants can enroll existing cards for Network Token through VGS.
* Network token availability for immediate transactions.
  {% endstep %}

{% step %}

### Processing Payments

* Once cards are enrolled, clients can use Network Tokens for future transactions.
  {% endstep %}
  {% endstepper %}

### Network Token Prerequisites

To use Network tokens, you must have a VGS Account. Please contact [support](mailto:support@vgs.io) to activate Network tokens.


# Quickstart - V1

## Introduction

This document is a comprehensive guide on how to set up the VGS Network Tokens integration, enabling you to retrieve Visa and Mastercard network tokens. A network token is a secure digital representation of a payment card, used to facilitate transactions between merchants and customers. It provides an additional security layer when transmitting sensitive payment information, as well as reducing the risk of fraud, and ensures a smooth and seamless transaction experience for your customers.

## Before you start

### Capture credit card data

> If you’re an existing user and already have VGS tokens, please skip this step.

Before creating and using network tokens, you need to capture and tokenize card data. You can do this in a few ways:

* **VGS Collect** - one of the ways to start collecting sensitive data is to configure the [VGS Collect form](/cmp/developer-resources/guides/create-a-card-using-vgs-collect) that will send requests to the VGS proxy, which is configured to redact the sensitive fields and store them in your vault. The form inputs themselves are VGS-hosted iFrames, so the web application is not interacting with the data as it is entered.
* **Vault API** - You can also use our [Vault API](broken://spaces/IK1qoGJ3ifpUepucGFZR/pages/trLwwmumlaofzMKwR3fr) to create test tokens.

### Test Cards

The following test cards can be used to test out the network tokens enrollment.

| Card Number      | Expiry Date (MMYY) | CVV          | Region |
| ---------------- | ------------------ | ------------ | ------ |
| 2222690420064590 | Any Future Date    | Any 3 digits | Global |
| 2222690420064574 | Any Future Date    | Any 3 digits | Global |
| 2222690420064582 | Any Future Date    | Any 3 digits | Global |
| 5120350100064594 | Any Future Date    | Any 3 digits | Global |
| 2223520127577835 | Any Future Date    | Any 3 digits | India  |

## Create Network Tokens

### Adding Network Tokens to your Integration

You integrate directly with the VGS Network Tokens API. VGS integrates with the network tokenization service provider (like Visa or MasterCard) on your behalf and uses the network token (where available) to process the transaction.

### Authentication and API Credentials

{% stepper %}
{% step %}

### Generate Service Account

You can generate a service account in the dashboard or create one using the VGS Command Line Interface (CLI).

* Navigate to the Service Accounts section of your Dashboard, under Vault > Organization > Service Accounts, and click on the Create New button.
* Select your Vault and add the `network-tokens:write` scope to provide access to Network Tokens.

Execute the sample code below, which will create `credentials.yaml`:

{% code title="CLI: generate service account" %}

```bash
vgs generate service-account -t calm --var vault_id=<VAULT_ID> > credentials.yaml
```

{% endcode %}
{% endstep %}

{% step %}

### Generate Access Token

To authenticate with the Network Tokens API, use the `CLIENT_ID` and `CLIENT_SECRET` generated in the previous step to create an `access_token`.

{% code title="cURL: obtain access token" %}

```bash
curl -X POST \
-d "client_id=<CLIENT_ID>" \
-d "client_secret=<CLIENT_SECRET>" \
-d "grant_type=client_credentials" \
"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token"
```

{% endcode %}

The generated token can now be used with the Network Tokens API. The `access_token` is valid only for 5 minutes. After expiry, generate a new access token using the same process. Do not use `refresh_token`. Pass the created `access_token` as an Authorization: `Bearer ${VGS_ACCESS_TOKEN}` header in each API call.
{% endstep %}

{% step %}

### Generate Access Credentials

To initiate a transaction to a PSP, you need an additional set of credentials that will allow requests through an outbound proxy.

* Go to Vault Settings > Access Credentials and press the Generate Credentials button.
* When Access Credentials are generated, download them. Note that access credential secrets are visible only at generation time.

If you lose these credentials, generate a new pair following the same process. Read more: [Access Credentials](/cmp/platform/authentication#id-3-generate-access-credentials)
{% endstep %}
{% endstepper %}

### Create Network Tokens

{% stepper %}
{% step %}

### Enable Network Tokens API

Go to Addons > VGS CALM and enable the Network Tokens addon. This will create an outbound route for the Network Tokens API.
{% endstep %}

{% step %}

### Enroll a Network Token

The Enrollment API invocation is synchronous and should complete within a few seconds. When you receive a response with `state: ACTIVE` you can use the Network Token to transact with a PSP.

{% code title="cURL: enroll network token" %}

```bash
curl -X POST https://calm.<ENVIRONMENT>.verygoodsecurity.app/network-tokens \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ${VGS_ACCESS_TOKEN}' \
-d '{
  "pan_alias":"tok_sandbox_mLCuQsa6bQUrsiZYYvzSC3",
  "exp_month":12,
  "exp_year":23
}'
```

{% endcode %}

You can explore all the fields that can be sent in an enrollment request [here](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1/network-tokens-bulk-enrollment-v1). Descriptions of enrollment failure reasons can be found [here](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1/network-tokens-bulk-enrollment-v1#enrollment-data-format).
{% endstep %}
{% endstepper %}

## Initiate A Payment Transaction

### Using Network Tokens to Transact

Performing a transaction with VGS Network Tokens is functionally the same as performing one with a VGS aliased PAN. Include the header `vgs-network-token: yes`. VGS will populate the payload with all the data needed for a successful transaction with your Network Token.

{% stepper %}
{% step %}

### Enable the integration for your PSP

To initiate a payment transaction you need to enable the integration with the desired PSP. Navigate to the Addons section under the Vault menu bar and find your desired PSP. Select the Network Tokens variant of their integration.

Note: For some PSPs, the default and Network Tokens integration are the same integration.

> Generally test cards cannot be used to perform test transactions with real PSPs. PSPs will need to add support for testing Network Tokens in their Sandbox environments. You can use our Demo PSP in the Addons section to test transactions.

Prebuilt PSP Integrations:

* Stripe
* Cybersource
* JPM Orbital
* Adyen
* Demo PSP

If the PSP you want to work with isn’t on the list, reach out to <support@vgs.io>.
{% endstep %}

{% step %}

### Initiate the payment transaction to your PSP

After enabling the outbound route to your PSP, include the `vgs-network-token: yes` header and send a regular request.

Below are examples for Cybersource showing: original request, transformed Network Token request, PAN fallback, and a sample response.

Original request:

{% code title="Cybersource - Request (aliased PAN)" %}

```json
{
  "clientReferenceInformation": {
    "code": "PaymentReferenceCode"
  },
  "paymentInformation": {
    "card": {
      "number": "tok_sandbox_dklas09asdmasdfssd9",
      "expirationMonth": "08",
      "expirationYear": "24"
    }
  },
  "orderInformation": {
    "amountDetails": {
      "totalAmount": "1",
      "currency": "USD"
    },
    "billTo": {
      "firstName": "John",
      "lastName": "Doe",
      "address1": "548 Market St",
      "locality": "Los Angeles",
      "administrativeArea": "CA",
      "postalCode": "94104",
      "country": "US",
      "email": "test@cybs.com"
    }
  }
}
```

{% endcode %}

Transformed Network Token request:

{% code title="Cybersource - Tokenized Request" %}

```json
{
  "clientReferenceInformation": {
    "code": "PaymentReferenceCode"
  },
  "paymentInformation": {
    "tokenizedCard": {
      "assuranceLevel": "07",
      "cryptogram": "AAA1sshfgdDVdsAafgjdsax",
      "expirationMonth": "12",
      "expirationYear": "2027",
      "number" :"4444444444444444"
    }
  },
  "orderInformation": {
    "amountDetails": {
      "totalAmount": "1",
      "currency": "USD"
    },
    "billTo": {
      "firstName": "John",
      "lastName": "Doe",
      "address1": "548 Market St",
      "locality": "Los Angeles",
      "administrativeArea": "CA",
      "postalCode": "94104",
      "country": "US",
      "email": "test@cybs.com"
    }
  }
}
```

{% endcode %}

PAN fallback request:

{% code title="Cybersource - PAN Fallback" %}

```json
{
  "clientReferenceInformation": {
    "code": "PaymentReferenceCode"
  },
  "paymentInformation": {
    "card": {
      "number": "4242424242424242",
      "expirationMonth": "08",
      "expirationYear": "24"
    }
  },
  "orderInformation": {
    "amountDetails": {
      "totalAmount": "1",
      "currency": "USD"
    },
    "billTo": {
      "firstName": "John",
      "lastName": "Doe",
      "address1": "548 Market St",
      "locality": "Los Angeles",
      "administrativeArea": "CA",
      "postalCode": "94104",
      "country": "US",
      "email": "test@cybs.com"
    }
  }
}
```

{% endcode %}

Sample response:

{% code title="Cybersource - Sample Response" %}

```json
{
    "_links": {
        "authReversal": {
            "method": "POST",
            "href": "/pts/v2/payments/123456789012345678901234567890/reversals"
        },
        "self": {
            "method": "GET",
            "href": "/pts/v2/payments/12345678901234567890"
        },
        "capture": {
            "method": "POST",
            "href": "/pts/v2/payments/123456789012345678901234567890/captures"
        }
    },
    "clientReferenceInformation": {
        "code": "YOURREFERENCE"
    },
    "id": "6920293736436626204988",
    "orderInformation": {
        "amountDetails": {
            "authorizedAmount": "1.00",
            "currency": "USD"
        }
    },
    "paymentAccountInformation": {
        "card": {
            "type": "001"
        }
    },
    "paymentInformation": {
        "tokenizedCard": {
            "type": "001"
        },
        "card": {
            "type": "001"
        }
    },
    "pointOfSaleInformation": {
        "terminalId": "0100123748"
    },
    "processorInformation": {
        "approvalCode": "123455I",
        "networkTransactionId": "1234567890",
        "transactionId": "12345678901234567890",
        "responseCode": "100",
        "avs": {
            "code": "N",
            "codeRaw": "I8"
        }
    },
    "reconciliationId": "1234567890HP",
    "status": "AUTHORIZED",
    "submitTimeUtc": "2023-08-14T16:09:34Z"
}
```

{% endcode %}
{% endstep %}
{% endstepper %}

## Set up Notifications

After a Network Token has been enrolled, there are events that may occur to update the status of the Network Token. You may receive these status updates via our Webhook integration, or may notice them on the Usage Reports section of your organization's Dashboard. Set up a webhook to receive Network Token updates by following these [setup instructions](/cmp/developer-resources/guides/testing/network-tokens-webhooks).

## Going Live Checklist

### Activate your Organization

To activate an organization, click on the Activate Organization button next to your Organization name. Organization activation is a simple process: you fill out some basic personal profile information and your company information.

### Create a Live Vault

Once you’ve activated your organization, you can create a Live Vault by hovering your cursor over your Vault list and clicking on “+ New” and then choosing “Live” as the environment.

### Live cards migration (optional)

If you need to, you can migrate your existing live cards into the vault using the following process: [Migrations](/cmp/developer-resources/api/credential-management-v1-apis-calm).

### Obtain a Token Requester ID for your Live Vault

> VGS has integrated directly with Visa and Mastercard to offer Network Token to its merchants. If you need a Network Token from other card networks (American Express, Discover etc.), contact <support@vgs.io>.

Go to the Network Tokens section in your Live Vault side menu bar, and press the **Complete TRID form** button. Follow the instructions and submit the necessary information about your business and contact details. Based on the card network, it might take up to 2 business days to receive onboarding confirmation. Look for the confirmation email from VGS. Once you receive it, proceed with the setup below.

### Set up authentication and API Credentials for your Live Vault

The VGS Network Tokenization APIs use OAuth 2.0 Client Credentials flow for authentication. This API is intended for server-to-server communication. The steps to set this up with VGS are detailed above: [Authentication and API Credentials](/cmp/platform/authentication).

### Enable the Network Tokens API & your PSP integration in your Live Vault

To promote your Sandbox integration from Sandbox to Live, use our [YAML](file:///3056465/platform-insights/dashboard/yaml.md) feature.

### Set up Notifications in Live

Follow the same steps described [here](/cmp/developer-resources/guides/testing/network-tokens-webhooks) to set up notifications in the live environment.

### Verify your live configurations

Perform test transactions using your company's internal cards, or reach out to Customer Support at <support@verygoodsecurity.com> to verify your live configuration of network tokens.

### Begin sending customer transactions through your integration!

Once you have completed the steps above, and verified your integration, you can begin processing live customer transactions through VGS Network Tokens.

## Glossary

* Tokenization is the act of securely redacting and storing sensitive information in your VGS Vault.
* A token is a piece of information stored within the VGS Vault. You can store up to 20 tokens in one API call.
* A network token is a secure digital representation of a payment card, used to facilitate transactions between merchants and customers.
* Inbound routes handle the passing of data from end users to your application repository using the VGS proxy to tokenize the data.
* Outbound routes handle the passing of data from your application repository to a third party, such as a card processor, using the VGS proxy to reveal the data.


# Network Tokens Onboarding - V1

{% stepper %}
{% step %}

### Get access token

In order to get an access token please see [Authentication guide](/cmp/platform/authentication#id-2-generate-access-token).
{% endstep %}

{% step %}

### Onboard an organization

Every organization needs to be registered at ‘Visa Token Services (VTS) program’ for VISA and Mastercard Digital Enablement Services (MDES) for Mastercard to receive a TRID (Token Requestor ID - unique merchant identifier at the schemes) before you can start using Network Tokens with VGS. A Token Requestor ID - TRID is used by Visa and Mastercard to provision merchant specific network tokens. Using `merchants` endpoint you can register for both Visa and Mastercard.

{% code title="Onboard merchant (curl)" %}

```bash
curl --location -X POST https://calm.<ENVIRONMENT>.verygoodsecurity.app/merchants \
    -H "Authorization: Bearer ${VGS_ACCESS_TOKEN}" \
    -H "Content-Type: application/json" \
    -x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 \
    --data-raw '{
          "dba_merchant_trade_name": "Example Company",
          "merchant_legal_name": "Example Company",
          "merchant_code": "1234",
          "company_website_url":"https://example.com",
          "acquirer_identification":"1234546",
          "acquirer_merchant_id":"123456",
          "contact_name":"John Doe",
          "contact_email":"jonh.doe@example.com",
          "duns_number":"123456789",
          "vault_id":"tntabcd1234",
          "organization_id":"ACrBqp51jFkn4CCaJEX3kf9j",
          "billing_address": {
              "address1": "Powell 12345",
              "address2": "54321",
              "city": "SF",
              "region": "CA",
              "country": "US",
              "postal_code": "12345",
              "phone": "+1(408)1112233"
          }
}'
```

{% endcode %}

You should receive a similar response:

{% code title="Successful response (example)" %}

```json
{
    "data": {
        "id": "MCcrYWJWqSbN1y9TXDnkvEiu",
        "merchant_legal_name": "Example Company",
        "card_networks": [
            {
                "network": "VISA",
                "created_at": "2023-05-09T11:54:16.273795",
                "updated_at": "2023-05-09T11:54:16.273795",
                "state": "COMPLETED"
            },
            {
                "network": "MASTERCARD",
                "created_at": "2023-05-09T11:54:16.273795",
                "updated_at": "2023-05-09T11:54:16.273795",
                "state": "PENDING"
            }
        ],
        "created_at": "2023-05-09T11:54:17.657088",
        "updated_at": "2023-05-09T11:54:17.659997"
    }
}
```

{% endcode %}

Example of failing onboarding request:

{% code title="Error response (example)" %}

```json
{
    "errors": [
        {
            "code": "internal-server-error",
            "detail": "Something went wrong.",
            "traceId": "00000000000000000000000000000000"
        }
    ]
}
```

{% endcode %}

{% endstep %}
{% endstepper %}

### What's next?

* [Network Tokens guide](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-onboarding-v1)
* [API docs](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1)


# Network Tokens API - V1


# Delete Network Token - V1

> To try it out today, email us at <support@verygoodsecurity.com>

## Delete a network token

Calling the Network Token API with the DELETE HTTP method will delete an already provisioned network token and the card information.

{% hint style="info" %}
Prerequisites:

You will need a valid `bearer_token` to issue Enrollment API calls. Please see the [Authentication guide](broken://pages/f6a564c267bb5994ddcaa79bd458c43459c7afa9) for how to create one.
{% endhint %}

### Deleting the token

<details>

<summary>View API specifications for DELETE /network-tokens/{pan_alias}</summary>

</details>

### What's next?

* [Transactions with Network Tokens](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1/transaction-with-network-token-v1)
* [API docs](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1)


# Authentication - V1

## API Credentials

The VGS Network Tokenization APIs use [OAuth 2.0 Client Credentials flow](https://oauth.net/2/grant-types/client-credentials/) for authentication. This API is intended for server-to-server communication, and no user is involved in the authentication process. The steps to set this up with VGS are detailed below.

{% stepper %}
{% step %}

### Generate a Service Account

API credentials can be generated using a [Service Account](/cmp/platform/authentication#id-1-generate-service-account) with the [VGS CLI](/cmp/platform/authentication#id-1-generate-service-account).

The service account configuration can be generated for your vault by executing the sample code below, which will create a **credentials.yaml** file:

{% code title="Generate service account" %}

```bash
vgs generate service-account -t calm --var vault_id=<VAULT_ID> > credentials.yaml
```

{% endcode %}

Your **credentials.yaml** file will contain the following code:

```yaml
apiVersion: 1.0.0
  kind: ServiceAccount
  data:
    annotations:
      "vgs.io/vault-id": "<VAULT_ID>"
    name: calm
    scopes:
      - name: cards:write
      - name: network-tokens:write
```

If needed, you can change the **name** field, and add/remove [scopes](/cmp/platform/authentication#id-1-generate-service-account) according to your needs in the `credentials.yaml` file.

{% hint style="warning" %}
Do not remove the **vgs.io/vault-id** annotation field. Requests are authorized per-vault; you may modify this field to contain the Vault ID that you want to use with Network Tokens.
{% endhint %}
{% endstep %}

{% step %}

### Generate Credentials

Apply the service account configuration stored in the **credentials.yaml** file with your organization ID by executing the following code:

{% code title="Apply service account" %}

```bash
vgs apply service-account -O <ORGANIZATION_ID> -f credentials.yaml
```

{% endcode %}

After executing, you should receive the following output, containing your credentials:

```yaml
apiVersion: 1.0.0
  kind: ServiceAccount
  data:
    clientId: <CLIENT_ID>
    clientSecret: <CLIENT_SECRET>
    name: calm
    scopes:
      - name: cards:write
      - name: network-tokens:write
```

{% hint style="warning" %}
Please make sure always to store these credentials in a secure environment. They should never be exposed.
{% endhint %}

Generated credentials can be located on the [VGS Dashboard](https://dashboard.verygoodsecurity.com) under the Organization Settings page:

Please note that `Write` organization access is required for credentials to work (set by default).
{% endstep %}
{% endstepper %}

## How To Authenticate

The VGS API authentication server is available at [https://auth.verygoodsecurity.com](https://auth.verygoodsecurity.com/).

To authenticate with the VGS Network Tokens API, use the `CLIENT_ID` and `CLIENT_SECRET` generated in the previous step to create a `Bearer` access token.

Example cURL request for obtaining an access token:

{% code title="Obtain access token" %}

```bash
curl -X POST \
-d "client_id=<CLIENT_ID>" \
-d "client_secret=<CLIENT_SECRET>" \
-d "grant_type=client_credentials" \
"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token"
```

{% endcode %}

Example response:

```json
{
 "access_token":"...",
 "expires_in":300,
 "refresh_expires_in":0,
 "token_type": "bearer",
 "not-before-policy":1620379100,
 "scope": "cards:write user_id service-account",
}
```

{% hint style="info" %}
The generated token can be used with the Network Token APIs only within the vault specified in the **vgs.io/vault-id** annotation field. The `access_token` is valid for 5 minutes. After that, obtain a new access token using the same process. `refresh_token` should not be used.
{% endhint %}

Pass the created `access_token` in the `Authorization: Bearer ${VGS_ACCESS_TOKEN}` header in each API call.

## How To Revoke Credentials

In case you need to revoke access to payment optimization services for particular credentials, there are two ways to do this:

* Using the VGS CLI (preferred):

{% code title="Revoke with VGS CLI" %}

```bash
vgs delete service-account <CLIENT_ID> -O <ORGANIZATION_ID>
```

{% endcode %}

* Remove the user named `<CLIENT_ID>@vgs.dev` from your Organization using the VGS Dashboard, under the Organization Settings page.

## Scopes

[OAuth 2.0 scopes](https://oauth.net/2/scope/) allow you to specify the level of API access required. Since API credentials are limited per vault, API scopes are limited only for that vault as well. Once an access token is granted via [authentication flow](/cmp/platform/authentication#id-2-generate-access-token), scopes can be located in the issued JWT.

[Network Token API credentials](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1) can have the following scopes:

| Scope                  | Permission                                     |
| ---------------------- | ---------------------------------------------- |
| `cards:write`          | Enroll and manage a card in VGS Network Tokens |
| `cards:read`           | Read details about the enrolled card           |
| `network-tokens:write` | Enroll and manage a VGS network token          |
| `network-tokens:read`  | Read details about the enrolled network tokens |

### What's next?

* [Enroll a Network Token](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1/network-tokens-bulk-enrollment-v1)
* [API docs](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1)


# Network Tokens Bulk Enrollment - V1

If you already have a set of cards that you want to enroll in Network Tokens, you may consider backbook/bulk enrollment. You will need to submit a .csv file with the required set of headers in the file, and VGS will take care of all other steps for you.

{% hint style="info" %}
Prerequisites

* You must have valid VGS aliases that point to the PAN of the cards from a production vault on your VGS dashboard.
* Enrollment in VGS Network Tokens.
* Completion of Network Tokens "Token Requester IDs (TRIDs)" registration.
* The VGS Support toggle must be enabled for your organization. VGS Support will access your organization to configure routes and access credentials for enrollment.
  {% endhint %}

## Enrollment Data Format

When you perform bulk enrollment of cards to VGS Network Tokens, the vital part is the format of your card data. Please see here for a sample file: <https://www.verygoodsecurity.com/docs/vgs\\_theme/static/vgs-nt-sample-file.csv>

The table below contains the CSV file fields, which are required or optional:

| Column Headers/Fields | Field Type | Description                                     |
| --------------------- | ---------- | ----------------------------------------------- |
| pan\_alias            | Required   | VGS alias representing the PAN                  |
| exp\_month            | Required   | Expiration month on the card                    |
| exp\_year             | Required   | Expiration year on the card                     |
| name                  | Optional   | Name of the user on the card                    |
| company               | Optional   | Company registered on the card                  |
| address1              | Optional   | Address1 of the user registered on the card     |
| address2              | Optional   | Address2 of the user registered on the card     |
| city                  | Optional   | City of the user registered on the card         |
| region                | Optional   | Region of the user registered on the card       |
| country               | Optional   | Country of the user registered on the card      |
| postal\_code          | Optional   | Postal Code of the user registered on the card  |
| phone                 | Optional   | Phone Number of the user registered on the card |

{% hint style="warning" %}
The header row is required for all columns/fields. Data for optional columns/fields can be left empty.
{% endhint %}

## Sending VGS your Enrollment Data

You will need to submit a CSV file to VGS for us to process your backbook/bulk enrollment of your cards. VGS will create an SFTP connection specific to your organization and share the credentials with you. To get started, contact <support@verygoodsecurity.com> and provide the information below.

{% stepper %}
{% step %}

### Provide organization details to <support@verygoodsecurity.com>

Include the following in your message:

* Organization Name
* VGS Organization ID
* VGS PROD Vault ID
* Contact Email
* Contact Phone
  {% endstep %}

{% step %}

### Receive SFTP credentials

VGS Support will share the SFTP credentials in a protected link with the contact email provided, typically within 48 hours.
{% endstep %}

{% step %}

### Upload your CSV

Use the provided SFTP credentials to upload your CSV file to the designated location.
{% endstep %}

{% step %}

### File processing and response

Once the file is processed, a response file will be generated in the same SFTP location. VGS Support will notify the contact email when processing starts/completes.

You can see a sample response file here: <https://www.verygoodsecurity.com/docs/vgs\\_theme/static/vgs-nt-processed-sample.csv>

If you have issues connecting to SFTP or need troubleshooting, reach out to <support@verygoodsecurity.com>.
{% endstep %}
{% endstepper %}

## Next Steps

{% stepper %}
{% step %}
Submit your backbook enrollment using the CSV file format specified and inform VGS support at <support@verygoodsecurity.com>.
{% endstep %}

{% step %}
VGS Support will notify the contact email provided once the file is processed. Processing starts within 48 hours; completion time depends on the number of cards to be enrolled.
{% endstep %}

{% step %}
After bulk enrollment of your existing cards, continue enrolling/provisioning Network Tokens for new cards using the Single Card enrollment/provisioning method: enroll-network-token.md
{% endstep %}
{% endstepper %}


# Transaction with Network Token - V1

Performing transactions with VGS Network Tokens is functionally the same as performing them with a VGS aliased PAN.

Below we go through the requirements and the logic that occurs in the process of making a payment request with a VGS Network Token.

Requirements:

* You must have a valid VGS alias which points to the PAN of the card
* The underlying card PAN must have been successfully enrolled as a Network Token
* A configured VGS outbound route to your 3rd party PSP to authorize the payment

## 1. The vgs-network-token header

Whether or not a Network Token is used for a request is determined by the `vgs-network-token` header on the request that is sent to VGS.

Set the header value as shown below:

| vgs-network-token | Result      |
| ----------------- | ----------- |
| yes               | NT used     |
| any other value   | NT not used |

## 2. Token cryptogram and PANs

VGS will determine whether to use a token cryptogram or PAN based on the configured 3rd party's support for Network Tokens.

| Brand                 | NT Provision Status                 | PSP that supports cryptogram                                                                                                                                 | PSP that does not support cryptogram                                                                                                   |
| --------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| Visa                  | Not Provisioned                     | VGS will use the PAN+CVV (if available) or PAN only for the transaction                                                                                      | VGS use the PAN+CVV (if available) or PAN only for the transaction                                                                     |
|                       | Provisioned                         | VGS will dynamically use shorter or longer form of cryptogram based on PSP readiness, and fallback to PAN+CVV (if available) or PAN only for the transaction | VGS will use shorter form of cryptogram based on PSP readiness, and fallback to PAN+CVV (if available) or PAN only for the transaction |
| Mastercard            | Not Provisioned                     | VGS will use the PAN+CVV (if available) or PAN only for the transaction                                                                                      | VGS use the PAN+CVV (if available) or PAN only for the transaction                                                                     |
|                       | Provisioned                         | VGS will use longer form of cryptogram based on PSP readiness, and fallback to PAN+CVV (if available) or PAN only for the transaction                        | VGS use the PAN+CVV (if available) or PAN only for the transaction                                                                     |
| Visa/Mastercard/Other | N/A, Inactive, Suspended or Deleted | VGS will use the PAN+CVV (if available) or PAN only for the transaction                                                                                      | VGS use the PAN+CVV (if available) or PAN only for the transaction                                                                     |

> If a Network Token is provisioned, and your PSP supports Network Tokens, but an error occurs in fetching the cryptogram, we will use the PAN.

## 3. Sending a Request to your PSP

Customers can initiate transactions using VGS Network Tokens by generating a unique cryptogram, commonly referred to as TAVV (Token Authentication Verification Value). This cryptogram is specific to the network token and can be up to 32 characters long. When submitting transactions, networks may require merchants to specify the transaction type explicitly during cryptogram generation. VGS supports two primary transaction types:

{% stepper %}
{% step %}

### Ecommerce (ECOM)

This is the default type for most transactions.

Example: Default Transaction Type: ECOM

{% code title="cURL (ECOM example)" %}

```bash
curl --location -X POST PSP_URL \
  -H "Authorization: Bearer ${VGS_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -x https://<USERNAME>:<PASSWORD>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 \
  --data-raw '{
     "amount": {
        "currency": "USD",
        "value": 1000
     },
     "reference": "Your order number",
     "paymentMethod": {
        "number": "VGS_ALIAS",
     },
     "returnUrl": "https://your-company.com/...",
     "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
  }'
```

{% endcode %}
{% endstep %}

{% step %}

### Account Funding Transaction (AFT)

This type is specifically for account funding transactions.

To initiate an AFT transaction, include the header `vgs-cryptogram-txn-type` with the value `AFT` in your request.

{% code title="cURL (AFT example)" %}

```bash
curl --location -X POST PSP_URL \
  -H "Authorization: Bearer ${VGS_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "vgs-cryptogram-txn-type: AFT" \
  -x https://<USERNAME>:<PASSWORD>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 \
  --data-raw '{
     "amount": {
        "currency": "USD",
        "value": 1000
     },
     "reference": "Your order number",
     "paymentMethod": {
        "number": "VGS_ALIAS"
     },
     "returnUrl": "https://your-company.com/...",
     "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
  }'
```

{% endcode %}
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Visa-Specific Requirement: For Visa transactions, it's mandatory to specify the `AFT` transaction type when fetching the cryptogram for account funding transactions.

Other networks typically default to the `ECOM` type unless explicitly specified.
{% endhint %}

VGS Network Token Usage

Sending a payment request using VGS Network Tokens functions similarly to using a VGS-aliased PAN. The same transaction type considerations apply when generating cryptograms.

VGS will populate the payload with all the data needed for a successful transaction with your Network Tokens. For example, the following will be utilized for Adyen’s payment with Network Tokens:

{% code title="Example payload (Adyen with Network Tokens)" %}

```json
"paymentMethod": {
  "type": "networkToken",
  "brand": "visa",
  "expiryMonth": "08",
  "expiryYear": "2020",
  "holderName": "CARDHOLDER_NAME",
  "number": "666666xxxxxx6666"
},
"mpiData": {
  "directoryResponse": "Y",
  "authenticationResponse": "Y",
  "cavv": "AAEBAwQjSQAAXXXXXXXJYe0BbQA=",
  "eci": "05"
}
```

{% endcode %}

{% code title="Additional paymentMethod example" %}

```json
"paymentMethod": {
  "type": "networkToken",
  "brand": "visa",
  "expiryMonth": "08",
  "expiryYear": "2020",
  "holderName": "CARDHOLDER_NAME",
  "number": "666666xxxxxx6666",
  "networkPaymentReference": "MCC123456789012"
}
```

{% endcode %}

### Example PSP response (Adyen)

{% code title="Adyen - Authorised response" %}

```json
{
  "additionalData": {
    "cardBin": "489537",
    "cardSummary": "3416",
    "PaymentAccountReference": "123456",
    "recurringProcessingModel": "CardOnFile",
    "paymentMethod": "visa",
    "networkTxReference": "393657085380164"
  },
  "pspReference": "NN8W2T8XCVTFWR82",
  "resultCode": "Authorised",
  "amount": {
    "currency": "USD",
    "value": 1000
  },
  "merchantReference": "afd8c4d3-c0c2-4737-a8c9-ade8229771d5",
  "paymentMethod": {
    "brand": "visa",
    "type": "networkToken"
  }
}
```

{% endcode %}

{% code title="Adyen - Refused response" %}

```json
{
  "additionalData": {
    "cardBin": "489537",
    "cardSummary": "0010",
    "PaymentAccountReference": "123456",
    "recurringProcessingModel": "CardOnFile",
    "paymentMethod": "visa"
  },
  "pspReference": "DM2GW4RSLV5X8N82",
  "refusalReason": "Refused",
  "resultCode": "Refused",
  "refusalReasonCode": "2",
  "merchantReference": "bf4ef8c1-a0b5-477c-8d0d-e851646c8564"
}
```

{% endcode %}

Note: Successful and failed responses may look different if you are using a different PSP.

## What's next?

* [API docs](/cmp/developer-resources/api/credential-management-v1-apis-calm/network-tokens-v1/network-tokens-api-v1)


# Network Tokens Events

#### Network Tokens Events

After a Network Token has been enrolled, there are a few key events that may occur. These fall into two broad categories:

* Lifecycle Events: These represent billable actions that typically result in a change to the card metadata or indicate successful provisioning.
* Status Updates: These reflect changes to the token's status (e.g., suspended or deleted) and are not billable. You may receive these events via our Webhook integration or view them in the Usage Reports section of your organization's Dashboard. Below is an explanation of each:

<table><thead><tr><th width="134.173583984375">Network Token Status</th><th width="134.40191650390625">VGS Network Token State</th><th width="256.7022705078125">VGS Reason Code</th><th width="206.390869140625">Description</th><th width="208.11090087890625">Classification Type</th></tr></thead><tbody><tr><td>Updated</td><td>updated</td><td><code>network_token.updated</code></td><td>The network has updated the card metadata</td><td>Lifecycle Event</td></tr><tr><td>Activated</td><td>activated</td><td><code>network_token.activated</code></td><td>A network token has been activated following a suspension.</td><td>Status Update</td></tr><tr><td>Suspended</td><td>suspended</td><td><code>network_token.suspended</code></td><td>A network token has been suspended by the issuing card network (Mastercard, Visa, etc).</td><td>Status Update</td></tr><tr><td>Deleted</td><td>deleted</td><td><code>network_token.deleted</code></td><td>A network token has been deleted via the API, or a Delete was triggered from the issuing bank</td><td>Status Update</td></tr></tbody></table>

#### Network Tokens Provisioning Errors

| Network    | Status/Error Code                           | Description                                                                                                                                            |
| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Visa       | 400 - InvalidParameter                      | These declines means that Visa declined it before sending to issuer because the PAN information is invalid.                                            |
| Visa       | 400 - card\_enrollment\_failed              | Invalid payment instrument or data associated with the payment instrument; Invalid input to pan/expiry date.                                           |
| Visa       | 403- card\_not\_allowed                     | Card cannot be used for tokenization at this moment. Please try again later. Something is wrong with the PAN itself. The PAN was expired for instance. |
| Visa       | 403 - declined                              | This card is not eligible for tokenization at this moment with the Network; Retry at a later time.                                                     |
| Visa       | 409 - declined                              | No further operations are allowed. Contact bank                                                                                                        |
| Visa       | 500 -Service Unavailable                    | Downstream service unavailable; retry later.                                                                                                           |
| Visa       | 503 -notReady                               | The server is currently unable to handle the request due to a temporary overloading or maintenance of the server.                                      |
| Mastercard | <p>400 -</p><p>card\_enrollment\_failed</p> | Invalid payment instrument or data associated with the payment instrument; Invalid input to pan/expiry                                                 |
| Mastercard | 403 -rejected                               | This card is not eligible for tokenization at this moment with the Network; Retry later.                                                               |
| Mastercard | 503 -Service Unavailable                    | Downstream service unavailable; retry later                                                                                                            |
| Mastercard | 503 -Service Unavailable                    | Downstream service unavailable; retry later                                                                                                            |

#### Network Tokens Crypto Fetch Network Errors

| Network    | Status/Error Code      | Description                                                                                                                                  |
| ---------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Visa       | 403 - declined         | This card is not eligible for tokenization at this moment with the Network; Retry at a later time.                                           |
| Visa       | 409 - declined         | No further operations are allowed. Contact bank                                                                                              |
| Visa       | 400 - rejected         | Invalid payment instrument or data associated with the payment instrument; Invalid input to pan/expiry date.                                 |
| Mastercard | 400 invalid\_argument  | Incorrect/missing fields or values.                                                                                                          |
| Mastercard | 401 - cannot\_be\_null | The request contains card type, but the card type does not correspond with the card number (e.g. card type = Visa; card number = MasterCard) |


# Account Updater - V1

{% hint style="warning" %}
**Important Notice:** Clients who are signed up to the Card Management Platform (CMP) should navigate to this [page](https://docs.verygoodsecurity.com/card-management).
{% endhint %}

Account Updater bridges the gap between card issuers and merchants, seamlessly delivering updated card information directly into your hands. No more chasing customers for new details or wrangling with failed payments. This powerful network tool empowers you to:

* Boost authorization success rates: Minimize declined transactions and ensure smooth recurring payments for subscription models.
* Reduce customer churn: Offer a frictionless checkout experience that keeps customers happy and engaged.
* Simplify workflows: Eliminate manual updates and focus on building your business instead of chasing card details.
* Enhance security: Leverage secure and encrypted data exchange to protect both you and your customers. VGS Account Updater simplifies connection to payment networks, automatically fetching and delivering updated card information to merchants, ensuring seamless recurring payments and reducing customer churn.

### Onboarding

{% stepper %}
{% step %}

### Timeline

The process of onboarding into the VGS Account Updater Service from the Card Networks typically requires up to \~10 business days. You must submit paperwork as either a merchant or a payment facilitator via a digital document.
{% endstep %}

{% step %}

### Submit the Merchant Onboarding Form

[Please download and fill out this Merchant Onboarding Form](https://www.verygoodsecurity.com/docs/vgs_theme/static/vgs-account-updater-merchant-onboarding.xlsx). After completing the form, email the updated file to VGS Support (<support@vgs.io>) and your VGS account manager.
{% endstep %}

{% step %}

### VGS completes registration

After paperwork is submitted, VGS will register the merchant with the networks, generate unique identifiers, and finalize the onboarding process.
{% endstep %}
{% endstepper %}

### Integration with VGS

Once VGS receives your merchant details and enables Account Updater on your account, you will be able to access the [Account Updater API](/cmp/developer-resources/api/account-updater) using either the `account updater` [credentials](/cmp/platform/authentication#id-3-generate-access-credentials).

### Reference

* [Quickstart](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1)
* [VGS Account Updater API documentation](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1/api-reference-v1/enroll-card-v1)
* [VGS Account Updater Notifications](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1/api-reference-v1/account-updater-notifications-v1)


# Quickstart - V1

> You need to have **VGS CLI** version **>=1.9.4** installed.

Get your cards enrolled with the VGS Account Updater to increase authorization acceptance of your payments. Follow these simple steps to get started.

## Setup Outbound Route

To import the route configuration file on your VGS dashboard, follow these steps:

{% stepper %}
{% step %}

### Using the Dashboard

* Navigate to the Addons section in your sandbox vault.
* Select VGS CALM from the route template options.
* Enable the switch for Account-Updater.\
  This will automatically add the route to your sandbox vault.
  {% endstep %}

{% step %}

### Using VGS CLI

Alternatively, configure the route by importing the route configuration file [(au\_outbound.yaml)](https://www.verygoodsecurity.com/docs/vgs_theme/static/yaml/au_outbound.yaml) using the VGS CLI. Run the following command:

```bash
vgs apply routes --vault <YOUR-VAULT_ID> -f au_outbound.yaml
```

Example of CLI command:

```bash
vgs apply routes --vault tntmhqqg8ew -f au_outbound.yaml
```

{% endstep %}
{% endstepper %}

## Obtain API Credentials

Integration with VGS Account Updater can start as soon as you create a [service account](/cmp/platform/authentication#id-1-generate-service-account) with VGS CLI:

> If Payment Orchestration credentials have already been provided by VGS Support, this section can be skipped. Use the Client ID and Secret provided by VGS Support to access the VGS Account Updater API

{% stepper %}
{% step %}

### Create Service Account

```bash
vgs generate service-account -t calm --var vault_id=YOUR-VAULT-ID > ./calm-credentials.yaml
vgs apply service-account -O YOUR-ORGANIZATION-ID -f ./calm_credentials.yaml
```

{% endstep %}

{% step %}

### Obtain Access Token

To obtain an access token with created credentials:

```bash
curl -X POST \
-d "client_id=<CLIENT_ID>" \
-d "client_secret=<CLIENT_SECRET>" \
-d "grant_type=client_credentials" \
"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token"
```

Visit [Authentication](/cmp/platform/authentication) for more details and code snippets.
{% endstep %}
{% endstepper %}

## Enroll Card in VGS Account Updater

Below is a diagram detailing how card data will flow to and from a customer's servers.

### Request Body Fields

The table below contains more details on the request body fields, which are required and which are optional.

| Field               | Field Type                                                                                                                                                        | Description                                                                                                                                    |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| name                | Required                                                                                                                                                          | Name of the user on the card                                                                                                                   |
| number              | Required                                                                                                                                                          | VGS alias representing the PAN                                                                                                                 |
| exp\_month          | Required                                                                                                                                                          | Expiration month on the card                                                                                                                   |
| exp\_year           | Required                                                                                                                                                          | Expiration year on the card                                                                                                                    |
| billing\_address    | Optional                                                                                                                                                          | Billing address registered on the card                                                                                                         |
| company             | Optional                                                                                                                                                          | Company registered on the card                                                                                                                 |
| address1            | Optional                                                                                                                                                          | Address1 of the user registered on the card                                                                                                    |
| address2            | Optional                                                                                                                                                          | Address2 of the user registered on the card                                                                                                    |
| city                | Optional                                                                                                                                                          | City of the user registered on the card                                                                                                        |
| region              | Optional                                                                                                                                                          | Region of the user registered on the card                                                                                                      |
| country             | Optional                                                                                                                                                          | Country of the user registered on the card                                                                                                     |
| postal\_code        | Optional                                                                                                                                                          | Postal Code of the user registered on the card                                                                                                 |
| phone               | Optional                                                                                                                                                          | Phone Number of the user registered on the card                                                                                                |
| merchant            | Conditional Required (pass this value if you are submitting the card on behalf of a merchant or if you have multiple merchants registered for a single VGS vault) | "merchant" element in the request payload                                                                                                      |
| sub\_merchant\_name | Conditional Required (pass this value if you are submitting the card on behalf of a merchant)                                                                     | Merchant Name registered on the card                                                                                                           |
| vgs\_merchant\_id   | Conditional Required (required only if multiple merchants are registered per VGS vault for Account Updater)                                                       | VGS generated ID per merchant registered for VGS Vault. This ID is returned as a part of the merchant registration process for Account Updater |

The following cURL command will enroll your card in VGS Account Updater.

```bash
curl https://calm.<ENVIRONMENT>.verygoodsecurity.app/cards \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer \${VGS_ACCESS_TOKEN}" \
-d '{
      "name": "John Doe",
      "number": "5573495XTjZP21V7312",
      "exp_month": 7,
      "exp_year": 24
    }'
```

After submitting the enrollment request, an immediate synchronous response is generated confirming the successful initiation of the enrollment process for updates with the payment service provider. This response provides details about the request's status, along with the associated event type received on the card.

```json
{
  "data": {
    "id": "CRDuVQCsenqj6dbHFQq9gen2E",
    "name": "John Doe",
    "number": "5573495XTjZP21V7312",
    "exp_month": 7,
    "exp_year": 24,
    "capabilities": [
      "ACCOUNT_UPDATER"
    ],
    "created_at": "2019-05-15T12:30:45Z",
    "updated_at": "2019-05-15T12:30:45Z",
    "state": "enrolled",
    "event": "au_card.updated"
  }
}
```

### Response Body Fields

The table below provides detailed information about the fields in the synchronous response body for the Enroll Card request.

| Field            | Description                                                                                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id               | Serves as a unique identifier for the card within VGS Account Updater Service                                                                                                   |
| name             | Name of the user on the card                                                                                                                                                    |
| number           | VGS alias representing the PAN                                                                                                                                                  |
| exp\_month       | Expiration month on the card                                                                                                                                                    |
| exp\_year        | Expiration year on the card                                                                                                                                                     |
| billing\_address | Billing address registered on the card                                                                                                                                          |
| name             | Name of the user on the card                                                                                                                                                    |
| company          | Company registered on the card                                                                                                                                                  |
| address1         | Address1 of the user registered on the card                                                                                                                                     |
| address2         | Address2 of the user registered on the card                                                                                                                                     |
| city             | City of the user registered on the card                                                                                                                                         |
| region           | Region of the user registered on the card                                                                                                                                       |
| country          | Country of the user registered on the card                                                                                                                                      |
| postal\_code     | Postal Code of the user registered on the card                                                                                                                                  |
| phone            | Phone Number of the user registered on the card                                                                                                                                 |
| capabilities     | Indicates that the card is enrolled in the VGS Account Updater Service                                                                                                          |
| created\_at      | Timestamp indicating when the card was enrolled with VGS Account Updater                                                                                                        |
| updated\_at      | Timestamp indicating when an update was received for the card from the network                                                                                                  |
| state            | Current state of the card in VGS                                                                                                                                                |
| event            | Event or status update received from the network regarding the card. For more information on possible events, please refer to this [link.](/cmp/api-dev/account-updater-events) |

An asynchronous response is also sent via a webhook URL to you if the enrollment does not complete immediately. The synchronous response will have the `state: ENROLLING` and not the final state of the request.

Note: No webhook event is sent if the enrollment returns `state: ENROLLED` in the response immediately.

### Mock Responses and Test Cards

For test card numbers that you can use for testing in the Sandbox environment, see [Test Cards](https://docs.verygoodsecurity.com/cmp/developer-resources/guides/testing/create-card#method-3-account-updater-enrollment-for-visamastercard-cards-with-networks).

### Get Card

Get Card - Get information on registered cards

The following cURL command will get your card information from the VGS Account Updater.

```bash
curl --request GET https://calm.<ENVIRONMENT>.verygoodsecurity.app/cards/CRDuVQCsenqj6dbHFQq9gen2E \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer \${VGS_ACCESS_TOKEN}"
```

VGS Account Updater returns a Card object in response to your API request.

```json
{
  "data": {
    "id": "CRDuVQCsenqj6dbHFQq9gen2E",
    "name": "John Doe",
    "number": "5573495XTjZP21V7312",
    "exp_month": 7,
    "exp_year": 24,
    "capabilities": [
      "ACCOUNT_UPDATER"
    ],
    "created_at": "2019-05-15T12:30:45Z",
    "updated_at": "2019-05-15T12:30:45Z",
    "state": "enrolled",
    "event": "au_card.enrolled"
  }
}
```

### VGS States and Network Events

Outlined below are the VGS states corresponding to various event types received on a card from the network.

| Notification Type                    | Card State     | Event Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Response Changes Summary                                                                                                                                                                                                                                                                                                                   |
| ------------------------------------ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| au\_card.updated                     | enrolled       | <p>Account number change message<br><br>This event is triggered when a cardholder opens a new account with a participating issuer or when a new card is issued. For e.g. this could be due to new account creation, lost or stolen card, or when a card holder gets upgraded to Platinum or downgraded, or, due to a portfolio change (one bank to other).</p>                                                                                                                                           | <p>1. New VGS alias is returned in the “number” field in the response<br>2. New Expiration Month is returned in the “exp\_month” field in the response<br>3. New Expiration Year is returned in the “exp\_year” field in the response</p>                                                                                                  |
| au\_card.expired                     | enrolled       | <p>Expiration date change<br><br>This event denotes an expiration date change event. Whenever the card expires but has the same PAN, then, a new expiration date is issued. This event is an indication that the card expired (and so a new date is issued). Typically, cards have an expiration date of 2, 3 or x years (it used to be 5 but we rarely see them these days). Sometimes, an issuer can have an expiration for 1 year (for brand new card holders as they do not have enough credit).</p> | <p>1. New Expiration Month is returned in the “exp\_month” field in the response<br>2. New Expiration Year is returned in the “exp\_year” field in the response</p>                                                                                                                                                                        |
| au\_card.closed                      | closed         | <p>Closed account advice<br><br>This event is triggered when the issuer reports the closure of the cardholder's account i.e. cardholder's account associated with the particular card is no longer active/closed providing an important update for merchants to keep their records accurate and avoid attempting transactions with invalid or closed accounts.</p>                                                                                                                                       | Returned card data replicates the information provided in the request with the status as closed                                                                                                                                                                                                                                            |
| au\_card.non\_participating          | enrolled       | <p>Non-participating BIN<br><br>This event represents a non-participating BIN event, indicating that cards linked to these BINs will not receive updates through the Account Updater service. i.e. BIN of a particular card is not participating in the Account Updater service and merchants subscribed to AU will not receive updates for cards associated with non-participating BINs.</p>                                                                                                            | Returned card data replicates the information provided in the request with the status as enrolled                                                                                                                                                                                                                                          |
| au\_card.contact\_cardholder\_advice | enrolled       | <p>Contact cardholder advice<br><br>This event indicates the issuer is letting the merchant know that something has changed and the merchant should force the customer to key enter the credential and the update will not be shared via the account updater channel for the merchant. In short the merchant must contact the cardholder for more information or clarification.</p>                                                                                                                      | Returned card data replicates the information provided in the request with the status as enrolled                                                                                                                                                                                                                                          |
| au\_card.unknown                     | enrolled       | <p>Account not found response from a participating BIN<br><br>This event indicates that the card is eligible for automatic updates, but there are no match was found for this account.</p>                                                                                                                                                                                                                                                                                                               | Returned card data replicates the information provided in the request with the status as unknown                                                                                                                                                                                                                                           |
| au\_card.enrolled                    | enrolled       | <p>Match made, account number and expiration date unchanged<br><br>This event implies that the card is already enrolled for Account Updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.</p>                                                                                                                                                                                                                                 | Returned card data replicates the information provided in the request with the status as enrolled                                                                                                                                                                                                                                          |
| au\_card.opt\_out                    | enrolled       | <p>Cardholder Opt-Out Note (Stop Advice) is placed on a card<br><br>This event is triggered when the cardholder chooses to opt-out of the account updater service i.e. when the cardholder does not want their account information automatically updated through the AU service. Opting out is typically a deliberate choice made by the cardholder.</p>                                                                                                                                                 | Returned card data replicates the information provided in the request with the status as enrolled                                                                                                                                                                                                                                          |
| au\_card.valid                       | enrolled/valid | <p>Match made, account number and expiration date unchanged<br><br>This event is triggered when the network confirms that the card status remains unchanged. <strong>Match made, account number and expiration date unchanged</strong> - This event implies that the card is already enrolled for Account Updater services, confirming the card's account number and expiration date haven't changed (matched) since the last card update.</p>                                                           | <p><strong>au\_card.valid</strong> event is exclusively available in the real-time card-check API response. In the context of the cards/ API, the corresponding event is represented as <strong>au\_card.enrolled</strong>.<br><br><br>Returned card data replicates the information provided in the request with the status as valid.</p> |

### Receive Card Updates

Once a card is enrolled in VGS Account Updater, your server will receive updates on the registered card using [VGS Account Updater Notifications](https://docs.verygoodsecurity.com/cmp/developer-resources/api/credential-management-v1-apis-calm/account-updater-v1/api-reference-v1/account-updater-notifications-v1).

Note: Once a card update is received through the networks, the updated card information is generally considered usable. However, the timing and approach to updates can vary across issuers.

Issuer Practices:

* Some issuers send updates only after the cardholder activates the new physical card ("plastic").
* Others may allow the old and new card details to coexist temporarily, ensuring continuity in transactions during the transition.
* No Uniform Pattern: There is no single standardized pattern across all issuers. Each issuer follows its internal policies regarding when updates are shared and how it handles card transitions.

Merchants should consider these variations and ensure they accommodate both scenarios to minimize disruptions in recurring or tokenized transactions.

### Sample Code

For a new vault, the procedure is the same except that aliases should be created beforehand. See our [sample code](https://github.com/vgs-samples/calm-bulk-enrollment#testing-on-sample-data), which shows how to redact a sample card data in your vault.

### Reference

* [Getting Started with Account Updater](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1)
* [VGS Account Updater API documentation](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1/api-reference-v1/enroll-card-v1)
* [VGS Account Updater Notifications](https://docs.verygoodsecurity.com/cmp/developer-resources/api/card-management-v1-apis-calm/account-updater-v1/api-reference-v1/account-updater-notifications-v1)


# Card Check - V1

With `/card-check` you can effortlessly integrate with different networks to receive the current account information. This stateless API fetches real-time card updates without requiring card enrollment to the VGS Account Updater. It operates without persisting any state.

### Prerequisites

You will need a valid `bearer_token` to issue Enrollment API calls. Please see the [Authentication guide](/cmp/platform/authentication) for how to create one.

{% hint style="warning" %}
Limitations:

* **American Express** and **Discover** do not support real-time Account Updater lookups.
  * Amex: Updates are retrieved approximately every 30 minutes.
  * Discover: Updates are retrieved once daily.
* Updates for Amex and Discover are handled through batch-based file processing and delivered via webhooks.
  {% endhint %}

## Check a card for updates in VGS Account Updater

> Stateless api to fetch card updates without persisting any state\
> VGS Account Updater will perform both card availability and eligibility checks to check that this specific card is eligible for management.<br>

```json
{"openapi":"3.0.0","info":{"title":"VGS Account Updater and Network Tokens APIs","version":"1.0.0"},"tags":[{"name":"Account Updater","description":"Cards enrolled in VGS Account Updater."}],"servers":[{"url":"https://calm.sandbox.verygoodsecurity.app","description":"Sandbox"},{"url":"https://calm.live.verygoodsecurity.app","description":"Live"}],"security":[{"OAuth2":["cards:write"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token","scopes":{"cards:write":"Grants write access to cards","cards:read":"Grants read access to cards","network-tokens:write":"Grants access to perform operations with network tokens","network-tokens:read":"Grants read access to the network tokens","merchants:write":"Grants write access to Merchant API","merchants:read":"Grants read access to Merchant API","merchants:admin":"Grants admin access to Merchant API"}}}}},"requestBodies":{"CardCheckRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"}}}}},"schemas":{"Card":{"type":"object","description":"Payment card object.","required":["name","number","exp_month","exp_year"],"properties":{"name":{"maxLength":255,"description":"Card owner's full name.","type":"string"},"number":{"maxLength":19,"minLength":13,"pattern":"^(\\d{6}.{0,9}[a-zA-Z].{0,9}\\d{4}?)|((?:4[0-9]{12}(?:[0-9]{3})?)|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\\d{3})\\d{11})$","description":"Customer's card number.","type":"string"},"exp_month":{"description":"Card's expiration month.","type":"integer","minimum":1,"maximum":12},"exp_year":{"description":"Card's expiration year.","type":"integer","minimum":0,"maximum":99},"cvv":{"description":"Card's cvv","type":"string","pattern":"^\\d{3,4}$"},"merchant":{"description":"AU merchant details.","type":"object","properties":{"vgs_merchant_id":{"maxLength":255,"description":"VGS merchant id.","type":"string"},"sub_merchant_name":{"maxLength":255,"description":"Sub merchant name. Required if you are submitting the card on behalf of a merchant.","type":"string"},"sub_merchant_mid":{"maxLength":255,"description":"Sub merchant MID. In some cases required for PayFac customers","type":"string"}}}}},"CheckCardData":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/CheckedCard"}}},"CheckedCard":{"allOf":[{"$ref":"#/components/schemas/Card"},{"type":"object","properties":{"failure_code":{"type":"string","enum":["account-updater-not-supported","merchant-not-found","invalid-exp-date","invalid-payload","invalid-param","internal-server-error"],"description":"Application-specific failure code which can only occur with failed state:\n  * `account-updater-not-supported` - Account Updater is not implemented for your card issuer\n  * `merchant-not-found` - No merchant was registered for organization\n"},"event":{"type":"string","description":"Current state of a card being processed:\n  * `au_card.valid` - Card is valid. Current Account and Expiration Date returned\n  * `au_card.updated` - Card was updated. New Account and Expiration Date returned\n  * `au_card.expired` - Card was expired. New Expiration Date returned\n  * `au_card.closed` - Card was closed.\n  * `au_card.non_participating` - BIN is not participating in AU\n  * `au_card.contact_cardholder_advice` - Cardholder has opted out and the merchant needs to contact cardholder for information\n  * `au_card.unknown` - BIN is participating in AU but there is no match yet\n  * `au_card.enrolled` - PAN and expiration date the merchant provided is up-to-date\n  * `au_card.opt_out` - Cardholder has opted out sharing credential information with the merchants\n","enum":["au_card.valid","au_card.updated","au_card.expired","au_card.closed","au_card.non_participating","au_card.contact_cardholder_advice","au_card.unknown","au_card.enrolled","au_card.opt_out"]}}}]},"CardApiErrors":{"type":"object","required":["errors","trace_id"],"properties":{"errors":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/CardApiError"},{"$ref":"#/components/schemas/GeneralError"}],"description":"List of errors that occurred while processing the request.","minItems":1}},"trace_id":{"description":"A unique identifier of the failed request.","type":"string"}}},"CardApiError":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error_code":{"type":"string","enum":["card-brand-not-supported","account-updater-not-supported","card-not-found","merchant-not-found"],"description":"Application-specific error code:\n  * `card-brand-not-supported` - Specified card brand is not supported, only Mastercard cards are supported\n  * `account-updater-not-supported` - Account Updater is not implemented for your card issuer\n  * `card-not-found` - Card is not enrolled in CALM\n  * `merchant-not-found` - No merchant was registered for organization and provided capability\n"}}}]},"Error":{"type":"object","description":"An error object","properties":{"detail":{"description":"Explanation of what exactly went wrong.","type":"string"}}},"GeneralError":{"additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error_code":{"type":"string","enum":["internal-server-error","invalid-payload","validation-failed","unsupported-media-type"],"description":"Application-specific error code:\n  * `internal-server-error` - Something went wrong\n  * `invalid-payload` - Invalid request payload\n  * `validation-failed` - Request validation failed\n  * `unsupported-media-type` - Request media type is not supported\n"}}}]}},"responses":{"CardCheckResponse":{"description":"Card check API response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckCardData"}}}}}},"paths":{"/card-check":{"post":{"tags":["Account Updater"],"summary":"Check a card for updates in VGS Account Updater","description":"Stateless api to fetch card updates without persisting any state\nVGS Account Updater will perform both card availability and eligibility checks to check that this specific card is eligible for management.\n","operationId":"checkCard","requestBody":{"$ref":"#/components/requestBodies/CardCheckRequest"},"responses":{"202":{"$ref":"#/components/responses/CardCheckResponse"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardApiErrors"}}}},"404":{"description":"Vgs Merchant Not found\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralError"}}}},"422":{"description":"Unprocessable Entity. Possible error codes:\n  * `card-brand-not-supported`\n  * `account-updater-not-supported`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardApiErrors"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralError"}}}},"default":{"$ref":"#/components/responses/CardCheckResponse"}}}}}}
```

Example request:

{% code title="curl" %}

```bash
curl --X POST https://calm.<ENVIRONMENT>.verygoodsecurity.app/card-check \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${VGS_ACCESS_TOKEN}"
-d '{
      "name": "John Doe",
      "number": 5573491171027312,
      "exp_month": 7,
      "exp_year": 24
    }'
```

{% endcode %}

Example response:

{% code title="Response (application/json)" %}

```json
{
  "data": {
    "name": "John Doe",
    "number": "5574491271028432",
    "exp_month": 7,
    "exp_year": 24,
    "event": "au_card.updated"
  }
}
```

{% endcode %}

Note: An error response can contain multiple validation messages for the same field/element. Example of multiple validations in the response:

{% code title="Error response example" %}

```json
{
  "errors": [
    {
      "detail": "[number] size must be between 13 and 19",
      "error_code": "validation-failed"
    },
    {
      "detail": "[number] with invalid card number format",
      "error_code": "validation-failed"
    }
  ],
  "trace_id": "2d137f00cc53f5a9265f3b40402f7892"
}
```

{% endcode %}

### Request Body Fields

The table below contains more details on the request body fields, which are required, and which are optional.

| Field               | Field Type                                                                                                                                                        | Description                                                                                                                                    |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| name                | Required                                                                                                                                                          | Name of the user on the card                                                                                                                   |
| number              | Required                                                                                                                                                          | VGS alias representing the PAN                                                                                                                 |
| exp\_month          | Required                                                                                                                                                          | Expiration month on the card                                                                                                                   |
| exp\_year           | Required                                                                                                                                                          | Expiration year on the card                                                                                                                    |
| merchant            | Conditional Required (pass this value if you are submitting the card on behalf of a merchant or if you have multiple merchants registered for a single VGS vault) | "merchant" element in the request payload                                                                                                      |
| sub\_merchant\_name | Conditional Required (pass this value if you are submitting the card on behalf of a merchant)                                                                     | Merchant Name registered on the card                                                                                                           |
| vgs\_merchant\_id   | Conditional Required (required only if multiple merchants are registered per VGS vault for Account Updater)                                                       | VGS generated ID per merchant registered for VGS Vault. This ID is returned as a part of the merchant registration process for Account Updater |

{% hint style="info" %}
Billing note: You will be billed if any of the following events occur when this API is invoked: Updated, Closed, Expired, or CardHolder Advice. Additionally, there will be no webhook response for future updates.
{% endhint %}


# API Reference - V1

### Mock Responses for MasterCard

For testing purposes, in the sandbox environment the result of the card enrollment will depend on the card `number` used in the request.

The response will be available only after a card is enrolled (state changes to enrolled). During enrolling state, the response is not yet determined and initial card data is returned.

| Request              | Response                                       |
| -------------------- | ---------------------------------------------- |
| number ending with 2 | A no-change response (the card is still valid) |
| number ending with 3 | Card number updated response                   |
| number ending with 4 | Card account closed response                   |
| number ending with 5 | Card expiration date change response           |

For the following cases the state will change from enrolling to failed.

| Request                   | Response                      |
| ------------------------- | ----------------------------- |
| number ending with 1 or 7 | Account updater not supported |
| number ending with 6 or 8 | An example error response     |


# Authentication - V1

## API Credentials

Payment Optimization APIs use [OAuth 2.0 Client Credentials flow](https://oauth.net/2/grant-types/client-credentials/) for authentication. This API is intended for server to server communication, and no user is involved in the process.

### Generate Service Account

API credentials can be generated using [Service Account](/cmp/developer-resources/api/credential-management-v1-apis-calm/account-updater-v1/api-reference-v1/authentication-v1#generate-service-account) on VGS CLI:

Generate the service account configuration for your vault by executing the sample below, storing it in the **credentials.yaml** file

```bash
vgs generate service-account -t calm --var vault_id=<VAULT_ID> > credentials.yaml
```

Your **credentials.yaml** will look like below.

```yaml
apiVersion: 1.0.0
kind: ServiceAccount
data:
  clientId: <CLIENT_ID>
  clientSecret: <CLIENT_SECRET>
  name: calm
  scopes:
    - cards:write
    - cards:read
```

If needed, change the **name** and add/remove scopes according to your needs in `credentials.yaml` file.

> Annotation **vgs.io/vault-id** with your vault identifier is required to authorize requests that are specific to the vault that you want to use with Payment Optimization.

### Generate Credentials

Apply the service account configuration stored in the **credentials.yaml** with your organization ID and execute:

```bash
vgs apply service-account -O <ORGANIZATION_ID> -f credentials.yaml
```

As a result of the previous step, you will have an output that will look similar to:

```yaml
apiVersion: 1.0.0
kind: ServiceAccount
data:
  clientId: <CLIENT_ID>
  clientSecret: <CLIENT_SECRET>
  name: calm
  scopes:
    - cards:write
    - cards:read
```

> Output will be different depending on the template used to generate service account

> Please make sure always to store these credentials in a secure environment. They should never be exposed.

Generated credentials can be located on VGS Dashboard under the Organization Settings page:

Please note that `Write` organization access is required for credentials to work (set by default).

## How To Authenticate

VGS API authentication server is available at [https://auth.verygoodsecurity.com](https://auth.verygoodsecurity.com/).

The first thing you'd need to authenticate is API credentials from the previous step: `CLIENT_ID` and `CLIENT_SECRET`.

With these two pieces of information in hand, you’re ready to authenticate. Here is an example request for obtaining an access token and its response:

{% tabs %}
{% tab title="Request" %}

```bash
curl -X POST \
-d "client_id=<CLIENT_ID>" \
-d "client_secret=<CLIENT_SECRET>" \
-d "grant_type=client_credentials" \
"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token"
```

{% endtab %}

{% tab title="Response" %}

```json
{
 "access_token":"...",
 "expires_in":300,
 "refresh_expires_in":0,
 "token_type": "bearer",
 "not-before-policy": 1620379100,
 "scope": "cards:write user_id service-account",
}
```

{% endtab %}
{% endtabs %}

Now you're ready to call an API with the obtained `access_token`. Generated token can be used with VGS Account Updater API **only** within the specified vault with the **vgs.io/vault-id** annotation. Please note that `access_token` is valid only for 5 minutes. After that, you need to obtain a new access token using the same request. `refresh_token` should not be used.

The obtained `access_token` value should be passed in `Authorization: Bearer ${VGS_ACCESS_TOKEN}` header in each API call.

{% hint style="info" %}
For simple usage of cURL commands across our documentation, you can store the `access_token` in an environment variable (requires [jq](https://github.com/stedolan/jq)):

```bash
VGS_ACCESS_TOKEN=`curl -X POST \
-d 'client_id=<CLIENT_ID>' \
-d 'client_secret=<CLIENT_SECRET>' \
-d 'grant_type=client_credentials' \
'https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token' | jq -r .access_token`
```

{% endhint %}

## How To Revoke Credentials

In case you need to revoke access to payment optimization services for particular credentials, you can follow these steps:

{% stepper %}
{% step %}

### Using VGS CLI (preferred)

```bash
vgs delete service-account <CLIENT_ID> -O <ORGANIZATION_ID>
```

{% endstep %}

{% step %}

### Via VGS Dashboard

Remove the user named `<CLIENT_ID>@vgs.dev` from the VGS Dashboard under the Organization Settings page.
{% endstep %}
{% endstepper %}


# Enroll Card - V1

Below is a diagram detailing how card data will flow to and from a customer's servers.

### Request Body Fields

The table below contains more details on the request body fields, which are required and which are optional.

| Field               | Field Type                                                                                                                                                        | Description                                                                                                                                    |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| name                | Required                                                                                                                                                          | Name of the user on the card                                                                                                                   |
| number              | Required                                                                                                                                                          | VGS alias representing the PAN                                                                                                                 |
| exp\_month          | Required                                                                                                                                                          | Expiration month on the card                                                                                                                   |
| exp\_year           | Required                                                                                                                                                          | Expiration year on the card                                                                                                                    |
| billing\_address    | Optional                                                                                                                                                          | Billing address registered on the card                                                                                                         |
| company             | Optional                                                                                                                                                          | Company registered on the card                                                                                                                 |
| address1            | Optional                                                                                                                                                          | Address1 of the user registered on the card                                                                                                    |
| address2            | Optional                                                                                                                                                          | Address2 of the user registered on the card                                                                                                    |
| city                | Optional                                                                                                                                                          | City of the user registered on the card                                                                                                        |
| region              | Optional                                                                                                                                                          | Region of the user registered on the card                                                                                                      |
| country             | Optional                                                                                                                                                          | Country of the user registered on the card                                                                                                     |
| postal\_code        | Optional                                                                                                                                                          | Postal Code of the user registered on the card                                                                                                 |
| phone               | Optional                                                                                                                                                          | Phone Number of the user registered on the card                                                                                                |
| merchant            | Conditional Required (pass this value if you are submitting the card on behalf of a merchant or if you have multiple merchants registered for a single VGS vault) | "merchant" element in the request payload                                                                                                      |
| sub\_merchant\_name | Conditional Required (pass this value if you are submitting the card on behalf of a merchant)                                                                     | Merchant Name registered on the card                                                                                                           |
| vgs\_merchant\_id   | Conditional Required (required only if multiple merchants are registered per VGS vault for Account Updater)                                                       | VGS generated ID per merchant registered for VGS Vault. This ID is returned as a part of the merchant registration process for Account Updater |

The following cURL command will enroll your card in VGS Account Updater.

{% code title="Enroll Card (cURL)" %}

```bash
curl https://calm.<ENVIRONMENT>.verygoodsecurity.app/cards \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${VGS_ACCESS_TOKEN}" \
-d '{
      "name": "John Doe",
      "number": "5573495XTjZP21V7312",
      "exp_month": 7,
      "exp_year": 24
    }'
```

{% endcode %}

After submitting the enrollment request, an immediate synchronous response is generated confirming the successful initiation of the enrollment process for updates with the payment service provider. This response provides details about the request's status, along with the associated event type received on the card.

{% code title="Synchronous Response (example)" %}

```json
{
  "data": {
    "id": "CRDuVQCsenqj6dbHFQq9gen2E",
    "name": "John Doe",
    "number": "5573495XTjZP21V7312",
    "exp_month": 7,
    "exp_year": 24,
    "capabilities": [
      "ACCOUNT_UPDATER"
    ],
    "created_at": "2019-05-15T12:30:45Z",
    "updated_at": "2019-05-15T12:30:45Z",
    "state": "enrolled",
    "event": "au_card.updated"
  }
}
```

{% endcode %}

An asynchronous response is also sent via a webhook URL to you, if the enrollment does not complete immediately. The synchronous response will have the `state: ENROLLING` and not the final state of the request.

{% hint style="info" %}
No webhook event is sent if the enrollment returns `state: ENROLLED` in the response immediately.
{% endhint %}

### Response Body Fields

The table below provides detailed information about the fields in the synchronous response body for the Enroll Card request.

| Field            | Description                                                                                                                                                                       |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id               | Serves as a unique identifier for the card within VGS Account Updater Service                                                                                                     |
| name             | Name of the user on the card                                                                                                                                                      |
| number           | VGS alias representing the PAN                                                                                                                                                    |
| exp\_month       | Expiration month on the card                                                                                                                                                      |
| exp\_year        | Expiration year on the card                                                                                                                                                       |
| billing\_address | Billing address registered on the card                                                                                                                                            |
| name             | Name of the user on the card                                                                                                                                                      |
| company          | Company registered on the card                                                                                                                                                    |
| address1         | Address1 of the user registered on the card                                                                                                                                       |
| address2         | Address2 of the user registered on the card                                                                                                                                       |
| city             | City of the user registered on the card                                                                                                                                           |
| region           | Region of the user registered on the card                                                                                                                                         |
| country          | Country of the user registered on the card                                                                                                                                        |
| postal\_code     | Postal Code of the user registered on the card                                                                                                                                    |
| phone            | Phone Number of the user registered on the card                                                                                                                                   |
| capabilities     | Indicates that the card is enrolled in the VGS Account Updater Service                                                                                                            |
| created\_at      | Timestamp indicating when the card was enrolled with VGS Account Updater                                                                                                          |
| updated\_at      | Timestamp indicating when an update was received for the card from the network                                                                                                    |
| state            | Current state of the card in VGS                                                                                                                                                  |
| event            | Event or status update received from the network regarding the card. For more information on possible events, please refer to this [link](/cmp/developer-resources/notifications) |

#### VGS States and Network Events Reference

For details about VGS states corresponding to various event types received on a card from the network, please refer to the documentation [here](/cmp/developer-resources/notifications).

{% hint style="info" %}
Once a card update is received through the networks, the updated card information is generally considered usable. However, the timing and approach to updates can vary across issuers.

Issuer Practices:

* Some issuers send updates only after the cardholder activates the new physical card ("plastic").
* Others may allow the old and new card details to coexist temporarily, ensuring continuity in transactions during the transition.
* No Uniform Pattern: There is no single standardized pattern across all issuers. Each issuer follows its internal policies regarding when updates are shared and how it handles card transitions.

Merchants should consider these variations and ensure they accommodate both scenarios to minimize disruptions in recurring or tokenized transactions.
{% endhint %}

### Mock Responses and Test Cards

For test card numbers that you can use for testing in the Sandbox environment, see [Test Cards](/cmp/developer-resources/guides/testing).


# Get Card - V1

Get Card - Get information on registered cards

## Get information on a specific enrolled card

> Returns information of enrolled card with the most up-to-date card information available from issuing banks and all VGS Account Updater capabilities.

```json
{"openapi":"3.0.0","info":{"title":"VGS Account Updater and Network Tokens APIs","version":"1.0.0"},"tags":[{"name":"Account Updater","description":"Cards enrolled in VGS Account Updater."}],"servers":[{"url":"https://calm.sandbox.verygoodsecurity.app","description":"Sandbox"},{"url":"https://calm.live.verygoodsecurity.app","description":"Live"}],"security":[{"OAuth2":["cards:read"]}],"components":{"securitySchemes":{"OAuth2":{"type":"oauth2","flows":{"clientCredentials":{"tokenUrl":"https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token","scopes":{"cards:write":"Grants write access to cards","cards:read":"Grants read access to cards","network-tokens:write":"Grants access to perform operations with network tokens","network-tokens:read":"Grants read access to the network tokens","merchants:write":"Grants write access to Merchant API","merchants:read":"Grants read access to Merchant API","merchants:admin":"Grants admin access to Merchant API"}}}}},"parameters":{"card_id":{"name":"card_id","in":"path","description":"ID of the card to fetch","required":true,"schema":{"type":"string","pattern":"^CRD.*$"}}},"responses":{"CardFetchResponse":{"description":"Enroll card API response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollCardData"}}}}},"schemas":{"EnrollCardData":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/EnrolledCard"}}},"EnrolledCard":{"allOf":[{"$ref":"#/components/schemas/CheckedCard"},{"type":"object","description":"Payment card object with billing address.","properties":{"billing_address":{"$ref":"#/components/schemas/BillingAddress"},"capabilities":{"type":"array","items":{"$ref":"#/components/schemas/Capability"}}}},{"type":"object","required":["id","created_at","updated_at","state"],"properties":{"id":{"type":"string","description":"Unique reference identifier for this card"},"created_at":{"type":"string","format":"date-time","description":"Creation time, in UTC."},"updated_at":{"type":"string","format":"date-time","description":"Last time card was updated, in UTC."},"state":{"type":"string","description":"Current state of a card being processed:\n  * `enrolling` - card is in enrolling state and is not yet available for updates\n  * `enrolled` - card was successfully enrolled and is available for Push and Pull updates\n  * `failed` - card enrollment failed, see `failure_code` for details\n  * `closed` - card was closed, but can still be retrieved\n","enum":["enrolling","enrolled","failed","closed"]}}}]},"CheckedCard":{"allOf":[{"$ref":"#/components/schemas/Card"},{"type":"object","properties":{"failure_code":{"type":"string","enum":["account-updater-not-supported","merchant-not-found","invalid-exp-date","invalid-payload","invalid-param","internal-server-error"],"description":"Application-specific failure code which can only occur with failed state:\n  * `account-updater-not-supported` - Account Updater is not implemented for your card issuer\n  * `merchant-not-found` - No merchant was registered for organization\n"},"event":{"type":"string","description":"Current state of a card being processed:\n  * `au_card.valid` - Card is valid. Current Account and Expiration Date returned\n  * `au_card.updated` - Card was updated. New Account and Expiration Date returned\n  * `au_card.expired` - Card was expired. New Expiration Date returned\n  * `au_card.closed` - Card was closed.\n  * `au_card.non_participating` - BIN is not participating in AU\n  * `au_card.contact_cardholder_advice` - Cardholder has opted out and the merchant needs to contact cardholder for information\n  * `au_card.unknown` - BIN is participating in AU but there is no match yet\n  * `au_card.enrolled` - PAN and expiration date the merchant provided is up-to-date\n  * `au_card.opt_out` - Cardholder has opted out sharing credential information with the merchants\n","enum":["au_card.valid","au_card.updated","au_card.expired","au_card.closed","au_card.non_participating","au_card.contact_cardholder_advice","au_card.unknown","au_card.enrolled","au_card.opt_out"]}}}]},"Card":{"type":"object","description":"Payment card object.","required":["name","number","exp_month","exp_year"],"properties":{"name":{"maxLength":255,"description":"Card owner's full name.","type":"string"},"number":{"maxLength":19,"minLength":13,"pattern":"^(\\d{6}.{0,9}[a-zA-Z].{0,9}\\d{4}?)|((?:4[0-9]{12}(?:[0-9]{3})?)|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\\d{3})\\d{11})$","description":"Customer's card number.","type":"string"},"exp_month":{"description":"Card's expiration month.","type":"integer","minimum":1,"maximum":12},"exp_year":{"description":"Card's expiration year.","type":"integer","minimum":0,"maximum":99},"cvv":{"description":"Card's cvv","type":"string","pattern":"^\\d{3,4}$"},"merchant":{"description":"AU merchant details.","type":"object","properties":{"vgs_merchant_id":{"maxLength":255,"description":"VGS merchant id.","type":"string"},"sub_merchant_name":{"maxLength":255,"description":"Sub merchant name. Required if you are submitting the card on behalf of a merchant.","type":"string"},"sub_merchant_mid":{"maxLength":255,"description":"Sub merchant MID. In some cases required for PayFac customers","type":"string"}}}}},"BillingAddress":{"description":"Internal schema for customer's billing.","type":"object","properties":{"name":{"maxLength":255,"type":"string"},"company":{"maxLength":255,"type":"string"},"address1":{"maxLength":255,"type":"string"},"address2":{"maxLength":255,"type":"string"},"city":{"maxLength":50,"type":"string"},"region":{"maxLength":50,"type":"string","description":"Principal subdivision in ISO 3166-2\n"},"country":{"maxLength":50,"type":"string","description":"ISO 3166 alpha 2 country code\n"},"postal_code":{"maxLength":50,"type":"string"},"phone":{"maxLength":50,"type":"string","description":"Telephone number in E.164\n"}}},"Capability":{"description":"CALM capabilities to enable.","type":"string","enum":["ACCOUNT_UPDATER","NETWORK_TOKEN"]},"CardApiErrors":{"type":"object","required":["errors","trace_id"],"properties":{"errors":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/CardApiError"},{"$ref":"#/components/schemas/GeneralError"}],"description":"List of errors that occurred while processing the request.","minItems":1}},"trace_id":{"description":"A unique identifier of the failed request.","type":"string"}}},"CardApiError":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error_code":{"type":"string","enum":["card-brand-not-supported","account-updater-not-supported","card-not-found","merchant-not-found"],"description":"Application-specific error code:\n  * `card-brand-not-supported` - Specified card brand is not supported, only Mastercard cards are supported\n  * `account-updater-not-supported` - Account Updater is not implemented for your card issuer\n  * `card-not-found` - Card is not enrolled in CALM\n  * `merchant-not-found` - No merchant was registered for organization and provided capability\n"}}}]},"Error":{"type":"object","description":"An error object","properties":{"detail":{"description":"Explanation of what exactly went wrong.","type":"string"}}},"GeneralError":{"additionalProperties":false,"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error_code":{"type":"string","enum":["internal-server-error","invalid-payload","validation-failed","unsupported-media-type"],"description":"Application-specific error code:\n  * `internal-server-error` - Something went wrong\n  * `invalid-payload` - Invalid request payload\n  * `validation-failed` - Request validation failed\n  * `unsupported-media-type` - Request media type is not supported\n"}}}]}}},"paths":{"/cards/{card_id}":{"get":{"tags":["Account Updater"],"summary":"Get information on a specific enrolled card","description":"Returns information of enrolled card with the most up-to-date card information available from issuing banks and all VGS Account Updater capabilities.","operationId":"getCard","parameters":[{"$ref":"#/components/parameters/card_id"}],"responses":{"200":{"$ref":"#/components/responses/CardFetchResponse"},"404":{"description":"Not found. Possible error codes:\n  * `card-not-found`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardApiErrors"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralError"}}}},"default":{"$ref":"#/components/responses/CardFetchResponse"}}}}}}
```

The following cURL command will get your card information from the VGS Account Updater.

{% code title="cURL" %}

```bash
curl --request GET https://calm.<ENVIRONMENT>.verygoodsecurity.app/cards/CRDuVQCsenqj6dbHFQq9gen2E \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${VGS_ACCESS_TOKEN}"
```

{% endcode %}

VGS Account Updater returns a Card object in response to your API request.

{% code title="Response (application/json)" %}

```json
{
  "data": {
    "id": "CRDuVQCsenqj6dbHFQq9gen2E",
    "name": "John Doe",
    "number": "tok_svzgzzX8SDJMRjk93GVKG6b",
    "exp_month": 7,
    "exp_year": 24,
    "capabilities": [
      "ACCOUNT_UPDATER"
    ],
    "created_at": "2019-05-15T12:30:45Z",
    "updated_at": "2019-05-15T12:30:45Z",
    "state": "enrolled",
    "event": "au_card.enrolled"
  }
}
```

{% endcode %}


# Account Updater Notifications - V1

Stay informed about your VGS Account Updater-enrolled cards! Enable Push Updates to automatically receive account information without manual checks. Learn more about notifications in the [Notification Center](/cmp/developer-resources/notifications).

#### To receive updates:

{% stepper %}
{% step %}

### Create an endpoint

Create an endpoint in your application to receive HTTP requests about your cards. See the [events](/cmp/api-dev/account-updater-events) documentation.
{% endstep %}

{% step %}

### Configure VGS Account Updater Notifications

[Configure VGS Account Updater Notifications](/cmp/developer-resources/guides/testing/account-updater-webhooks) in your VGS Dashboard.
{% endstep %}

{% step %}

### Enable Card Updates

Enable Card Updates to send card updates to your new endpoint.
{% endstep %}
{% endstepper %}

## Configure VGS Account Updater Notifications

To set up the webhook endpoints, go to the **Organization Settings** > **Notifications** tab on your dashboard, click Add Notifications on the right and add your webhook where you will receive notifications.

After notifications are setup, you can configure cards events to send updates to your application endpoint. See the *Add Card Events* section below for more details on setting up these events.

## Add Card Events

To get card lifecycle notifications you need to add them to your webhook configuration.

After you added the event, please select a vault within which you want to receive it.

### Events

When you enroll cards using the VGS Account Updater API, you'll receive convenient notifications for lifecycle events. Each notification includes the card ID, allowing you to quickly fetch the latest card data using a simple GET request. Here's how it works:

{% stepper %}
{% step %}

### Enroll cards with the VGS Account Updater API

{% endstep %}

{% step %}

### Receive notifications for events like

* Card updates
* Expirations
* Account closures
* And others
  {% endstep %}

{% step %}

### Signature

Read more about [**webhook signature**](/cmp/developer-resources/guides/testing/account-updater-webhooks) to configure authentication properly.
{% endstep %}

{% step %}

### Extract the cardID from each notification

Each notification includes a details block containing card\_id.
{% endstep %}

{% step %}

### Use the cardID to fetch the updated card data

Get Card - Get information on registered cards:

{% code title="curl example" %}

```bash
curl --request GET https://calm.<ENVIRONMENT>.verygoodsecurity.app/cards/CRDuVQCsenqj6dbHFQq9gen2E \
-x https://<CREDENTIALS>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443 -k \
-H "Content-type: application/json" \
-H "Authorization: Bearer ${VGS_ACCESS_TOKEN}"
```

{% endcode %}
{% endstep %}
{% endstepper %}

VGS Account Updater returns a Card object immediately in response to your API request, providing a synchronous response. For details on request and response fields, please refer to [Enroll Card](/cmp/developer-resources/api/credential-management-v1-apis-calm/account-updater-v1/api-reference-v1/enroll-card-v1).

```json
{
    "data": {
      "id": "CRDuVQCsenqj6dbHFQq9gen2E",
      "name": "John Doe",
      "number": "5573495XTjZP21V7312",
      "exp_month": 7,
      "exp_year": 24,
      "capabilities": [
        "ACCOUNT_UPDATER"
      ],
      "created_at": "2019-05-15T12:30:45Z",
      "updated_at": "2019-05-15T12:30:45Z",
      "state": "enrolled",
      "event": "au_card.updated
    }
}
```

### au\_card.updated — Card Updated

Once your card account number or expiration date has been changed.

au\_card.updated Response

```json
{
  "description": "Card updated",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "new_account_number": "************5698",
    "new_expiration_date": "0227",
    "occurred_at": "2024-01-17T00:00Z",
    "old_account_number": "************7343",
    "old_expiration_date": "0424"
  },
  "event": "au_card.updated",
  "fingerprint": "0734f9289326955d9b323c26b281fd8112f78ef56acd09a3dc2b8c7a9a13c948",
  "grouping": "every_single",
  "id": "bba88542-cfb1-42f8-8f63-aba60d62917c",
  "integration_id": "IN6VgSvLVRV2j2iuxugi4mh7",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" has been updated within vault tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-18T23:49:31.809Z"
}
```

### au\_card.expired — Card Expired

Once your card has expired.

au\_card.expired Response

```json
{
  "description": "Card expired",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "new_account_number": "************7343",
    "new_expiration_date": "0427",
    "occurred_at": "2024-01-17T00:00Z",
    "old_account_number": "************7343",
    "old_expiration_date": "0224"
  },
  "event": "au_card.expired",
  "fingerprint": "a9f7f574f9df11acee08aecb9292b6aee2607ca6923893214450e2ddaf3e9fb2",
  "grouping": "every_single",
  "id": "72a57889-48e2-41a2-bad1-777dba7455b5",
  "integration_id": "IN6VgSvLVRV2j2iuxugi4mh7",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" has been expired within vault tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-19T00:04:39.891Z"
}
```

### au\_card.closed — Card Closed

Once your card account is closed.

au\_card.closed Response

```json
{
  "description": "Card closed",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z",
    "old_account_number": "************7343",
    "old_expiration_date": "0424"
  },
  "event": "au_card.closed",
  "fingerprint": "a786596550eb3a2ef0e33ae58c2b74253e9e7ce6661326bb00c643add7032ccd",
  "grouping": "every_single",
  "id": "6c8c259c-1e42-48a9-864c-80c61c6c2fba",
  "integration_id": "IN6VgSvLVRV2j2iuxugi4mh7",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" has been closed within vault tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-19T00:07:27.836Z"
}
```

### au\_card.contact\_cardholder\_advice — Card Contact Cardholder Advice

au\_card.contact\_cardholder\_advice Response

```json
{
  "description": "Card Contact Cardholder Advice",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z",
    "old_account_number": "************7343",
    "old_expiration_date": "0424"
  },
  "event": "au_card.contact_cardholder_advice",
  "fingerprint": "c3168b4820cfb68f7e5fb8e3744bfa8efb340021660ec0180471177f8db0ec1d",
  "grouping": "every_single",
  "id": "64cb7832-56e6-46c5-b3fe-611cfbd3d954",
  "integration_id": "INwhuRND8kbbUL6Yv9QudB9w",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" has opted out and the merchant needs to contact cardholder for tenant tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-24T17:51:37.473Z"
}
```

### au\_card.non\_participating — Card Non-Participating

au\_card.non\_participating Response

```json
{
  "description": "Card Non-Participating",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z"
  },
  "event": "au_card.non_participating",
  "fingerprint": "c16a070bc351c29bd0a74c504dc1c727a8ea641478000b5251bcedf931e4c0ee",
  "grouping": "every_single",
  "id": "bae8eb84-2197-4d78-9742-d9fc14992d12",
  "integration_id": "INwhuRND8kbbUL6Yv9QudB9w",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" is not participating for tenant tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-24T18:03:57.032Z"
}
```

### au\_card.unknown — Card Unknown

au\_card.unknown Response

```json
{
  "description": "Card Valid",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z"
  },
  "event": "au_card.unknown",
  "fingerprint": "369a1a951d2131450953b68c678bff7f052c519ac85946859275efb392fb2cce",
  "grouping": "every_single",
  "id": "41e13908-b5d1-4d71-96d7-13186e7f7e64",
  "integration_id": "INs4MeN1xjpQniQtZBR7VSg5",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" is valid for tenant tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-24T19:46:50.349Z"
}
```

### au\_card.enrolled — Card Enrolled

au\_card.enrolled Response

```json
{
  "description": "Card Enrolled",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z"
  },
  "event": "au_card.enrolled",
  "fingerprint": "46c9722d2f3ff2e130acf530ae43d8e277cb3586e5ced98ebccbf032d21c0741",
  "grouping": "every_single",
  "id": "cc42d364-e38f-4631-8363-a8782f7e463b",
  "integration_id": "INs4MeN1xjpQniQtZBR7VSg5",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" enrolled for tenant tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-24T19:45:06.768Z"
}
```

### au\_card.opt\_out — Card Opt-Out

au\_card.opt\_out Response

```json
{
  "description": "Card Opt Out",
  "details": {
    "card_id": "CRDecqZp3xRgXU3TFmtcDdzQs",
    "occurred_at": "2024-01-17T00:00Z"
  },
  "event": "au_card.opt_out",
  "fingerprint": "4f7451324fcb50779abd62fb2eda31f604b8b99d334f5c0de43e7f28571d1089",
  "grouping": "every_single",
  "id": "765719b8-8c9d-4456-89b7-9a98a51edca2",
  "integration_id": "INmPVDZzkSos7CnsjCBQCRgf",
  "occurrence": 1,
  "org_id": "AC21kskfJCLyrkVjmAT6gU9X",
  "producer": {
    "application_name": "calm-api",
    "application_protocol": "http"
  },
  "scope": "vault",
  "summary": "Card \"CRDecqZp3xRgXU3TFmtcDdzQs\" has opted out for tenant tntvlyn1nof",
  "tenant": "tntvlyn1nof",
  "timestamp": "2024-01-25T16:01:38.719Z"
}
```

## Notification Response Body Fields

The table below provides detailed information about the fields in the asynchronous notification response body for updates received on a card.

| Fields                | Data type                                               | Occurrence | Min length | Max length | Description                                                                                       | Purpose/Usage                                                                                                                                      |
| --------------------- | ------------------------------------------------------- | ---------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| description           | String                                                  | Optional   | 31         | 31         | Description of the event                                                                          | Provides details about the nature of the event                                                                                                     |
| details               | JSON String                                             | Optional   | 0          | INF        | Block containing card details. Includes: card\_id and occurred\_at                                | Encapsulates relevant details of the card associated with the event                                                                                |
| card\_id              | String - Custom identifier                              | Mandatory  | 25         | 25         | System-generated ID for the card in VGS                                                           | Serves as a unique identifier for the card within VGS Account Updater Service                                                                      |
| occurred\_at          | String - Date-Time - ISO 8601                           | Optional   | 24         | 26         | Timestamp of when the event was generated or occurred.                                            | Records the exact timestamp when the event was generated or occurred                                                                               |
| new\_account\_number  | Number - Masked                                         | Mandatory  | 16         | 16         | Masked new account number on the card                                                             | Indicates an account update on the card, allowing the use of the last 4 digits of the new number                                                   |
| new\_expiration\_date | Number                                                  | Mandatory  | 4          | 4          | New expiration date of the card                                                                   | Indicates an updated expiration date for the card, making the new date readily available                                                           |
| old\_account\_number  | Number - Masked                                         | Mandatory  | 16         | 16         | Masked old account number of the card                                                             | Records the exact timestamp when the event was generated or occurred                                                                               |
| old\_expiration\_date | Number                                                  | Mandatory  | 4          | 4          | Old expiration date of the card                                                                   | Reflects the previous expiration date before the update, indicating a change in the expiration date                                                |
| event                 | String                                                  | Mandatory  | 14         | 33         | Event or status update received from the network regarding the card                               | Reflects the actual state or event of the card as received from the network. For more information on possible events, please refer to this link    |
| exp\_month            | Number                                                  | Mandatory  | 1          | 2          | A two-digit value (from 01 to 12) indicating the month when the card's validity ends.             | Verifies the token's validity or match it with the expiration details on file during payment transactions.                                         |
| exp\_year             | Number                                                  | Mandatory  | 2          | 4          | A four-digit value indicating the year when the card expires                                      | Determines whether the tokenized card is still valid, ensuring that the payment process proceeds smoothly                                          |
| created\_at           | DateTime                                                | Mandatory  | 20         | 20         | Timestamp indicating when a specific account update (like a card update) was created or processed | Tracks the moment when the card record was created in VGS Vault                                                                                    |
| event                 | String                                                  | Mandatory  | 14         | 33         | Event or status update received from the network regarding the card                               | Reflects the actual state or event of the card as received from the network. For more information on possible events, please refer to this link    |
| fingerprint           | String - Custom identifier - Hexadecimal representation | Mandatory  | 64         | 64         | Hexadecimal SHA-256 hash of event+details+tenant                                                  | Enables grouping and throttling of similar messages based on the fingerprint, set by the producer as exp\_repeat instead of individual occurrences |
| grouping              | String                                                  | Mandatory  | 9          | 12         | Method for grouping similar events by fingerprint                                                 | Allows throttling of requests based on the same fingerprint, grouping as exp\_repeat, every\_single, or high\_rate                                 |
| id                    | String - UUID                                           | Mandatory  | 36         | 36         | Unique ID for the request                                                                         | Serves as a unique identifier for the request                                                                                                      |
| integration\_id       | String - Custom identifier - Base62-encoded             | Mandatory  | 24         | 24         | Unique integration ID for this webhook                                                            | Identifies the webhook integration associated with this notification                                                                               |
| occurrence            | int                                                     | Mandatory  | 1          | 1          | Grouping-related field; set to 1 if no grouping is applied                                        | Represents the occurrence count if events are grouped; defaults to 1 if no grouping                                                                |
| org\_id               | String - Custom identifier                              | Mandatory  | 24         | 24         | Organization ID                                                                                   | Indicates the organization ID linked to this event, which can be found on your VGS Dashboard.                                                      |
| producer              | -                                                       |            |            |            | Originator of the event                                                                           | Identifies the source system or entity generating the event                                                                                        |
| application\_name     | String                                                  | Optional   | 0          | INF        | Name of the producer application                                                                  | Provides the name of the application responsible for generating this event                                                                         |
| application\_protocol | String - Protocol Identifier                            | Optional   | 4          | 5          | Protocol used by the producer application                                                         | Specifies the protocol used by the application for this event                                                                                      |
| scope                 | String - Scope Identifier                               | Mandatory  | 5          | 5          | Scope of the event notification                                                                   | Used internally to populate additional fields based on the event scope                                                                             |
| summary               | String                                                  | Optional   | 0          | INF        | Summary of the notification                                                                       | Offers a concise overview of the notification                                                                                                      |
| tenant                | String - Custom identifier                              | Mandatory  | 11         | 11         | Vault ID                                                                                          | Indicates the vault linked to this event, which can be found on your VGS Dashboard.                                                                |
| timestamp             | String - Date-Time - ISO 8601                           | Mandatory  | 24         | 26         | Date and time when a specific update to a cardholder’s card information was updated by Networks   | Track the exact day and time when a card's details were updated, such as a new expiration date or card number.                                     |

## Testing

When testing using the VGS Account Updater sandbox, push notifications will be sent out immediately after enrolling a card. The exact notification type that gets sent out is determined based on the last digit in the card number. The map of which digits line up to which notification types is documented in the [VGS Account Updater API Reference](/cmp/developer-resources/api/account-updater).

## Reference

* [Getting started with Account Updater](/cmp/products-and-services/account-updater#product-overview)
* [VGS Account Updater API documentation](/cmp/api-dev/account-updater)


# Account Updater Scopes - V1

[OAuth 2.0 scopes](https://oauth.net/2/scope/) allow you to specify the level of API access required. Since API credentials are limited per vault, API scopes are limited only for that vault as well. Once an access token is granted via the [authentication flow](/cmp/platform/authentication), scopes can be located in the issued JWT.

[CALM API credentials](/cmp/developer-resources/api/credential-management-v1-apis-calm) can have the following scopes:

| Scope                  | Permission                                     |
| ---------------------- | ---------------------------------------------- |
| `cards:write`          | Enroll and manage a card in CALM               |
| `cards:read`           | Read details about the enrolled card           |
| `network-tokens:write` | Enroll and manage a network tokens in CALM     |
| `network-tokens:read`  | Read details about the enrolled network tokens |


# Card Attributes - V1

{% hint style="warning" %}
**Important Notice:** Clients who are signed up to the Card Management Platform (CMP) should navigate to this [page](https://docs.verygoodsecurity.com/card-management).
{% endhint %}

## Card Attributes Overview - V1 (Legacy)

The VGS Card Attributes Service delivers powerful insights about any card. This service facilitates well-informed, automated decisions in your payment flows using payment credentials. It delivers a comprehensive set of attributes, including card brand, issuer, country, and more. With the data this service delivers, you can make more informed risk decisions, support loyalty programs, and enhance your customers' experience.

The service can deliver attributes from a full PAN, a six-digit IIN, or a card PAN's token/alias from your VGS Vault.

### The anatomy of a card's PAN

There is a lot one can get just from a credit card number. The VGS Card Attributes Service enhances this data with other attributes only available through the use of the Card Attributes Service.

* Major Industry Identifier (MII) (First Digit): This number reveals the card's network and issuing industry. For instance, a "4" indicates Visa, "5" indicates Mastercard, and "6" indicates Discover. The number "3" is usually American Express.
* Issuer Identification Number (IIN) (Digits 1-6): The first digit (MII) is combined with the next five digits from the IIN (also sometimes called BIN). This number is unique to the financial institution, usually a bank or credit union, that issued the card.
* Individual Account Number (Digits 7-15/14): These digits exclusively identify the cardholder account with the card issuer.
* Check Digit (Last Digit): This final number is a security measure. It's calculated using the Luhn algorithm based on the preceding digits. If someone tries to use a fake card number, there's a high chance the check digit won't validate using the Luhn algorithm, alerting the processor of potential fraud.

### Extra attributes available through the Card Attributes Service

The following attributes are available through this service

| Attribute              | Definition                                                                      | Access Level Required |
| ---------------------- | ------------------------------------------------------------------------------- | --------------------- |
| bin                    | bin number                                                                      | Basic                 |
| brand                  | The card brand facilitates payment transactions. Eg: Visa, Mastercard, Discover | Basic                 |
| issuing\_organization  | The bank that issued the card to the customer. Eg: Chase, Bofa, USBank          | Basic                 |
| card\_type             | The type of card that is issued by the issuing bank. Eg: Credit , Debit         | Basic                 |
| card\_category         | Category of Card. Eg: BUSINESS , PREPAID                                        | Basic                 |
| issuing\_country\_name | ISO country name that is associated with an ISO code. Eg: USA, United Kingdom   | Basic                 |
| issuing\_country\_code | Issuing country ISO number: Eg 840 for USA                                      | Basic                 |
| maximum\_pan\_length   | maximum PAN length                                                              | Basic                 |
| card\_commercial\_type | Defines if the BIN is PERSONAL or COMMERCIAL                                    | Basic                 |
| regulation\_status     | Defines if the BIN is regulated or non-regulated                                | Basic                 |
| version                | Date at which the returned data was last updated                                | Basic                 |
| prepaid\_type          | Indicates if the card is a prepaid debit card                                   | Advanced              |
| cobadged\_brands       | Lists the network co-badges of the card, if applicable                          | Advanced              |

### Benefits of using the Card Attributes API in your payments applications

* Enhanced Checkout experience: Retrieve real-time card attributes for pre-filling and enhancing checkout forms.
* Intelligent Payment Orchestration: Intelligent payment routing for faster authorization and lower costs using card-specific data.
* Subscription Payment Management: Identify non-reloadable prepaid cards to optimize subscription payment flows and minimize failed retries.
* Advanced Fraud Detection: Advanced fraud detection using BIN data and other risk factors.
* Streamlined Transaction Troubleshooting: transaction troubleshooting using detailed BIN data and card attributes.


# Quickstart - V1

This guide describes how to get started with the Card Attributes Service API. It is designed for an integration developer as the first step in learning how to integrate with the API, but should be simple enough for anyone to follow.

## Using the API

For this quickstart you will need the following.

* Admin access to the VGS Dashboard and a VGS sandbox or live vault.
* Access to a terminal command line.

Once you are ready for full integration, the full Open API specification for this API is located [here](/cmp/developer-resources/api/credential-management-v1-apis-calm/card-attributes-v1) in our API Reference store.

## Create and store your API credentials

This API authenticates using the OAuth2.0 client credentials flow, which requires a client id and secret to obtain an access token. You can create credentials in your VGS dashboard or via the VGS CLI, following these instructions.

{% stepper %}
{% step %}

### Create a service account

To create a service account for your organization, go to the Service Accounts section of the *VGS Dashboard > Organization settings* page and click the "Create New" button. Assign a name for this credential and select scopes.

Scopes indicate the services you wish to be accessed by these credentials. If they are available, assign one of the two following scopes: `card-attributes:basic` for basic level access to the attributes or `card-attributes:advanced` for advanced access. Advanced has more capabilities than basic; the differences are outlined below.

If you do not have access to these scopes, you can create a service account without adding these scopes; you will still have access to the basic version of the API, but will be limited to 15 times a day.
{% endstep %}

{% step %}

### Save your Client ID and Secret

Important! Be sure to save your Client ID and Secret!! You will not see the client secret again after it is presented to you on the screen.
{% endstep %}

{% step %}

### Store credentials as environment variables

Store your credentials in environment variables on your device by going into a terminal and entering these commands. Replace `<client id>` and `<secret>` with your actual Client Id and Secret.

{% code title="Set VGS credentials (bash)" %}

```bash
export VGS_CLIENT_ID=<client id>
export VGS_CLIENT_SECRET=<secret>
```

{% endcode %}
{% endstep %}
{% endstepper %}

## Try out the API

Now that you have stored the environment variables on your device, the following cURL command will retrieve an access token and use that token to call the VGS Card Attributes API.

{% stepper %}
{% step %}

### Retrieve an access token and call the Attributes endpoint

{% code title="cURL example" %}

```bash
curl https://card-enrichment-api.live.verygoodvault.com/attributes -H "Authorization: Bearer $( curl --request POST \
  --url 'https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=${VGS_CLIENT_ID}  \
  --data client_secret=${VGS_CLIENT_SECRET} | jq -r .access_token)" \
  -H 'Content-Type: application/json' \
  -d '{
  "number": "411111"
}' -v
```

{% endcode %}
{% endstep %}
{% endstepper %}

## Response Body

The command will return a JSON object similar to the one below.

{% code title="Sample response" %}

```javascript
{
  "bin": "411111",
  "brand": "VISA",
  "issuing_organization": "CONOTOXIA SP. Z O.O",
  "card_type": "DEBIT",
  "card_category": "CLASSIC",
  "issuing_country_name": "POLAND",
  "issuing_country_code": "616",
  "maximum_pan_length": 16,
  "card_commercial_type": "PERSONAL",
  "regulation_status": "UNREGULATED",
  "version": "v20241206",
  "prepaid_type": "NONRELOADABLE"
}
```

{% endcode %}

## Additional Test data

Replace the `411111` in the above REST API with the samples below.

* 223009 : Mastercard
* 340002 : American Express

## Attribute Summary

| Attribute              | Definition                                                                      | Access Level Required |
| ---------------------- | ------------------------------------------------------------------------------- | --------------------- |
| bin                    | bin number                                                                      | Basic                 |
| brand                  | The card brand facilitates payment transactions. Eg: Visa, Mastercard, Discover | Basic                 |
| issuing\_organization  | The bank that issued the card to the customer. Eg: Chase, Bofa, USBank          | Basic                 |
| card\_type             | The type of card that is issued by the issuing bank. Eg: Credit , Debit         | Basic                 |
| card\_category         | Category of Card. Eg: BUSINESS , PREPAID                                        | Basic                 |
| issuing\_country\_name | ISO country name that is associated with an ISO code. Eg: USA, United Kingdom   | Basic                 |
| issuing\_country\_code | Issuing country ISO number: Eg 840 for USA                                      | Basic                 |
| maximum\_pan\_length   | maximum PAN length                                                              | Basic                 |
| card\_commercial\_type | Defines if the BIN is PERSONAL or COMMERCIAL                                    | Basic                 |
| regulation\_status     | Defines if the BIN is regulated or non-regulated                                | Basic                 |
| version                | Date at which the returned data was last updated                                | Basic                 |
| prepaid\_type          | Indicates if the card is a prepaid debit card                                   | Advanced              |
| cobadged\_brands       | Lists the network co-badges of the card, if applicable                          | Advanced              |

With the Advanced scope assigned, all basic attributes are returned as well as advanced attributes.


# API Reference (Static)

> **POST /cards**

<details>

<summary>Create a card (complete)</summary>

```
POST /cards HTTP/1.1
Host: sandbox.vgsapi.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/vnd.api+json
Accept: */*
Content-Length: 440

{
  "data": {
    "attributes": {
      "pan": "4111111111111111",
      "pan_alias": "tok_sandbox_hhyPgvvdFfFGBnyi73TfFu",
      "cvc": "123",
      "cvc_status": "active",
      "cvc_alias": "tok_sandbox_5XK62B8G2i1mTwoGR5o4tL",
      "exp_month": 4,
      "exp_year": 28,
      "cardholder": {
        "name": "<NAME>",
        "company": "A Corp, LLC",
        "address": {
          "address1": "123 Main St",
          "address2": "Suite 456",
          "address3": "Line 3",
          "address4": "Line 4",
          "city": "San Francisco",
```

</details>

<details>

<summary>Sending DPAN token and apple pay wallet</summary>

```
POST /cards HTTP/1.1
Host: sandbox.vgsapi.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/vnd.api+json
Accept: */*
Content-Length: 124

{
  "data": {
    "attributes": {
      "pan": "4111111111111111",
      "exp_month": 4,
      "exp_year": 28,
      "token_type": "dpan",
      "wallet_type": "apple_pay"
    }
  }
}
```

</details>

<details>

<summary>Sending MPAN token and apple pay wallet</summary>

```
POST /cards HTTP/1.1
Host: sandbox.vgsapi.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/vnd.api+json
Accept: */*
Content-Length: 124

{
  "data": {
    "attributes": {
      "pan": "4111111111111111",
      "exp_month": 4,
      "exp_year": 28,
      "token_type": "mpan",
      "wallet_type": "apple_pay"
    }
  }
}
```

</details>

<details>

<summary>Sending PAN token and apple pay wallet</summary>

```
POST /cards HTTP/1.1
Host: sandbox.vgsapi.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/vnd.api+json
Accept: */*
Content-Length: 124

{
  "data": {
    "attributes": {
      "pan": "4111111111111111",
      "exp_month": 4,
      "exp_year": 28,
      "token_type": "pan",
      "wallet_type": "google_pay"
    }
  }
}
```

</details>

<details>

<summary>Sending user-defined metadata</summary>

```
POST /cards HTTP/1.1
Host: sandbox.vgsapi.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/vnd.api+json
Accept: */*
Content-Length: 105

{
  "data": {
    "attributes": {
      "pan": "4111111111111111",
      "exp_month": 4,
      "exp_year": 28
    },
    "meta": {
      "customerID": 1234
    }
  }
}
```

</details>


# Notifications

## Notifications <a href="#notifications" id="notifications"></a>

Enable Push Updates to automatically receive information about the CMP services without manual checks. Learn more about notifications in the [Notification Center](/enterprise-platform/developer-resources/webhook-notifications).

You can set up a webhook to receive Network Token and Account Updater updates by following the below steps:

* Navigate to your Dashboard, and in the left-hand menu under `Administration` select `Organization`
* On the `Organization` page, select the `Notifications` tab
* Select `Add a Notification`, and enter the details for your Webhook as desired
* After creation, search and add the desired events from the events list

#### Card Management Platform - Account Updater events <a href="#cmp-account-updater-events" id="cmp-account-updater-events"></a>

* cmp\_au\_card.updated
* cmp\_au\_card.expired
* cmp\_au\_card.closed
* cmp\_au\_card.non\_participating
* cmp\_au\_card.contact\_cardholder\_advice
* cmp\_au\_card.unknown
* cmp\_au\_card.enrolled
* cmp\_au\_card.opt\_out
* cmp\_au\_card.enrollment\_failed

For more information on CMP Account Updater Events, refer to the [Account Updater Events](/cmp/developer-resources/api/account-updater-events) section.

#### Card Management Platform - Network Tokens events <a href="#cmp-network-tokens-events" id="cmp-network-tokens-events"></a>

* cmp\_network\_token.updated

For more details on CMP Network Tokens Events, refer to the [Network Tokens Events](/cmp/api-dev/network-token-events) section.

* Configure the Vaults for which you want to subscribe to these notifications in the modal that appears
* Press the Save button in the bottom right corner of the page

You should now start receiving updates for the Network Token and/or Account Updater Vaults for which you have subscribed.

#### Card Management Platform - 3DS events <a href="#cmp-3ds-events" id="cmp-3ds-events"></a>

* **cmp\_threeds.device\_fingerprint**
  * Configure this event in your notifications on the VGS Dashboard to receive the result of the device fingerprinting step.&#x20;
  * This notification indicates whether device fingerprinting was successfully completed (`success = true` or `false`) via the Initialize Callback/Notification.
* **cmp\_threeds.challenge\_result**
  * Configure this event in your notifications on the VGS Dashboard to receive the final authentication result for the challenge flow.
  * This notification indicates whether the user successfully completed the challenge or if it was aborted or timed out.
* Click [here](https://docs.verygoodsecurity.com/enterprise-platform/developer-resources/webhook-notifications) to learn how to set up your notifications.

### Webhook Notifications - Signature Validation <a href="#webhook-notifications---signature-validation" id="webhook-notifications---signature-validation"></a>

Each webhook request contains a unique signature within HTTP header “vgs-signature” to verify the request’s VGS origin. More details can be found [here](/enterprise-platform/developer-resources/webhook-notifications#webhooks-signature).

<br>


# Guides


# Create a Card using VGS Collect

To create a Card object in the Card Management Platform (CMP), you can use [VGS Collect](/vault/developer-tools/vgs-collect), a PCI-compliant form with hosted fields that securely captures card details in your web or mobile UI. Sensitive payment info such as PAN and CVC never touches your systems. Instead, VGS Collect sends the data directly to VGS, and CMP creates the card and returns a Card Object with both basic identifiers (aliases, expiration, last4) and optional enriched attributes (issuer details, card type, regulatory status).

This method:

* Uses customizable PCI-compliant hosted fields (web, iOS, Android) to securely collect card details from the end user
* Passes them through VGS Collect to create a Card Object in CMP and return PAN/CVC aliases
* Can return [enriched card attributes](/cmp/products-and-services/card-attributes) in the same response if enabled in your account

### Step 1: Create a Client-Side Service Account <a href="#step-1-create-a-client-side-service-account" id="step-1-create-a-client-side-service-account"></a>

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`\
   ![](/files/FKRQSgddvEyf4KecD5xV)

#### Reference Documentation

&#x20;[Full Service Account Setup Guide](/vault/developer-tools/vgs-cli/service-account#using-service-accounts-via-dashboard)

### 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.

{% tabs %}
{% tab title="server.js" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>// sample-agentic-app
</strong><strong>// `npm start` to run
</strong><strong>
</strong><strong>const express = require('express');
</strong><strong>const axios = require('axios');
</strong>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}`);
});
</code></pre>

{% endtab %}

{% tab title=".env" %}

```bash
VGS_CLIENT_ID=example-client-id
VGS_CLIENT_SECRET=example-client-secret
```

{% endtab %}

{% tab title="package.json" %}

```json
{
  "name": "sample-agentic-app",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "axios": "^1.6.7",
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.18.2"
  }
}

```

{% endtab %}
{% endtabs %}

### Step 3: Frontend – Instantiate the Form

Load the VGS Collect library and instantiate the form:

```javascript
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

* [VGS Collect Overview](/vault/developer-tools/vgs-collect)
* [VGS Collect Create Form](/vault/developer-tools/vgs-collect/js/reference-documentation#api-vgscollectcreate)

### Step 4: Create Form Fields

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

{% tabs %}
{% tab title="Front-end JS" %}

```javascript
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 });
```

{% endtab %}

{% tab title="HTML" %}

```html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css"
    integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" href="./styles.css">
  <title>VGS Agentic Card Form</title>
</head>

<body>
  <div class="container pt-4">
    <div class="row">
      <div class="col-md">
        <div>
          <div id="cardholder-name" class="field-wrapper"></div>
        </div>
        <div>
          <div id="card-number" class="field-wrapper"></div>
        </div>
        <div>
          <div id="card-expiration" class="field-wrapper"></div>
        </div>
        <div>
          <div id="card-cvc" class="field-wrapper"></div>
        </div>

        <button id="submit-btn" class="submit-btn">Collect Card</button>

      </div>
    </div>
  </div>

  <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js"></script>
  <script src="script.js"></script>
</body>

</html>
```

{% endtab %}
{% endtabs %}

#### Reference Documentation

* [Cardholder Name Field](/vault/developer-tools/vgs-collect/js/reference-documentation#api-formfield)
* [Card Number Field](/vault/developer-tools/vgs-collect/js/reference-documentation#api-formfield)
* [Card Expiration Field](/vault/developer-tools/vgs-collect/js/reference-documentation#api-formfield)
* [CVC Field](/vault/developer-tools/vgs-collect/js/reference-documentation#api-formfield)

### 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.

```javascript
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.');
  }
}); 
```

### Card Object JSON Example&#x20;

```json
{
  "data": {
    "id": "CRDvM4kR5YUo3Zn8c1ZyY2vZ9",
    "type": "cards",
    "attributes": {
      "pan_alias": "tok_sandbox_918ZFABetAL717AUBzhMSx",
      "cvc_alias": "tok_sandbox_hURL8gt26jAgZhzPNgWCQi",
      "exp_month": 8,
      "exp_year": 30,
      "cardholder": {
        "name": "John Wick"
      },
      "token_type": "pan",
      "bin": "411111",
      "first8": "41111111",
      "last4": "1111",
      "card_fingerprint": "dZ9bao6fa6YWWHZSYXY7kU7UGFstmQke6hgWgCL7s6Vz",
      "capabilities": [
        "network-tokens",
        "card-updates"
      ],
      "created_at": "2025-08-27T20:09:05.456411",
      "updated_at": "2025-08-27T20:09:05.456417",
      "enriched_attributes": {
        "card_properties": {
          "card_number_length": 16,
          "card_brand": "VISA",
          "card_type": "DEBIT",
          "card_segment_type": "PERSONAL",
          "virtual_card": false,
          "prepaid_card": false,
          "product_name": "CLASSIC",
          "issuer_bin": "411111",
          "country_name": "POLAND",
          "country_numeric": 616
        },
        "card_capabilities": {
          "reloadable": false,
          "hsa": false,
          "fsa": false,
          "ebt": false
        },
        "bank": {
          "issuer_name": "CONOTOXIA SP. Z O.O"
        },
        "interchange": {
          "regulated": "N"
        }
      }
    }
  }
}
```

### 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.

<table data-full-width="true"><thead><tr><th width="111.39068603515625">Name</th><th width="258.729248046875"></th><th>JSON Path</th></tr></thead><tbody><tr><td>Card ID</td><td><p>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.</p><p></p><p>This value will remain constant even if the underlying card details change using card services.</p></td><td><code>card_object.data.id</code></td></tr><tr><td>PAN Alias</td><td><p>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.</p><p></p><p>This value can be used with the VGS Outbound Proxy when you wish to share the original PAN with a third-party.</p></td><td>`<code>card_object.data.attributes.pan_alias</code></td></tr><tr><td>CVC Alias</td><td>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.<br><br>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.</td><td>`<code>card_object.data.attributes.cvc_alias</code></td></tr><tr><td>Expiration Date</td><td>The expiration date of the card. This value will be required for issuing PSP tokens and performing payments.</td><td><code>card_object.data.attributes.exp_month</code><br><code>card_object.data.attributes.exp_year</code></td></tr></tbody></table>

### Read More

* [How to sign up on VGS to get comprehensive card attributes](/cmp/products-and-services/card-attributes)
* [Account Management on the Card Management Platform](/cmp/platform/cmp-account)


# Testing Guide


# Overview

This document provides instructions for testing the mock implementations of the Create Card API and Get Card API. The testing process allows you to simulate various responses based on specific card numbers and request configurations. This is essential for ensuring the robustness and reliability of the card management system before using it in a sandbox/live environment.


# Prerequisite

Generate an access token using the service account. You can create a service account through the dashboard or using the VGS Command Line Interface (CLI). For more details on generating an Access Token, click [here](/cmp/platform/authentication#id-2-generate-access-token).


# Create Card

## Create Card API - Mock Testing

You can test the Create Card API using mocks and the following methods:

### Method 1: Fixed Card Numbers for Specific Responses <a href="#method-1-fixed-card-numbers-for-specific-responses" id="method-1-fixed-card-numbers-for-specific-responses"></a>

Using specific card numbers, you can simulate fixed responses for the Create Card API. The following table lists card numbers and the corresponding responses you will receive upon making API requests.

With this set of Fixed Cards, you’ll always receive the same card ID, regardless of whether Duplicate Card Check is enabled or disabled. While the card ID remains constant, the user metadata will reflect the values you send. Please note, however, that in both sandbox and production, user metadata cannot be updated or deleted.

Additionally, the card IDs generated for these fixed cards are typically longer (52 chars) than the standard card ID format (24 chars) returned for real cards.

**Note:** The test cards in this method only work for accounts set up with the **on-create** enrollment type. Do **not** use the `cardID`s from these mock cards to enroll into AU or provision NT via independent endpoints if your account is configured for **manual** enrollment.

| Test Card Number                                | Test CardIDs                                         | Expiration Date | Expected Responses                                                                                                                                                                                                                             | HTTP Status Code |
| ----------------------------------------------- | ---------------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| 5100260000019206                                | CRDKfukrUmMsUdotydKS4euZ1v2exoN617mWi7avaehqkYh2J5JP | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Successful Notification<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (active status) objects are available</p> | 201              |
| 5100260000009207                                | CRDqL55P51GVUMbZMDgYakHQTJSoFP2e8NoMXzhQpVPgLh91ZEQo | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Failed Notification<br>3. GET response: Card, Account Updater (failed status) and Network Token (failed status) objects are available</p>       | 201              |
| 5100260000059210                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                            | 401              |
| 5100260000049211                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Forbidden)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                               | 403              |
| 5100260000019214                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Internal Server)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 500              |
| 5100260000009215                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Bad Gateway)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                             | 502              |
| 5100260000099216                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Service Unavailable)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                     | 503              |
| 5100260000089217                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Gateway Timeout)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 504              |
| 4000210000089208                                | CRDrc6FX3HbucdEvQCHha7Tkqa2TMT66xV9QDrNzh72NB5mw2R7u | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Successful Notification<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (active status) objects are available</p> | 201              |
| 4000210000079209                                | CRDoy9WqbTDwadttfKbWSTcbSnYddb8i5naGmDprK4BLBzbCawHg | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Failed Notification<br>3. GET response: Card, Account Updater (failed status) and Network Token (failed status) objects are available</p>       | 201              |
| 4000210000029212                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                            | 401              |
| 4000210000019213                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Forbidden)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                               | 403              |
| 4000210000089216                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Internal Server)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 500              |
| 4000210000079217                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Bad Gateway)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                             | 502              |
| 4000210000069218                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Service Unavailable)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                     | 503              |
| 4000210000059219                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Gateway Timeout)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 504              |
| <p>3400000000099200<br><br><br></p>             | CRDKfukrUmMsUdotydKS4euZ1v2exoN617mWi7avaehqkYh2J5J0 | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status) objects are available</p>                                     | 201              |
| 3400000000179200                                | CRDqL55P51GVUMbZMDgYakHQTJSoFP2e8NoMXzhQpVPgLh91ZEQ1 | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status) objects are available</p>                                           | 201              |
| 3400000000259200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                            | 401              |
| 3400000000339200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Forbidden)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                               | 403              |
| 3400000000419200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Internal Server)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 500              |
| 3400000000589200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Bad Gateway)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                             | 502              |
| 3400000000669200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Service Unavailable)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                     | 503              |
| 3400000000749200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Gateway Timeout)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 504              |
| <p>6599990001539200<br><br><br><br><br><br></p> | CRDKfukrUmMsUdotydKS4euZ1v2exoN617mWi7avaehqkYh2J5J2 | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status) objects are available</p>                                | 201              |
| 6599990001619200                                | CRDqL55P51GVUMbZMDgYakHQTJSoFP2e8NoMXzhQpVPgLh91ZEQ3 | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status) objects are available</p>                                      | 201              |
| 6599990001799200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                            | 401              |
| 6599990001879200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Forbidden)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                               | 403              |
| 6599990001959200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Internal Server)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 500              |
| 6599990002039200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Bad Gateway)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                             | 502              |
| 6599990002119200                                |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Service Unavailable)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                     | 503              |
| <p>6599990002299200<br></p>                     |                                                      | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Gateway Timeout)<br>2. Async notification: No<br>3. GET response: Not applicable</p>                                                                                                         | 504              |

### Method 2: Any PAN with Specific Mastercard or Visa Bins <a href="#method-2-any-pan-with-specific-mastercard-or-visa-bins" id="method-2-any-pan-with-specific-mastercard-or-visa-bins"></a>

Alternatively, you can use any PAN (Primary Account Number) that starts with the Mastercard bin (510026), Visa bin (400021), Amex bin (340000) and Discover bin (659999) to test the Create Card API. The response will depend on the validity of the request payload and the credentials used:

* **Successful Requests:** Appropriate success responses (e.g., 201 - Created) will be returned.
* **Error Responses:** Depending on the request payload and credentials, various error messages (e.g., 4XX errors) will be returned.
  * Testing tips:
    * For 422 - remove a required field or provide an invalid value such has 13 as the month in the request.
    * For 400 - malform the json such as removing a comma.

**Notes:**

* 5XX errors cannot be triggered using this method. Please use the fixed card numbers from Method 1 to trigger 5XX errors.
* Static test cards will return static cardholder information.
* To receive the provided cardholder information in the mock success response, use the static bin method.
* In this method, both Duplicate Card Check and fingerprinting are enforced.
* **For** **accounts set up with the manual enrollment-type,** you can create cards with this method, but must trigger AU updates or provision NT separately using the card’s `cardID` generated by this method.

| Card Number                                                                                                                                   | Expiration Date | Expected Responses                                                                                                                               | HTTP Status Code |
| --------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
| <p>510026\*\*\*\*\*\*\*\*\*\*<br>Well formed request payload is sent with no validation errors</p>                                            | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: No<br>3. GET response: Only card object are available</p>         | 201              |
| <p>510026\*\*\*\*\*\*\*\*\*\*<br>Request payload is sent with incorrect auth token (token has incorrect creds)</p>                            | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>              | 401              |
| <p>510026\*\*\*\*\*\*\*\*\*\*<br>Request payload sent without a required field or an invalid value such as 13 as the month in the request</p> | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 422 Unprocessable Entity)<br>2. Async notification: No<br>3. GET response: Not Applicable</p> | 422              |
| <p>510026\*\*\*\*\*\*\*\*\*\*<br>Request payload sent with malformed json such as without a comma</p>                                         | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 400 Bad Request)<br>2. Async notification: No<br>3. GET response: Not Applicable</p>          | 400              |
| <p>400021\*\*\*\*\*\*\*\*\*\*<br>Well formed request payload is sent with no validation errors</p>                                            | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: No<br>3. GET response: Only card object are available</p>         | 201              |
| <p>400021\*\*\*\*\*\*\*\*\*\*<br>Request payload is sent with incorrect auth token (token has incorrect creds)</p>                            | Any Future Date | <p>1. Sync response: Card Object Creation Failed (Unauthorized)<br>2. Async notification: No<br>3. GET response: Not applicable</p>              | 401              |
| <p>400021\*\*\*\*\*\*\*\*\*\*<br>Request payload sent without a required field or an invalid value such as 13 as the month in the request</p> | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 422 Unprocessable Entity)<br>2. Async notification: No<br>3. GET response: Not Applicable</p> | 422              |
| <p>400021\*\*\*\*\*\*\*\*\*\*<br>Request payload sent with malformed json such as without a comma</p>                                         | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 400 Bad Request)<br>2. Async notification: No<br>3. GET response: Not Applicable</p>          | 400              |
| <p>340000\*\*\*\*\*\*\*\*\*\*<br>Well formed request payload is sent with no validation errors<br><br><br><br></p>                            | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: No<br>3. GET response: Only card object are available</p>         | 201              |
| <p>340000\*\*\*\*\*\*\*\*\*\*<br>Request payload sent without a required field or an invalid value such as 13 as the month in the request</p> | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 422 Unprocessable Entity)<br>2. Async notification: No<br>3. GET response: Not Applicable</p> | 422              |
| <p>340000\*\*\*\*\*\*\*\*\*\*<br>Request payload sent with malformed json such as without a comma</p>                                         | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 400 Bad Request)<br>2. Async notification: No<br>3. GET response: Not Applicable</p>          | 400              |
| <p>659999\*\*\*\*\*\*\*\*\*\*<br>Well formed request payload is sent with no validation errors<br><br><br><br></p>                            | Any Future Date | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: No<br>3. GET response: Only card object are available</p>         | 201              |
| <p>659999\*\*\*\*\*\*\*\*\*\*<br>Request payload sent without a required field or an invalid value such as 13 as the month in the request</p> | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 422 Unprocessable Entity)<br>2. Async notification: No<br>3. GET response: Not Applicable</p> | 422              |
| <p>659999\*\*\*\*\*\*\*\*\*\*<br>Request payload sent with malformed json such as without a comma</p>                                         | Any Future Date | <p>1. Sync response: Card Object Creation Failed - 400 Bad Request)<br>2. Async notification: No<br>3. GET response: Not Applicable</p>          | 400              |

### Method 3: Account Updater Enrollment for Visa/Mastercard Cards with Networks <a href="#method-3-account-updater-enrollment-for-visamastercard-cards-with-networks" id="method-3-account-updater-enrollment-for-visamastercard-cards-with-networks"></a>

Webhook notifications for the listed events will not be triggered. However:

* **For** **accounts set up with the manual enrollment-type,** you can create cards with this method, but must trigger AU updates or provision NT separately using the card’s `cardID` generated by this method.&#x20;
* **For** **accounts set up with the on-create enrollment-type,** Account Updater enrollment will generate a success notification, and Network Token provisioning will generate success or failure notifications (note that provisioning usually fails for these cards). The “Expected Response” in the table below applies when these cards are used with accounts configured in on-create mode.

Amex and Discover do not offer sandbox test cards for network testing in sandbox environments.

| Test Cards       | Expiry Date | Network Event             | Expected Response                                                                                                                                                                                                                                                                                                      |
| ---------------- | ----------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 4680056031099387 | 8/26        | Expired                   | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>New Expiration Date</p>                     |
| 4403933787254356 | 9/26        | Closed                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Same Card Data</p>                          |
| 4000220720915104 | 1/25        | Contact cardholder advice | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Same Card Data</p>                          |
| 4207670264522669 | 10/26       | Valid                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Same Card Data</p>                          |
| 4327390068355738 | 12/23       | Updated                   | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Updated Card Number and Expiration Date</p> |
| 4549612182636736 | 3/23        | Account non-participating | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Same Card Data</p>                          |
| 5122350100384503 | 5/25        | Updated                   | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Updated Card Number and Expiration Date</p> |
| 5122351100114502 | 6/25        | Valid                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>Same Card Data</p>                          |
| 5122351100004505 | 7/25        | Expired                   | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>New Expiration Date</p>                     |
| 5022351100004506 | 8/25        | Failed                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed + Network Token Provision Failed Notifications<br>3. GET response: Card, Account Updater (failed status) and Network Token (failed status) objects are available<br>Same Card Data</p>                                |

**Notes:**

* For Mastercard Account Updater (Account Updater) Enrollment Cards, you can use any Mastercard numbers ending in the following digits, in addition to the above mentioned Mastercard card numbers.
  * **0, 3:** Any future date → Account update response.
  * **2:** Any future date → No change response (card is still valid).
  * **5:** Any future date → Account expiry date update response.
  * **6, 8, 9:** Any future date → Example error response.

The above-mentioned Visa cards are also available [here](/cmp/developer-resources/guides/testing/3ds).

### Method 3a : Network Token Provisioning for Visa/Mastercard Cards with Networks <a href="#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks" id="method-3a--network-token-provisioning-for-visamastercard-cards-with-networks"></a>

Webhook notifications for the listed events will not be triggered. However, a Network Token provisioning success notification will be sent, and Account Updater enrollment success or failure notifications will be generated (note that Account Updater enrollment typically could fail for these cards).

Note that these are testcards from the networks and not real network BINs, hence the attribute properties may not be accurate or consistent for the test cards.

**For test cards to validate Visa Network Tokens, please contact** [**VGS Support**](mailto:support@vgs.io) **or your designated VGS implementation representative.**

| Card Number      | Expiration Date | Expected Response                                                                                                                                                                                                                                                                                                                      |
| ---------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 2222690420064574 | 6/27            | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful/Failure + Network Token Provision Successful (+ sometimes Activated) Notifications<br>3. GET response: Card, Account Updater (enrolled or failed status) and Network Token (active or activated status) objects are available</p> |
| 2222690420064582 | 7/27            | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful/Failure + Network Token Provision Successful (+ sometimes Activated) Notifications<br>3. GET response: Card, Account Updater (enrolled or failed status) and Network Token (active or activated status) objects are available</p> |
| 5120350100064594 | 8/27            | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful/Failure + Network Token Provision Successful (+ sometimes Activated) Notifications<br>3. GET response: Card, Account Updater (enrolled or failed status) and Network Token (active or activated status) objects are available</p> |

### Method 4a : Discover NT Test Cards (Direct to Network) <a href="#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks" id="method-3a--network-token-provisioning-for-visamastercard-cards-with-networks"></a>

<table><thead><tr><th width="249.78125">Use Case</th><th width="240.6092529296875">Test Card Number</th><th width="123.9417724609375">HTTP Status</th><th>Error Code</th></tr></thead><tbody><tr><td>Token Provisioning / Single Token - Happy Path<br><br>Bulk Provision Token Request - Happy Path</td><td>6011000025883707<br>6011012015750069<br>6011000024700456<br>6011000068300544<br>6011012021880256</td><td>200</td><td>0</td></tr><tr><td>Token Provisioning / Single Token - Happy Path - NO PAR<br><br>Bulk Provision Token Request - Happy Path - NO PAR</td><td>6011222244446666<br>6011222244449728</td><td>200</td><td>0</td></tr><tr><td>Token Provisioning / Multiple Tokens - Happy Path</td><td>6011000088618537</td><td>200</td><td>0</td></tr><tr><td>Token Provisioning - Invalid Card</td><td>6011005199449433</td><td>400<br></td><td>10001</td></tr><tr><td>Token Provisioning - Ineligible PAN</td><td>6011005199449441</td><td>400</td><td>10002</td></tr><tr><td>Token Provisioning - Provisioning Count Exceeded</td><td>6011005199449458</td><td>400</td><td>10003</td></tr><tr><td>Token Provisioning - Cryptographic Error</td><td>6011005199449466</td><td>400</td><td>10004</td></tr><tr><td>Token Provisioning - Card Identifier Validation Failed</td><td>6011005199449474</td><td>400</td><td>10006</td></tr><tr><td>Token Provisioning - Account/User Cannot Be Added</td><td>6011005199449482</td><td>400</td><td>10007</td></tr><tr><td>Token Provisioning - Account is already provisioned in the wallet</td><td>6011005199449490</td><td>400</td><td>10009</td></tr><tr><td>Token Provisioning - Name Verification Failed</td><td>6011005199449508</td><td>400</td><td>10010</td></tr><tr><td>Token Provisioning - Expired Card</td><td>6011005199449516</td><td>400</td><td>10012</td></tr><tr><td>Token Provisioning - User Locked</td><td>6011005199449524</td><td>400</td><td>10013</td></tr><tr><td>Token Provisioning - Incorrect Account Details</td><td>6011005199449532</td><td>400</td><td>10014</td></tr><tr><td>Token Provisioning - Invalid Token Requestor Id</td><td>6011005199449540</td><td>400</td><td>10020</td></tr><tr><td>Token Provisioning - API Request Valid/Unexpected Error</td><td>6011005199449557</td><td>400</td><td>30001</td></tr><tr><td>Token Provisioning - API Request Valid/Downstream System Unavailable</td><td>6011005199449565</td><td>400</td><td>30001</td></tr><tr><td>RED-FLOW PAN - Declined Response</td><td>6011012020630389<br>6011000000006548</td><td>200</td><td>non-zero<br>error code</td></tr></tbody></table>

### Method 4b: Discover NT Test Cards (VGS Mock Cards) <a href="#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks" id="method-3a--network-token-provisioning-for-visamastercard-cards-with-networks"></a>

| Test Card        | Expiration | Notification Event |
| ---------------- | ---------- | ------------------ |
| 6599991849593102 | 12/99      | Card Updated       |
| 6599993413164757 | 12/99      | Suspended          |
| 6599992553419286 | 12/99      | Activated          |
| 6599993276483500 | 12/99      | Deleted            |
| 6599993056413958 | 12/99      | Active             |
| 6599993767242381 | 12/99      | Failed             |

### Method 5: Amex NT Test Cards (VGS Mock Cards) <a href="#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks" id="method-3a--network-token-provisioning-for-visamastercard-cards-with-networks"></a>

<table><thead><tr><th width="249.78125">Test Card</th><th width="191.9302978515625">Expiration</th><th width="179.850830078125">Notification Event</th></tr></thead><tbody><tr><td>340000104332183</td><td>12/99</td><td>Card Updated</td></tr><tr><td>340000196001332</td><td>12/99</td><td>Suspended</td></tr><tr><td>340000890838633</td><td>12/99</td><td>Activated</td></tr><tr><td>340000794026541</td><td>12/99</td><td>Deleted<br></td></tr><tr><td>340000235116158</td><td>12/99</td><td>Active</td></tr><tr><td>340000594078163</td><td>12/99</td><td>Failed</td></tr></tbody></table>

**Note:**&#x20;

1. We recommend reviewing our [Forward-Compatible API Integration Guidelines](/cmp#forward-compatible-api-integration) to ensure your integration remains stable as CMP evolves. Avoid strict schema validation or exact JSON comparisons, as new fields may be added to request and response payloads over time.
2. When your account is set to manual mode, automatic Account Updater (AU) and Network Tokenization (NT) processes are not triggered when a card is created. For sandbox cards, you must first manually enroll them in AU. After enrollment, performing a GET request by card ID will return the updated AU and NT values.
3. While American Express (Amex) does not currently support test cards in their sandbox environment Network Tokens, VGS provides mock cards designed to simulate various testing scenarios&#x20;
4. VGS Mock Cards are internally built test cards that do not communicate with the networks.&#x20;


# Get Card

## Get Card API - Mock Testing

For the Get Card API, the testing process is dependent on the card objects created using the Create Card API mock.

* **Valid Card IDs:**
  * When a card object is successfully created using the Create Card API mock using the static BIN method (i.e., the static BIN followed by any random numbers as the PAN), a cardID is returned in the response.
  * When the Get Card API mock is triggered using a valid cardID a success response is returned.
* **Invalid Card IDs:** Using an invalid will return a 404 error response.
* **Other Error Responses:** Depending on the credentials used and the syntax of the request URL, other error messages (e.g., 4XX errors) can be triggered.

### Testing Notes <a href="#testing-notes" id="testing-notes"></a>

* 5XX errors cannot be triggered using the Get Card API mock.
* The Card ID generated using the static BIN method (i.e., the static BIN followed by any random numbers as the PAN) will remain valid until deleted via the Delete by Card ID API and can be tested using the Get Card mock.
* Alternatively, the static card 5100260000099208 will consistently return a GET card response that includes Network Token and Account Updater details.

<br>


# Delete Card

## Delete Card API - Mock Testing <a href="#delete-card-api---mock-testing" id="delete-card-api---mock-testing"></a>

For the Delete Card API, the testing process is dependent on the card objects created using the Create Card API mock.

* **Valid Card IDs:**
  * When a card object is successfully created using the Create Card API mock using the static BIN method (i.e., the static BIN followed by any random numbers as the PAN), a cardID is returned in the response.
  * When the Delete Card API mock is triggered using a valid cardID a success response is returned.
* **Invalid Card IDs:**
  * Using an invalid cardID will return a 404 error response.
* **Other Error Responses:**
  * Depending on the credentials used and the syntax of the request URL, other error messages (e.g., 4XX errors) can be triggered.

Note: 5XX errors cannot be triggered using the Delete Card API mock.


# On-Demand Updates

## On-Demand Updates API - Testing <a href="#on-demand-updates-api---testing" id="on-demand-updates-api---testing"></a>

On-Demand Updates API performs a **one-time lookup** for the most recent Account Updater status without enrolling the card for ongoing updates.

* Real-time updates are supported only for Visa and Mastercard.
* American Express and Discover are not supported for real-time Account Updater lookups.
* This mock does not track future updates and does not enroll the card in Account Updater.

The On-Demand Updates API mock allows you to test real-time card update scenarios for **Visa and Mastercard** cards.

### Testing Steps <a href="#testing-steps" id="testing-steps"></a>

1. **Account Enrollment Type:** Manual Enrollment
2. **Register Cards**: Use the **Create Card API** to register the test cards listed in the table below.
3. **Invoke On-Demand Updates API**: Call the **Card Check API** with the cardIDs obtained in step 2 to simulate a card update check.

To test the On-Demand Account Updater endpoint, first set your account to **manual enrollment**. Then, create cards using the test cards listed below and trigger the On-Demand endpoint individually using each card’s `cardID` generated through this process.

**Note:** If you test this with an account set up for **on-create enrollment** and run the On-Demand endpoint using the card IDs from the test cards, the sync response will show an **enrolled** status, and the actual event will be sent to the async webhook URL configured on your VGS dashboard. Therefore, use these test cards only with accounts set up for **manual enrollment**.

#### Test Cards and Expected Responses <a href="#test-cards-and-expected-responses" id="test-cards-and-expected-responses"></a>

| Test Cards        | Expiry Date | Expected Account Updater Event |
| ----------------- | ----------- | ------------------------------ |
| 4680056031099387  | 8/26        | Expired                        |
| 4403933787254356  | 9/26        | Closed                         |
| 4000220720915104  | 1/25        | Contact cardholder advice      |
| 4327390068355738  | 12/23       | Updated                        |
| 4549612182636736  | 3/23        | Account non-participating      |
| 5100260000099240  | 9/26        | Updated                        |
| 5100260000059244  | 6/26        | Closed                         |
| 51223511000004505 | 7/25        | Expired                        |


# Request Cryptogram

## Request Cryptogram - Testing <a href="#request-cryptogram---testing" id="request-cryptogram---testing"></a>

The **CryptoFetch API** retrieves the cryptogram associated with the **active** Network Tokens for a card. This cryptogram is used to facilitate secure, tokenized transactions.

To successfully test CryptoFetch, the card must have an active Network Tokens provisioned with the network in the sandbox environment.

Refer to [VGS Sandbox Network Token](/cmp/developer-resources/guides/testing/create-card#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks) Provisioning for guidance on provisioning Network Tokens.

### Points to Note <a href="#points-to-note" id="points-to-note"></a>

* **For CMP accounts with `ON-CREATE` enrollment type:**
  * Network Tokens are automatically provisioned when the card is created.
  * Perform a `GET` on the card ID to verify that the Network Tokens status is `active`.
  * Once verified, you can proceed with the CryptoFetch API call.
* **For CMP accounts with `MANUAL` enrollment type:**
  * Network Tokens are **not** provisioned by default.
  * Use the Network Tokens [Provisioning endpoint](/cmp/developer-resources/api/network-tokens#post-cards-card_id-network-tokens) to provision the Network Tokens manually.
  * Then, perform a `GET` to ensure the Network Tokens status is active before calling CryptoFetch.
* **Do not use mock test cards for CryptoFetch testing:**
  * Mock cards do **not** provision Network Tokens with networks.
  * Since CryptoFetch depends on active Network Tokens, it will **not work** with mock cards.

### Testing Steps <a href="#testing-steps" id="testing-steps"></a>

* **Create Cards:** Use the **Create Card API** to register [test cards](/cmp/developer-resources/guides/testing/create-card#method-3a--network-token-provisioning-for-visamastercard-cards-with-networks) that support Network Tokens provisioning in the sandbox.
* **Provision Network Tokens (if required):**
  * Skip this step for`ON-CREATE` enrollment (Network Tokens is auto-provisioned).
  * For MANUAL enrollment, call the Network Tokens [Provisioning endpoint](/cmp/developer-resources/api/network-tokens#post-cards-card_id-network-tokens).
* **Verify Network Tokens Status**: Use the `GET` **Card API** to check that the Network Tokens status is active.
* **Call Request cryptogram API:** Once the Network Tokens is active, use the [Request cryptogram endpoint](/cmp/developer-resources/api/network-tokens#post-cards-card_id-cryptogram) to retrieve the cryptogram for that token.


# Account Updater Webhooks

## Account Updater Webhooks - Mock Testing <a href="#account-updater-webhooks---mock-testing" id="account-updater-webhooks---mock-testing"></a>

You can test the various Account Updater notifications using the the mocks and the following methods:

### Method 1: Fixed Card Numbers for Specific Responses <a href="#method-1-fixed-card-numbers-for-specific-responses" id="method-1-fixed-card-numbers-for-specific-responses"></a>

Using specific card numbers with the Create Card API, you can simulate fixed Account Updater notifications. The following table lists card numbers and the corresponding Account Updater notifications you will receive upon making enrollment/create card request:

| Test Card Number | Test CardIDs                                         | Expiration Date | Notification Event-Triggered | VGS Event                                 | Expected Responses                                                                                                                                                                                                                                                  |
| ---------------- | ---------------------------------------------------- | --------------- | ---------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 5100260000079200 | CRDnKQt89XXFRQVBEzcRvkhvmhs5rpBvxkv3PbeAFPB52zFFqjCR | Any Future Date | Valid                        | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Valid/Successful Notification<br>3. GET response: Card and Account Updater (enrolled status + event = valid field (same card data)) objects are available</p>             |
| 5100260000069201 | CRDqKgQbzM9cUWNUAQR5EFu9BrZuSLP5tgqxadbJBJdqgc2iKQ5i | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 5100260000059202 | CRDoy3ak2ipNi9Fac1tugukHQQi2JWkKdutozwHdd9MWZk9tj31J | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 5100260000049203 | CRDnedYQWP8U4qLZ8dELJTPa3iC3A9ANryT53dAeL8Nmdg21YnZ0 | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>              |
| 5100260000039204 | CRDnExWG9xEu5khrT6Xw3pqi6CEtVei3yeogHgD8GG7jR6fxK2af | Any Future Date | Non\_participating           | cmp\_au\_card.non\_participating          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Non\_Participating Notification<br>3. GET response: Card and Account Updater (enrolled status + event = non\_participating field (same card data)) objects are available</p>    |
| 5100260000029205 | CRDrcHw9DHbRtEQxzWbh86qnAinGiah7QVbFDnZX9jCUqCX78J30 | Any Future Date | Unknown                      | cmp\_au\_card.unknown                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Unknown Notification<br>3. GET response: Card and Account Updater (enrolled status + event = unknown field (same card data)) objects are available</p>                          |
| 5100260000019206 | CRDKfukrUmMsUdotydKS4euZ1v2exoN617mWi7avaehqkYh2J5JP | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status and same card data) objects are available</p>                                       |
| 5100260000009207 | CRDqL55P51GVUMbZMDgYakHQTJSoFP2e8NoMXzhQpVPgLh91ZEQo | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status and same card data) objects are available</p>                                             |
| 4000210000069200 | CRDqoPvUouevmR2sqLGixGh8W7mzwPoveweDNoWSbYRQoWdUbCzd | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 4000210000059201 | CRDoy8VqBYLSYpnYXQcgQuQpTfcT9LtQxaBmUrJdZNckTDoE4Xk5 | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 4000210000049202 | CRDM6fByTJLfGy6fPTp8g65JmWLBJ35hH9AsjU2vz2mY2C4rx87q | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>              |
| 4000210000039203 | CRDnEyXHMB8oWJg7ij2gHUkLCzZz8NaXjSB4GkJkwJqNUNNDEEbo | Any Future Date | Contact cardholder advice    | cmp\_au\_card.contact\_cardholder\_advice | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: CardHolder Advice Notification<br>3. GET response: Card and Account Updater (enrolled status + event = contact\_cardholder\_advice field (same card data) objects are available</p>  |
| 4000210000029204 | CRDnER9L5RRdhgLpJH96hNEizvAqhvkRswXYfsS4dspXaAVaHmtM | Any Future Date | Valid                        | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Valid/Successful Notification<br>3. GET response: Card and Account Updater (enrolled status + event = valid field (same card data)) objects are available</p>             |
| 4000210000019205 | CRDnExMybKBt8N1R3TWjzAyRr8UAbYNJEMpgWguoYBiLxU5rmDpu | Any Future Date | Non participating            | cmp\_au\_card.non\_participating          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Non\_Participating Notification<br>3. GET response: Card and Account Updater (enrolled status + event = non\_participating field (same card data)) objects are available</p>    |
| 4000210000009206 | CRDneB3zHjoDQW9xLKBeF9KtjJhb6eR134XjfPPyisqpcQpmAEHx | Any Future Date | Unknown                      | cmp\_au\_card.unknown                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Unknown Notification<br>3. GET response: Card and Account Updater (enrolled status + event = unknown field (same card data)) objects are available</p>                          |
| 4000210000099207 | CRDoCww5soTmXA7sqtUQ3mS8b8ZAmhHCguWyvMhWMAQLU9UJcFUn | Any Future Date | Opt out                      | cmp\_au\_card.opt\_out                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Opt\_Out Notification<br>3. GET response:Card and Account Updater (enrolled status + event = opt\_out field (same card data)) objects are available</p>                         |
| 4000210000089208 | CRDrc6FX3HbucdEvQCHha7Tkqa2TMT66xV9QDrNzh72NB5mw2R7u | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status and same card data) objects are available</p>                                       |
| 4000210000079209 | CRDoy9WqbTDwadttfKbWSTcbSnYddb8i5naGmDprK4BLBzbCawHg | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status and same card data) objects are available</p>                                             |
| 3400000000829200 | CRDqoPvUouevmR2sqLGixGh8W7mzwPoveweDNoWSbYRQoWdUbCz0 | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 3400000000909200 | CRDoy8VqBYLSYpnYXQcgQuQpTfcT9LtQxaBmUrJdZNckTDoE4Xk1 | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 3400000001089200 | CRDM6fByTJLfGy6fPTp8g65JmWLBJ35hH9AsjU2vz2mY2C4rx872 | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>                            |
| 3400000001329200 | CRDnEyXHMB8oWJg7ij2gHUkLCzZz8NaXjSB4GkJkwJqNUNNDEEb3 | Any Future Date | Contact Cardholder Advice    | cmp\_au\_card.contact\_cardholder\_advice | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: CardHolder Advice Notification<br>3. GET response: Card and Account Updater (enrolled status + event = contact\_cardholder\_advice field (same card data) objects are available</p>  |
| 3400000001169200 | CRDoCww5soTmXA7sqtUQ3mS8b8ZAmhHCguWyvMhWMAQLU9UJcFU2 | Any Future Date | Opt Out                      | cmp\_au\_card.opt\_out                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Opt\_Out Notification<br>3. GET response: Card and Account Updater (enrolled status + event = opt\_out field (same card data)) objects are available</p>                        |
| 3400000001249200 | CRDnER9L5RRdhgLpJH96hNEizvAqhvkRswXYfsS4dspXaAVaHmt4 | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status and same card data) objects are available</p>                                       |
| 3400000004219200 | CRDnExMybKBt8N1R3TWjzAyRr8UAbYNJEMpgWguoYBiLxU5rmDp5 | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status and same card data) objects are available</p>                                             |
| 6599990002379200 | CRDnER9L5RRdhgLpJH96hNEizvAqhvkRswXYfsS4dspXaAVaHmt5 | Any Future Date | Valid                        | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Enrollment Valid/Successful Notification<br>3. GET response: Card and Account Updater (enrolled status + event = valid field (same card data)) objects are available</p>        |
| 6599990002459200 | CRDqoPvUouevmR2sqLGixGh8W7mzwPoveweDNoWSbYRQoWdUbCz6 | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 6599990002529200 | CRDoy8VqBYLSYpnYXQcgQuQpTfcT9LtQxaBmUrJdZNckTDoE4Xk7 | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 6599990002609200 | CRDM6fByTJLfGy6fPTp8g65JmWLBJ35hH9AsjU2vz2mY2C4rx878 | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>                            |
| 6599990002869200 | CRDneB3zHjoDQW9xLKBeF9KtjJhb6eR134XjfPPyisqpcQpmAEHb | Any Future Date | Unknown                      | cmp\_au\_card.unknown                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Unknown Notification<br>3. GET response: Card and Account Updater (enrolled status + event = unknown field (same card data)) objects are available</p>                          |
| 6599990002949200 | CRDnExMybKBt8N1R3TWjzAyRr8UAbYNJEMpgWguoYBiLxU5rmDpb | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status) objects are available</p>                                                          |
| 6599990003109200 | CRDoCww5soTmXA7sqtUQ3mS8b8ZAmhHCguWyvMhWMAQLU9UJcFUc | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status) objects are available</p>                                                                |
| 6599990003289200 | CRDnEyXHMB8oWJg7ij2gHUkLCzZz8NaXjSB4GkJkwJqNUNNDEEbc | Any Future Date | Contact cardholder advice    | cmp\_au\_card.contact\_cardholder\_advice | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: CardHolder Advice Notification<br>3. GET response: Card and Account Updater (enrolled status + event = contact\_cardholder\_advice field (same card data)) objects are available</p> |

Known Fact about Account Updater Notifications Mock Implementation:In the mock environment, the synchronous response from the Create Card API returns the expected cardID—which matches the Account Updater notifications—and accurately replicates the card number, BIN, first 8 digits, and last 4 digits as provided in the request. However, the address and expiration date fields in the mock response will not match the values from the original request.

### Method 2: Any PAN with Specific Mastercard or Visa Bins + Last4 <a href="#method-2-any-pan-with-specific-mastercard-or-visa-bins--last4" id="method-2-any-pan-with-specific-mastercard-or-visa-bins--last4"></a>

You can also test Account Updater notifications by using any PAN (Primary Account Number) that starts with the Mastercard BIN (510026) or Visa BIN (400021) and ends with a last4 in the range 9200-9209. Simply trigger the Create Card/Enrollment process using these PANs. In the Account Updater notifications, three new fields have been added to provide more detailed card information: "card\_first8", "card\_bin", and "card\_last4". These fields will appear in the following Account Updater notifications:

* cmp\_au\_card.contact\_cardholder\_advice
* cmp\_au\_card.closed
* cmp\_au\_card.expired
* cmp\_au\_card.updated

To receive these notifications please ensure to set up the webhook URL on the dashboard. See [here](/cmp/developer-resources/notifications) for details on notification set-up.

| Test Cards             | Expiry Date     | Notification Event-Triggered | VGS Event                                 | Expected Responses                                                                                                                                                                                                                                                  |
| ---------------------- | --------------- | ---------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 510026\*\*\*\*\*\*9200 | Any Future Date | Valid                        | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Valid/Successful Notification<br>3. GET response: Card and Account Updater (enrolled status + event = valid field (same card data)) objects are available</p>             |
| 510026\*\*\*\*\*\*9201 | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 510026\*\*\*\*\*\*9202 | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 510026\*\*\*\*\*\*9203 | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>                            |
| 510026\*\*\*\*\*\*9204 | Any Future Date | Non participating            | cmp\_au\_card.non\_participating          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Non\_Participating Notification<br>3. GET response: Card and Account Updater (enrolled status + event = non\_participating field (same card data)) objects are available</p>    |
| 510026\*\*\*\*\*\*9205 | Any Future Date | Unknown                      | cmp\_au\_card.unknown                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Unknown Notification<br>3. GET response: Card and Account Updater (enrolled status + event = unknown field (same card data)) objects are available</p>                          |
| 510026\*\*\*\*\*\*9206 | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status and same card data) objects are available</p>                                       |
| 510026\*\*\*\*\*\*9207 | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status and same card data) objects are available</p>                                             |
| 400021\*\*\*\*\*\*9200 | Any Future Date | Updated                      | cmp\_au\_card.updated                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Update Notification<br>3. GET response: Card and Account Updater (enrolled status + event = updated field (new pan and expiration date)) objects are available</p>              |
| 400021\*\*\*\*\*\*9201 | Any Future Date | Expired                      | cmp\_au\_card.expired                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Expired Notification<br>3. GET response: Card and Account Updater (enrolled status + event = expired field (new expiration date)) objects are available</p>                     |
| 400021\*\*\*\*\*\*9202 | Any Future Date | Closed                       | cmp\_au\_card.closed                      | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Closed Notification<br>3. GET response: Card and Account Updater (enrolled status + event = closed field (same card data)) objects are available</p>                            |
| 400021\*\*\*\*\*\*9203 | Any Future Date | Contact cardholder advice    | cmp\_au\_card.contact\_cardholder\_advice | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: CardHolder Advice Notification<br>3. GET response: Card and Account Updater (enrolled status + event = contact\_cardholder\_advice field (same card data)) objects are available</p> |
| 400021\*\*\*\*\*\*9204 | Any Future Date | Valid                        | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Valid/Successful Notification<br>3. GET response: Card and Account Updater (enrolled status + event = valid field (same card data)) objects are available</p>             |
| 400021\*\*\*\*\*\*9205 | Any Future Date | Non participating            | cmp\_au\_card.non\_participating          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Non\_Participating Notification<br>3. GET response: Card and Account Updater (enrolled status + event = non\_participating field (same card data)) objects are available</p>    |
| 400021\*\*\*\*\*\*9206 | Any Future Date | Unknown                      | cmp\_au\_card.unknown                     | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Unknown Notification<br>3. GET response: Card and Account Updater (enrolled status + event = unknown field (same card data)) objects are available</p>                          |
| 400021\*\*\*\*\*\*9207 | Any Future Date | Opt-out                      | cmp\_au\_card.opt\_out                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Opt\_Out Notification<br>3. GET response: Card and Account Updater (enrolled status + event = opt\_out field (same card data)) objects are available</p>                        |
| 400021\*\*\*\*\*\*9208 | Any Future Date | Enrolment Successful         | cmp\_au\_card.enrolled                    | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful Notification<br>3. GET response: Card and Account Updater (enrolled status and same card data) objects are available</p>                                       |
| 400021\*\*\*\*\*\*9209 | Any Future Date | Enrolment Failed             | cmp\_au\_card.enrollment\_failed          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Failed Notification<br>3. GET response: Card and Account Updater (failed status and same card data) objects are available</p>                                             |

### Method 3: Account Updater Mock Webhook Notifications with Networks <a href="#method-3-account-updater-mock-webhook-notifications-with-networks" id="method-3-account-updater-mock-webhook-notifications-with-networks"></a>

**Visa, Amex and Discover:** Account Updater notifications cannot be tested because Visa, Amex and Discover network do not provide a mock environment for webhook notifications.

**Mastercard:** For Mastercard Account Updater Notification Cards, you can use any Mastercard numbers ending in the following digits:

* **12:** Account Expiration Date Change Notification
* **22:** Account Number Updated Notification
* **32:** Account Closed Notification:
  * You can generate random luhn valid card numbers [here](https://www.dcode.fr/luhn-algorithm)

#### Examples of Cards for Triggering Events (Expired, Updated, and Closed) <a href="#examples-of-cards-for-triggering-events-expired-updated-and-closed" id="examples-of-cards-for-triggering-events-expired-updated-and-closed"></a>

Below are sample card numbers ending in 12, 22, and 32 that will trigger the respective card events: expired, updated, and closed.

Important Notes:

* You will only receive event notifications for cards that generate a **201 - Card Created Successfully** response.
* For cards that already exist and generate a **303 HTTP Response** (i.e., card already exists), no notifications will be sent.
* To test the event notifications again, please use a **new card number** ending in 12, 22, or 32 each time. You can generate these numbers using the Luhn Algorithm tool [here](https://www.dcode.fr/luhn-algorithm).

| Example Test Cards | Expiry Date | Network Event                                         | Expected Response                                                                                                                                                                                                                                                                                                                            |
| ------------------ | ----------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 5522351100074512   | 7/25        | Card expiration date change notification will be sent | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed + Card Expired Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>    a. New Expiration Date</p>                     |
| 5522351100054522   | 8/25        | Card number updated notification will be sent         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed + Card Updated Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>    a. Updated Card Number and Expiration Date</p> |
| 5522351100034532   | 9/25        | Card closed notification will be sent                 | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Enrollment Successful + Network Token Provision Failed + Card Closed Notifications<br>3. GET response: Card, Account Updater (enrolled status) and Network Token (failed status) objects are available<br>    a. Same Card Data</p>                           |

### Account Updater Enrollment Failure Reason Codes <a href="#account-updater-enrollment-failure-reason-codes" id="account-updater-enrollment-failure-reason-codes"></a>

| Reason Code              | Reason Text                                                                                                                                                                  |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| card-brand-not-supported | XXX card brand is not supported.Currently, only Visa and Mastercard cards are supported. This error will be returned if an Amex, Discover, or any other card scheme is used. |
| declined                 | Vgs merchant not found. This error typically indicates that the customer has not been onboarded to use the account updater with the provided vault credentials.              |
| internal-server-error    | Something went wrong.                                                                                                                                                        |

### Notifications Set Up <a href="#notifications-set-up" id="notifications-set-up"></a>

You can configure a webhook to receive updates for Account Updater. For detailed instructions on setting up notifications, click [here](/cmp/developer-resources/api/account-updater-events).


# Network Tokens Webhooks

## Network Tokens Webhooks - Mock Testing <a href="#network-tokens-webhooks---mock-testing" id="network-tokens-webhooks---mock-testing"></a>

You can test the various Network Token notifications using the mocks and the following methods:

### Method 1: Fixed Card Numbers for Specific Responses <a href="#method-1-fixed-card-numbers-for-specific-responses" id="method-1-fixed-card-numbers-for-specific-responses"></a>

Using specific card numbers with the Create Card API, you can simulate fixed Network Token notifications. The following table lists card numbers and the corresponding Network Token notifications you will receive upon making an enrollment/create card request:

| Test Card Number | Test CardIDs                                         | Expiration Date | Notification Event-Triggered | VGS Event/State/Reason\_Code                                                                                         | Expected Responses                                                                                                                                                                                        |
| ---------------- | ---------------------------------------------------- | --------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 5100260000039220 | CRDpqQNTZMPkjFh4iQJ28grPyZYfPy4nZodLgMPDyK4qEvUpXXQ2 | Any Future Date | CARD\_UPDATED                | <p>Event: cmp\_network\_token.updated<br>State: CARD\_UPDATED<br>Reason\_code: cmp\_card\_updated</p>                | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Updated Notification<br>3. GET response: Card and Network Token (card\_updated status) objects are available</p>      |
| 5100260000029221 | CRDLDNW4pyFMq2meBi3vp5Z88ff8Q8WCKbctmD7hL6CFrCuZGj4T | Any Future Date | SUSPENDED                    | <p>Event: cmp\_network\_token.updated<br>State: SUSPENDED<br>Reason\_code: cmp\_network\_token.suspended</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Suspended Notification<br>3. GET response: Card and Network Token (suspended status) objects are available</p>             |
| 5100260000019222 | CRDrc7GJqNHVAqX3eQFspL2eN7b6gRvj43Q4KRSpiqFEVJotEUcX | Any Future Date | ACTIVE                       | <p>Event: cmp\_network\_token.updated<br>State: ACTIVATED<br>Reason\_code: cmp\_network\_token.activated</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Activated Notification<br>3. GET response: Card and Network Token (activated status) objects are available</p>             |
| 5100260000009223 | CRDqj7n3kRVAmBsD3WkArj4M9tUAh5eDxXpMURUwydPHQ8YSK42F | Any Future Date | DELETED                      | <p>Event: cmp\_network\_token.updated<br>State: DELETED<br>Reason\_code: cmp\_network\_token.deleted</p>             | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Deleted Notification<br>3. GET response: Card and Network Token (deleted status) objects are available</p>                 |
| 5100260000099224 | CRDM1tW9LGUPXHH9BGPePkzC1PNTshezGBHyqURv7K771rQuQpuy | Any Future Date | PROVISIONING SUCCESSFUL      | <p>Event: cmp\_network\_token.updated<br>State: ACTIVE<br>Reason\_code: cmp\_network\_token.provisioned</p>          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Successfully Provisioned Notification<br>3. GET response: Card and Network Token (active status) objects are available</p> |
| 5100260000089225 | CRDpX9ZT8hZtEorWeqb7AhEFmVg4NyvZybBhiJ2W5koED8asxcDv | Any Future Date | PROVISIONING FAILED          | <p>Event: cmp\_network\_token.updated<br>State: FAILED<br>Reason\_code: cmp\_network\_token.provisioning\_failed</p> | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Provisioning Failed Notification<br>3. GET response: Card and Network Token (failed status) objects are available</p>      |
| 4000210000029220 | CRDoxCWvA7CmBLR1mdsirzmtrECuUX1c5G3iqP6HV83zPPcRB7vE | Any Future Date | CARD\_UPDATED                | <p>Event: cmp\_network\_token.updated<br>State: CARD\_UPDATED<br>Reason\_code: cmp\_card\_updated</p>                | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Updated Notification<br>3. GET response: Card and Network Token (card\_updated status) objects are available</p>      |
| 4000210000019221 | CRDM6gJUNUt8BaxaPrJ46jJn6K9NZAN1ip71FrjzDoPe3DKw1wnW | Any Future Date | SUSPENDED                    | <p>Event: cmp\_network\_token.updated<br>State: SUSPENDED<br>Reason\_code: cmp\_network\_token.suspended</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Suspended Notification<br>3. GET response: Card and Network Token (suspended status) objects are available</p>             |
| 4000210000009222 | CRDoCwtdKzpDxbn1sowRCiPRneCMmhm6EogQGKGGi47Eh6KPXzj3 | Any Future Date | ACTIVE                       | <p>Event: cmp\_network\_token.updated<br>State: ACTIVATED<br>Reason\_code: cmp\_network\_token.activated</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Activated Notification<br>3. GET response: Card and Network Token (activated status) objects are available</p>             |
| 4000210000099223 | CRDqjBoPbYX9ZtVXpDX2vvSmtpUFq9DUHcbZUuTQ3XeXP8rxgge2 | Any Future Date | DELETED                      | <p>Event: cmp\_network\_token.updated<br>State: DELETED<br>Reason\_code: cmp\_network\_token.deleted</p>             | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Deleted Notification<br>3. GET response: Card and Network Token (deleted status) objects are available</p>                 |
| 4000210000089224 | CRDpSY16wcG9484FtM2h7DEhXkeQXdMaTpeJTaEvfutjnJa9BBTw | Any Future Date | PROVISIONING SUCCESSFUL      | <p>Event: cmp\_network\_token.updated<br>State: ACTIVE<br>Reason\_code: cmp\_network\_token.provisioned</p>          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Successfully Provisioned Notification<br>3. GET response: Card and Network Token (active status) objects are available</p> |
| 4000210000079225 | CRDKLBY6Es9jW8vyJZnTPFWNNZVBVhWeoJJUUHZqWpvPhHxq1EmY | Any Future Date | PROVISIONING FAILED          | <p>Event: cmp\_network\_token.updated<br>State: FAILED<br>Reason\_code: cmp\_network\_token.provisioning\_failed</p> | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Provisioning Failed Notification<br>3. GET response: Card and Network Token (failed status) objects are available</p>      |

Known Fact about Network Token Notifications Mock Implementation: In the mock environment, the synchronous response from the Create Card API returns the expected cardID—which matches the Network Token notifications—and accurately replicates the card number, BIN, first 8 digits, and last 4 digits as provided in the request. However, the address and expiration date fields in the mock response will not match the values from the original request.

### Method 2: Any PAN with Specific Mastercard or Visa Bins + Last4 <a href="#method-2-any-pan-with-specific-mastercard-or-visa-bins--last4" id="method-2-any-pan-with-specific-mastercard-or-visa-bins--last4"></a>

You can also test Account Updater notifications using any 16-digit PAN (Primary Account Number) that starts with the Mastercard BIN (`510026`) or Visa BIN (`400021`) and ends with a last4 value in the range `9220`–`9225`. To do this, trigger the Create Card/Enrollment flow with a PAN constructed using the specified BIN and one of the supported last4 values.\
\
For Network Token notifications, the `network_token_bin` field has been added. We have also added a new `reason_code` field to help uniquely identify the Network Token event that was triggered.

To receive these notifications please ensure to set up the webhook URL on the dashboard. See [here](/cmp/developer-resources/notifications) for details on notification set-up.

| Test Cards             | Expiry Date     | Notification Event-Triggered | VGS Event                                                                                                            | Expected Response                                                                                                                                                                                         |
| ---------------------- | --------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 510026\*\*\*\*\*\*9220 | Any Future Date | CARD\_UPDATED                | <p>Event: cmp\_network\_token.updated<br><br>State: CARD\_UPDATEDReason\_code: cmp\_card\_updated</p>                | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Updated Notification<br>3. GET response: Card and Network Token (card\_updated status) objects are available</p>      |
| 510026\*\*\*\*\*\*9221 | Any Future Date | SUSPENDED                    | <p>Event: cmp\_network\_token.updated<br><br>State: SUSPENDEDReason\_code: cmp\_network\_token.suspended</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Suspended Notification<br>3. GET response: Card and Network Token (suspended status) objects are available</p>             |
| 510026\*\*\*\*\*\*9222 | Any Future Date | ACTIVE                       | <p>Event: cmp\_network\_token.updated<br><br>State: ACTIVATEDReason\_code: cmp\_network\_token.activated</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Activated Notification<br>3. GET response: Card and Network Token (activated status) objects are available</p>             |
| 510026\*\*\*\*\*\*9223 | Any Future Date | DELETED                      | <p>Event: cmp\_network\_token.updated<br><br>State: DELETEDReason\_code: cmp\_network\_token.deleted</p>             | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Deleted Notification<br>3. GET response: Card and Network Token (deleted status) objects are available</p>                 |
| 510026\*\*\*\*\*\*9224 | Any Future Date | PROVISIONING SUCCESSFUL      | <p>Event: cmp\_network\_token.updated<br><br>State: ACTIVEReason\_code: cmp\_network\_token.provisioned</p>          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Successfully Provisioned Notification<br>3. GET response: Card and Network Token (active status) objects are available</p> |
| 510026\*\*\*\*\*\*9225 | Any Future Date | PROVISIONING FAILED          | <p>Event: cmp\_network\_token.updated<br><br>State: FAILEDReason\_code: cmp\_network\_token.provisioning\_failed</p> | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Provisioning Failed Notification<br>3. GET response: Card and Network Token (failed status) objects are available</p>      |
| 400021\*\*\*\*\*\*9220 | Any Future Date | CARD\_UPDATED                | <p>Event: cmp\_network\_token.updated<br><br>State: CARD\_UPDATEDReason\_code: cmp\_card\_updated</p>                | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Card Updated Notification<br>3. GET response: Card and Network Token (card\_updated status) objects are available</p>      |
| 400021\*\*\*\*\*\*9221 | Any Future Date | SUSPENDED                    | <p>Event: cmp\_network\_token.updated<br><br>State: SUSPENDEDReason\_code: cmp\_network\_token.suspended</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Suspended Notification<br>3. GET response: Card and Network Token (suspended status) objects are available</p>             |
| 400021\*\*\*\*\*\*9222 | Any Future Date | ACTIVE                       | <p>Event: cmp\_network\_token.updated<br><br>State: ACTIVATEDReason\_code: cmp\_network\_token.activated</p>         | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Activated Notification<br>3. GET response: Card and Network Token (activated status) objects are available</p>             |
| 400021\*\*\*\*\*\*9223 | Any Future Date | DELETED                      | <p>Event: cmp\_network\_token.updated<br><br>State: DELETEDReason\_code: cmp\_network\_token.deleted</p>             | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Deleted Notification<br>3. GET response: Card and Network Token (deleted status) objects are available</p>                 |
| 400021\*\*\*\*\*\*9224 | Any Future Date | PROVISIONING SUCCESSFUL      | <p>Event: cmp\_network\_token.updated<br><br>State: ACTIVEReason\_code: cmp\_network\_token.provisioned</p>          | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Successfully Provisioned Notification<br>3. GET response: Card and Network Token (active status) objects are available</p> |
| 400021\*\*\*\*\*\*9225 | Any Future Date | PROVISIONING FAILED          | <p>Event: cmp\_network\_token.updated<br><br>State: FAILEDReason\_code: cmp\_network\_token.provisioning\_failed</p> | <p>1. Sync response: Card Object Creation Successful<br>2. Async notification: Provisioning Failed Notification<br>3. GET response: Card and Network Token (failed status) objects are available</p>      |

### Method 3: Network Token Mock Webhook Notifications with Networks <a href="#method-3-network-token-mock-webhook-notifications-with-networks" id="method-3-network-token-mock-webhook-notifications-with-networks"></a>

**Both Visa and Mastercard** Network Token notifications cannot be tested because both networks do not provide a mock environment for Network Token webhook notifications. Please refer to Method 1 above to test Network Token Notifications.

### Network Token Provisioning Failure Reason Codes <a href="#network-token-provisioning-failure-reason-codes" id="network-token-provisioning-failure-reason-codes"></a>

| Reason Code              | Reason Text                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| card\_enrollment\_failed | Invalid payment instrument or data associated with the payment instrument                                    |
| card\_not\_allowed       | Card cannot be used for tokenization at this moment. Please try again later                                  |
| card\_not\_allowed       | The requested action is not allowed for a given PAN. This card is valid but cannot be used for tokenization. |
| declined                 | This card is not eligible for tokenization at this moment with the Network; Retry at a later time.           |
| declined                 | No further operations are allowed. Contact bank                                                              |
| service\_unavailable     | Downstream service unavailable; retry later                                                                  |
| rejected                 | This card is not eligible for tokenization at this moment with the Network; Retry later.                     |

### Notifications Set Up <a href="#notifications-set-up" id="notifications-set-up"></a>

You can configure a webhook to receive updates for the Network Token. For detailed instructions on setting up notifications, click [here](/cmp/developer-resources/api/network-token-events).

<br>


# Card Attributes

## Create Card and Get Card API - Test Cards <a href="#network-tokens-webhooks---mock-testing" id="network-tokens-webhooks---mock-testing"></a>

Use the following Cards for testing in the Sandbox environment. Please note that only these specific Cards are supported.

The Card Attribute Service response return 8-digit BINs for Mastercard and Visa, and 6-digit BINs for Discover and American Express (Amex)

<table><thead><tr><th width="211.2550048828125">BIN or PAN</th><th width="178.6307373046875">Attributes </th><th>Response</th></tr></thead><tbody><tr><td>4545 6322 6796 4322<br>4147 2061 0764 1002<br>5102 5899 9999 9913<br>5322 3400 0000 0000<br>5200 4000 0000 0009<br>4000 0330 0330 0335<br>4000 0566 5566 5556<br>4110 1441 1014 4115<br>5102 5899 9999 9913<br>5105 1051 0510 5100<br>3782 8224 6310 005<br>3714 4963 5398 431<br>3787 3449 3671 000<br>6011 9811 1111 1113<br>6011 9500 0602 0887<br>6011 6099 0000 0003<br>4111 1111 1111 1111<br>4012 0000 3333 0125<br>4622 94</td><td>Enriched Attributes</td><td>Comprehensive JSON in API Reference</td></tr><tr><td>5104 6000 0000 0001</td><td>HSA</td><td>True indicates the card is attached to a Health Savings Account</td></tr><tr><td>5299 2300 0000 0002</td><td>Virtual Card</td><td>True indicates the given BIN range supports virtual card creation. </td></tr><tr><td>6026 7500 0000 0007</td><td>EBT</td><td>True indicates the BIN has Electronic Benefits Transfer (EBT) capabilities</td></tr><tr><td>3713 9930 0000 0008</td><td>FSA</td><td>True indicates the card is attached to a Flexible Spending Account</td></tr><tr><td>4871 0499 9999 9902</td><td>Additional Network </td><td>Indicates the card is a co-badged card with an additional network (BANCONTACT), giving cardholders flexibility in how their transaction is processed.</td></tr><tr><td>4977 6303 5000 0001</td><td>Additional Network</td><td>Indicates the card is a co-badged card with an additional network (CB), giving cardholders flexibility in how their transaction is processed.</td></tr><tr><td>5178 0530 0000 0004</td><td>Basic Attributes</td><td>Returns only Card Brand and Card Type.</td></tr><tr><td>4360 0000 0100 0005</td><td>Commercial Level 2</td><td>Returns True to Indicate Commercial Level 2 interchange rate eligibility.</td></tr><tr><td>4035 5014 2814 6300</td><td>Commercial Level 3</td><td>Returns True to Indicate Commercial Level 3 interchange rate eligibility.</td></tr></tbody></table>


# 3DS

### **3D Secure (3DS) Testing Guide**

This guide explains how to test **3DS initialize and authentication flows** in a controlled environment. You can simulate various responses, including **challenge flows**, **frictionless flows**, and **HTTP error scenarios**, to see how your application behaves.

Testing can be performed in two ways:

1. **Mock Card Testing** – using static card IDs that simulate specific responses.
2. **Sandbox Testing** – using test PANs in a sandbox environment.

### **General Setup**

* **Enable 3DS on your account.**
  * To enable 3DS, provide the CMP account ID for the environment you want to enable, along with the merchant name, URL, and country.
  * **To configure 3DS on your account, please reach out to your VGS representative.**
* **Content-Type Header:** `application/vnd.api+json`
* **HTTP Method:** `POST`
* Each request includes a unique `merchant_transaction_id` to track transactions.
* Initialize Responses typically include a `device_fingerprinting_html` (device fingerprinting) that must be submitted to the ACS.
* Challenge responses usually contain a **Challenge Form** which is submitted to display the challenge questionnaire to the user.
* Asynchronous notifications (**webhooks**) are sent once device fingerprinting and the user’s authentication challenge are completed and processed by the ACS.

### 3DS Initialize API - **Mock Card Testing**

Test different 3DS scenarios without using real cards. Each static `cardID` returns a predefined response (success, frictionless, challenge, or error). When using these mock card IDs, you do *not* need 3DS enabled on your account and you do *not* need to generate a JWT auth token. Simply replace `{cardID}` with one of the static mock values.&#x20;

**Base URL:**&#x20;

```
https://gw-01-sandbox.vgsapi.com/3ds-mocks
```

**Initialize API Endpoint:**

```
POST /cards/{cardID}/3ds-initialize
```

**Example Request:**

```bash
curl -X POST "https://gw-01-sandbox.vgsapi.com/3ds-mocks/cards/CRAbcDefGhijKlmNoPqrStuVw/3ds-initialize" \
-H "Content-Type: application/vnd.api+json"
```

<table><thead><tr><th width="204.86419677734375">Test cardID</th><th width="185.6978759765625">Expected HTTP Status</th><th>Expected Response / Notes</th></tr></thead><tbody><tr><td>CRAbcDefGhijKlmNoPqrStuVw</td><td>200 OK</td><td><p>Returns the synchronous response with the iframe/data needed to proceed with authentication. </p><p></p><p><strong>Please note:</strong> rendering the iframe from this mock response will not trigger issuer fingerprinting or send the async notification. To trigger device fingerprinting and receive the async notification, you must submit the iframe on your checkout HTML using sandbox cards.</p></td></tr><tr><td>CRnOiFrAmEqDxRgXU3TFmtcD</td><td>206 OK</td><td>Returns a synchronous response without iframe/data, confirming that initialization is not required and the authentication process can proceed immediately.</td></tr><tr><td>CRaZcXeVtBrNnMpLoKjIhUgYt</td><td>400 Bad Request</td><td>Simulates a 400 error from the initialize endpoint.</td></tr><tr><td>CRdFhJkLmNoPqRsTuVwXyZ012</td><td>401 Unauthorized</td><td>Simulates a 401 error from the initialize endpoint.</td></tr><tr><td>CRpOiUytRewQAzXswEdcRfVtB</td><td>403 Forbidden</td><td>Simulates a 403 error from the initialize endpoint.</td></tr><tr><td>CRuYtRewQAzWsXeDcRfVtGbYh</td><td>404 Not Found</td><td>Simulates a 404 error from the initialize endpoint.</td></tr><tr><td>CRiKoLpMnBvCxZaQsWeRdTfYg</td><td>422 Unprocessable Entity</td><td>Simulates a 422 error from the initialize endpoint.</td></tr><tr><td>CRzXaScVbNmLkJhgFdSaQwErT</td><td>500 Internal Server Error</td><td>Simulates a 500 error from the initialize endpoint.</td></tr><tr><td>CRbNtMvCxZlKjHgFdSaQwErTy</td><td>503 Service Unavailable</td><td>Simulates a 503 error from the initialize endpoint.</td></tr></tbody></table>

### 3DS Initialize API - **Sandbox Testing**

Test 3DS flows using **test PANs** in a sandbox environment. This is closer to production and safe for testing. **When using Sandbox, 3DS must be enabled on your account**. You’ll also need a service account with the required 3DS scopes and must use it to generate a JWT auth token.

**Base URL:**

```
https://sandbox.vgsapi.com
```

**Initialize API Endpoint:**

```
POST /cards/{card_id}/3ds-initialize
```

**Sample Request Body:**

```json
{
  "data": {
    "attributes": {
      "token_type": "pan",
      "transaction_info": {
        "merchant_transaction_id": "12346586",
        "xid": "UgG20AB6E6dceR1gDg8I8VtxoHk="
      }
    }
  }
}
```

<table><thead><tr><th width="204.86419677734375">Test Card/Pan</th><th width="118.0833740234375">Expiration Date</th><th>Expected Response / Notes</th><th>HTTP Status Code</th></tr></thead><tbody><tr><td>4016360000000493</td><td>Any Future Date</td><td><p>Returns the synchronous response with the iframe/form needed to proceed with authentication. </p><p></p><p>Look for <strong>device_fingerprinting_html</strong> field in the Initialize sync response.</p></td><td>200</td></tr><tr><td>5188340000000969</td><td>Any Future Date</td><td><p>Returns the synchronous response with the iframe/form needed to proceed with authentication. </p><p></p><p>Look for <strong>device_fingerprinting_html</strong> field in the Initialize sync response.</p></td><td>200</td></tr><tr><td>4016365555555493</td><td>Any Future Date</td><td><p>Returns a synchronous response without iframe/data, confirming that initialization is not required and the authentication process can proceed immediately. </p><p></p><p><strong>device_fingerprinting_html</strong> field will not be present in the Initialize sync response.</p></td><td>206 (Partial Content)</td></tr></tbody></table>

**Note: VGS Collect Integration:** Collect requires Luhn-valid card numbers by default. Because the current 3DS sandbox test card numbers are not Luhn-valid, Collect’s default validation will reject them. If you are testing through your Checkout Component with Collect, override the default validation on the Card Number field and use a custom validation rule like the one below. After making this change, you should be able to proceed with testing the sandbox 3DS cards through Collect.

#### **Invoking 3DS Device Fingerprinting**

1. **Prepare Request**
   * Ensure `merchant_transaction_id` is **unique** for each request.
   * The synchronous response will include a **3DS Method Form** in `device_fingerprinting_html` with a hidden field `threeDSMethodData`.
2. **Run Device Fingerprinting**
   * This simulates the device fingerprinting between the browser and the ACS/Issuer.
   * Posting `threeDSMethodData` to the ACS allows it to collect device/browser info and triggers an **asynchronous 3DS Method Completion** notification to your configured webhook. Extract `<input type="hidden" name="threeDSMethodData" value="..."/>` from `device_fingerprinting_html`.
   * Create a local HTML file and embed the value in this snippet:

```html
<!doctype html>
<html lang="en">
<body onload="document.forms[0].submit()">
  <form action="https://3ds-acs.test.modirum.com/mdpayacs/3ds-method" method="post" target="hiddenFrame">
    <input type="hidden" name="threeDSMethodData" value="<threeDSMethodData>" />
  </form>
  <iframe name="hiddenFrame" style="display:none"></iframe>
  <p>The form has been submitted to ACS. View the callback <a href="https://play.svix.com/view/e_y4H4J9EA18Hm1Y1Ws5XeVaU45Lq" target="_blank">here</a>.</p>
</body>
</html>
```

3. **Execute and Observe**
   * Open the HTML file in a browser; it auto-submits to ACS.
   * Observe the **asynchronous 3DS Method Completion notification** at your configured notification URL.&#x20;
   * Refer to the VGS Dashboard to **set up notification URL** and **configure 3DS events**.
     * [Configure 3DS events](/cmp/developer-resources/notifications#cmp-3ds-events)
     * [Set up your notification URL](/enterprise-platform/developer-resources/webhook-notifications)

![](/files/9s1PDGCceygYRrRYh8Om)

### **3DS Authenticate API - Mock Card Testing**

The 3DS **Authenticate** API (`/cards/{cardID}/3ds-authenticate`) simulates the final authentication response.

* For **frictionless** flows, this will be the synchronous response.
* For **challenge** flows, this response will be sent in the asynchronous webhook notification.

You can test various authentication outcomes and error scenarios by providing the corresponding `cardID` as part of the URL path.

**Example Request URL:&#x20;**<mark style="color:orange;">**POST**</mark>**&#x20;** [<mark style="color:blue;">`https://gw-01-sandbox.vgsapi.com/3ds-mocks`</mark>](https://gw-01-sandbox.vgsapi.com/3ds-mocks)<mark style="color:blue;">`/cards/CRAbcDefGhijKlmNoPqrStuVw/3ds-authenticate`</mark>

**Example CURL:**

{% code overflow="wrap" %}

```
curl -X POST "https://gw-01-sandbox.vgsapi.com/3ds-mocks/cards/CRcHaLlEnGeReQdXU3TFmtcD/3ds-authenticate"
-H "Content-Type: application/vnd.api+json"
```

{% endcode %}

**Test `cardID`s and Expected Responses**

<table><thead><tr><th width="147.92327880859375">Test cardID</th><th width="125.3294677734375">Expected HTTP Status</th><th width="181.8585205078125">Expected status (in JSON response)</th><th>Notes</th></tr></thead><tbody><tr><td>CRAbcDefGhijKlmNoPqrStuVw</td><td>200 OK</td><td>AUTHENTICATED</td><td>Simulates a successful authentication (final auth response).</td></tr><tr><td>CRcHaLlEnGeReQdXU3TFmtcD</td><td>200 OK</td><td>CHALLENGE_REQUIRED</td><td><p>Simulates a response that includes the prebuilt HTML form (<code>challenge_form</code>) to directly render the challenge or build your own form using <code>challenge_url</code>, <code>challenge_request</code>, and <code>challenge_session_data</code>. </p><p></p><p><strong>Please note:</strong> rendering the <code>challenge_form</code> from this mock response will not trigger the challenge questionnaire. To trigger the challenge form and receive the async notification, you must submit the html on your checkout page using sandbox cards.</p></td></tr><tr><td>CRXyZ0123456789abcDEfGhij</td><td>200 OK</td><td>INFORMATIONAL_ONLY</td><td>Simulates an informational-only status for a frictionless auth result.</td></tr><tr><td>CRMnOpQrStUvWxYzABCdefGhi</td><td>200 OK</td><td>REJECTED</td><td>Simulates a rejected status for the auth result.</td></tr><tr><td>CRQrStUvWxYz0123456789AbC</td><td>200 OK</td><td>UNABLE_TO_AUTHENTICATE</td><td>Simulates an unable to authenticate status for the auth result.</td></tr><tr><td>CRDecqZp3xRgXU3TFmtcDdzQs</td><td>200 OK</td><td>DENIED</td><td>Simulates a denied status for the auth result.</td></tr><tr><td>CRaZcXeVtBrNnMpLoKjIhUgYt</td><td>400 Bad Request</td><td>N/A (Error Response)</td><td>Simulates a 400 error from the authenticate endpoint.</td></tr><tr><td>CRdFhJkLmNoPqRsTuVwXyZ012</td><td>401 Unauthorized</td><td>N/A (Error Response)</td><td>Simulates a 401 error from the authenticate endpoint.</td></tr><tr><td>CRpOiUytRewQAzXswEdcRfVtB</td><td>403 Forbidden</td><td>N/A (Error Response)</td><td>Simulates a 403 error from the authenticate endpoint.</td></tr><tr><td>CRuYtRewQAzWsXeDcRfVtGbYh</td><td>404 Not Found</td><td>N/A (Error Response)</td><td>Simulates a 404 error from the authenticate endpoint.</td></tr><tr><td>CRiKoLpMnBvCxZaQsWeRdTfYg</td><td>422 Unprocessable Entity</td><td>N/A (Error Response)</td><td>Simulates a 422 error from the authenticate endpoint.</td></tr><tr><td>CRzXaScVbNmLkJhgFdSaQwErT</td><td>500 Internal Server Error</td><td>N/A (Error Response)</td><td>Simulates a 500 error from the authenticate endpoint.</td></tr><tr><td>CRbNtMvCxZlKjHgFdSaQwErTy</td><td>503 Service Unavailable</td><td>N/A (Error Response)</td><td>Simulates a 503 error from the authenticate endpoint.</td></tr></tbody></table>

### **3DS Authentication API – Sandbox Testing**

Use the 3DS Authentication API to simulate different challenge flow responses in Sandbox.\
As with Initialize, Sandbox behavior closely mirrors production and is safe for end-to-end testing.

To test Auth in Sandbox, ensure:

* 3DS is **enabled** for the network you are testing
* Your account has a **notification URL** configured
* You are using a **service account** with the required 3DS scopes to generate a JWT

**Base URL**

```
https://sandbox.vgsapi.com
```

**Auth API Endpoint**

```
POST /cards/{card_id}/3ds-authenticate
```

**Headers**

```
Accept: text 
Accept-Language: text (e.g. en-US)
Content-Type: application/vnd.api+json
```

**Sample Auth Request**

(Must reuse the `merchant_transaction_id` and `xid` from your initialize call)

```json
{
  "data": {
    "attributes": {
      "auth_type": "challenge",
      "token_type": "pan",
      "redirect_url": "https://www.merchant-website.com/purchase-complete",
      "transaction_info": {
        "xid": "E6Kdhoz49St6A2uhf//tZFeXq8Q=",
        "merchant_transaction_id": "f1ec2b0b-bf68-4f2e-9ad5-a60fd04ebdf8"
      },
      "purchase_info": {
        "currency_code": "USD",
        "amount": 1002.25
      },
      "browser_info": {
        "java_enabled": "false",
        "javascript_enabled": "true",
        "language": "en-US",
        "color_depth": 24,
        "screen_height": 1080,
        "screen_width": 1920,
        "tz": -240
      },
      "merchant_info": {
        "acquirer_bin": "444444",
        "acquirer_country_code": "USA",
        "acquirer_requestor_name": "CoffeeHouse",
        "acquirer_requestor_id": "1000",
        "acquirer_merchant_id": "1000",
        "name": "CoffeeHouse",
        "category_code": "4829",
        "country_code": "CAN",
        "website_url": "https://www.coffeehouse.com"
      }
    }
  }
}
```

#### **⚠️ Important Sandbox Requirements**

* **VGS Collect Integration:** Collect requires Luhn-valid card numbers by default. Because the current 3DS sandbox test card numbers are not Luhn-valid, Collect’s default validation will reject them. If you are testing through your Checkout Component with Collect, override the default validation on the Card Number field and use a custom validation rule like the one below. After making this change, you should be able to proceed with testing the sandbox 3DS cards through Collect.

```
form.cardNumberField(`#${panId}`, { validations: ["required"] })                    
```

* When testing in **Sandbox**, the following apply:
  * **All fields under `merchant_info` are required**.
  * The following fields must use these exact values:

```json
"acquirer_bin": "444444",
"acquirer_requestor_id": "1000",
"acquirer_merchant_id": "1000"
```

#### **ℹ️ Production Requirements**

In **Production**:

* `acquirer_requestor_id` and `acquirer_requestor_name` are **optional** for **Visa** and **Mastercard**.
* All other fields should follow the network-specific requirements you receive during acquirer setup.

> *For more information on how to use 3DS with VGS, see the guide* [*here*](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds#using-3ds-with-vgs)*.*
>
> *For additional network-specific guidance on requestor identifiers, see* [*here*](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds#requestor-identifier-guidance-per-network)*.*

#### **Understanding the Auth Response**

After calling Auth, you will get one of two outcomes:

<table><thead><tr><th width="40">#</th><th width="130.3359375">Type</th><th width="291.70703125">Description</th><th>Example / Notes</th></tr></thead><tbody><tr><td>1</td><td>Synchronous Auth Result</td><td>For certain test PANs, the final 3DS result is returned directly in the auth response. No browser interaction is required.</td><td><ol><li>APPROVED</li><li>DENIED</li><li>ATTEMPTS_PERFORMED</li><li>REJECTED</li><li>UNABLE_TO_AUTHENTICATE</li></ol></td></tr><tr><td>2</td><td>Challenge Flow (Async)</td><td>If the response includes <strong>data.attributes.challenge_info.challenge_form</strong>, a browser-based challenge must be performed.</td><td>N/A</td></tr></tbody></table>

#### **How to Execute the `challenge_form` Returned in the Auth Response**

If the Auth API returns a challenge, you’ll receive:

```
data.attributes.challenge_info.challenge_form
```

This is **ready-to-run HTML** that must be rendered **exactly as provided**.

To execute it, inject the `challenge_form` HTML directly into your checkout page or an iframe you control. Examples include:

* Setting it as the innerHTML of a container
* Writing it into an iframe
* Rendering it inside a modal that can execute HTML

The HTML already includes:

* The ACS form
* All required hidden fields
* Auto-submit behavior
* Redirect/iframe handling
* Any UI needed for the challenge (password entry or simulation buttons)

**Do not** save it to a file, modify or sanitize it, wrap it in another form, or rebuild the structure.\
This breaks the challenge because the ACS expects the **exact form layout**, the auto-submit must run inside a real browser DOM, and the HTML may rely on specific parent/iframe context.

Render it as-is to ensure the ACS challenge runs correctly. Once the challenge is executed and completed, the authentication flow proceeds, and the final 3DS result is returned to the **configured async webhook**.

#### **Auth Testing Cards (Sandbox)**

Below are all supported test cards and their expected behaviors.

* **VGS Collect Integration:** Collect requires Luhn-valid card numbers by default. Because the current 3DS sandbox test card numbers are not Luhn-valid, Collect’s default validation will reject them. If you are testing through your Checkout Component with Collect, override the default validation on the Card Number field and use a custom validation rule like the one below. After making this change, you should be able to proceed with testing the sandbox 3DS cards through Collect.

```
form.cardNumberField(`#${panId}`, { validations: ["required"] })                    
```

**Mastercard**

<table><thead><tr><th width="208.03515625">Test Card PAN</th><th width="125.875">Result Type</th><th width="257.3125">Expected Status</th><th>Notes</th></tr></thead><tbody><tr><td>5239290700000151</td><td><strong>Async</strong></td><td>APPROVED</td><td>Password challenge → use <code>secret!33</code></td></tr><tr><td>5239290700000102</td><td><strong>Sync</strong></td><td>APPROVED</td><td>—</td></tr><tr><td>5188340000000629</td><td><strong>Sync</strong></td><td>DENIED</td><td>—</td></tr><tr><td>5188340000000937</td><td><strong>Sync</strong></td><td>ATTEMPTS_PERFORMED</td><td>—</td></tr><tr><td>5188340000000952</td><td><strong>Sync</strong></td><td>REJECTED</td><td>—</td></tr><tr><td>5188340000000222</td><td><strong>Sync</strong></td><td>APPROVED</td><td>—</td></tr><tr><td>5188340000000445</td><td><strong>Sync</strong></td><td>UNABLE_TO_AUTHENTICATE</td><td>With <code>acs_info</code></td></tr></tbody></table>

**Visa**

<table><thead><tr><th width="223.0546875">Test Card PAN</th><th>Result Type</th><th>Expected Status</th><th>Notes</th></tr></thead><tbody><tr><td>4016360000000493</td><td><strong>Async</strong></td><td>APPROVED / ATTEMPTED / DENIED / REJECTED / UNAVAILABLE</td><td>Buttons simulate every result</td></tr><tr><td>4147463011110134</td><td><strong>Sync</strong></td><td>APPROVED</td><td>—</td></tr><tr><td>4147463011110142</td><td><strong>Sync</strong></td><td>DENIED</td><td>—</td></tr><tr><td>4147463011110159</td><td><strong>Sync</strong></td><td>ATTEMPTS_PERFORMED</td><td>—</td></tr><tr><td>4147463011110175</td><td><strong>Sync</strong></td><td>REJECTED</td><td>—</td></tr><tr><td>4147463011110167</td><td><strong>Sync</strong></td><td>UNABLE_TO_AUTHENTICATE</td><td>With <code>acs_info</code></td></tr></tbody></table>

### **Content Security Policy (CSP) Requirements for 3DS Challenge Flow**

When testing 3DS challenge flows, you may notice that the `challenge_url` domain changes depending on the card used. This is expected behavior.

The `challenge_url` returned in the authentication response is generated dynamically by the issuer’s **Access Control Server (ACS)**. Because different issuers may use different ACS endpoints, the challenge domain can vary from one card to another. For that reason, there is **not** a fixed issuer-by-issuer domain list that can be shared in advance.

To ensure the 3DS challenge flow works correctly, your application’s **Content Security Policy (CSP)** must be configured broadly enough to allow these dynamically generated challenge URLs and related scripts to load.

#### **Recommended CSP settings**

**Sandbox / Test**

```
default-src 'self' *.modirum.com; frame-src https://*;
```

**Production**

```
default-src 'self' *.entersekt.eu; frame-src https://*;
```

#### **Important notes**

* The `challenge_url` cannot be known ahead of time.
* The domain may vary depending on the issuer / ACS and the card being used.
* Because of this, CSP should allow loading content from dynamically generated `https://*` challenge URLs so the challenge flow can complete successfully.
* There is no fixed issuer-specific domain allowlist available for this flow.


# Account Validation

### **Account Validation Testing Guide**

This guide explains how to test Account Validation in a controlled environment. You can simulate various responses using different test PANs for the Account Validation endpoint and the expected responses for each.

Sandbox testing coverage is limited. Some scenarios, including the CVC use case, are not yet supported in this environment. We are actively working with the network to make these available.

**Very Important Information:** Please use only the provided test cards for this process. Under no circumstances should you input real PANs or live card data.

### Onboarding&#x20;

* Create a CMP Account in Sandbox or use an existing account.&#x20;
* Create a service account with the following `card:write`, `card:read`, `account:write`, `account:read`, `account-validations:write`, `account-validations:read` .
* Create Card IDs using the PANs below

### **General Setup**

* **Content-Type Header:** `application/vnd.api+json`
* **HTTP Method:** `POST`&#x20;
* **Authentication:** <https://auth.verygoodsecurity.com/auth/realms/vgs/protocol/openid-connect/token>

**Base URL:**&#x20;

```
https://sandbox.vgsapi.com
```

**Initialize API Endpoint:**

```
POST /cards/{cardID}/validations
```

**Example Request:**

* Merchant should use the test data in the request below during test in sandbox to get positive responses.
  * `cvc`
  * `cardholder_address`
  * `cardholder_name`
* Merchant must provide the below information in every request.
  * `merchant_name`
  * `address`

```bash
{
  "data": {
    "attributes": {
      "cvc": "022",
      "cardholder_address": {
        "street": "900 Metro Center Blv",
        "postal_code": "94404"
      },
      "cardholder_name": {
        "first_name": "ACCOUNT",
        "middle_name": "NAME",
        "last_name": "INQUIRY"
      },
      "merchant": {
        "merchant_name": "ABC Corp",
        "address": {
          "city": "San Francisco",
          "state": "CA",
          "country": "US",
          "postal_code": "94102"
        }
      }
    }
  }
}

```

### Account Validation API - Test Card Scenarios

Test different Account Validation scenarios using real cards. Create Card IDs with the cards below and expect each card to return a predefined response (`verified`, `not_verified`, `match`, `no_matched`, `partial_match`).

### Validation Results

<table><thead><tr><th width="181.06109619140625">PAN</th><th width="114.3670654296875">Expiration</th><th width="188.730712890625">Scenario</th><th width="496.4417724609375">API Request Body</th><th width="183.347900390625">Card Verification</th><th width="191.73516845703125">Address Verification</th><th width="199.01318359375">CVC Verification</th><th width="198.634521484375">Name Verification</th></tr></thead><tbody><tr><td>4957030420210462</td><td>10/40</td><td><ul><li>Card Valid</li><li>Full Address Match</li></ul><p></p></td><td>{"data": {"type": "account-validations","attributes": {"merchant": {"merchant_name": "ABC Corp","address": {<br>"city": "San Francisco","state": "CA","country": "US","postal_code": "94102"}},"cardholder_address": {"street": "900 Metro Center Blv","postal_code": "94404","city": "San Francisco","state": "CA","country": "US"}}}</td><td>verified</td><td>match</td><td>not applicable</td><td>not applicable</td></tr><tr><td>4860371715886350</td><td>10/40</td><td><ul><li>Card Not Valid</li><li>Partial Address Match</li></ul></td><td>{"data": {<br>"type": "account-validations","attributes": {"merchant": {<br>"merchant_name": "ABC Corp",<br>"address": {"city": "San Francisco","state": "CA","country": "US","postal_code": "94102"}},"cardholder_address": {<br>"street": "900 Metro Center Blv","postal_code": "94404",<br>"city": "San Francisco","state": "CA","country": "US"}}}</td><td>not_verified</td><td>not applicable</td><td>not applicable</td><td>partial_match</td></tr><tr><td>4860515915886350</td><td>10/40</td><td><ul><li>Card Not Valid</li><li>Address No Match</li></ul></td><td>{"data": {"type": "account-validations",<br>"attributes": {"merchant": {"merchant_name": "ABC Corp","address": {"city": "San Francisco","state": "CA",<br>"country": "US","postal_code": "94102"}},"cardholder_address": {"street": "900 Metro Center Blv","postal_code": "94404","city": "San Francisco",<br>"state": "CA","country": "US"}}}}</td><td>not_verified</td><td>not applicable</td><td>not applicable</td><td>no_match</td></tr><tr><td>4860967315886359</td><td>10/40</td><td><ul><li>Card Not Valid</li><li>Address No Match</li></ul></td><td>{"data": {"type": "account-validations","attributes": {"merchant": {"merchant_name": "ABC Corp","address": {<br>"city": "San Francisco""state": "CA","country": "US","postal_code": "94102"}},"cardholder_address": {<br>"street": "900 Metro Center Blv","postal_code": "94404",<br>"city": "San Francisco","state": "CA","country": "US"}}}}</td><td>not_verified</td><td>not applicable</td><td>not applicable</td><td>no_match</td></tr></tbody></table>


# Wallet Decrypt

## **Apple Pay Wallet Decryption Testing Guide**

This guide explains how to test **Apple Pay Wallet Decryption** in a controlled environment. You can test both **DPAN** and **MPAN** wallet decryption flows and validate the resulting **Create Card** and **Get Card by ID** behavior.

Testing can be performed in two ways:

* **Mock Testing** – using static encrypted Apple Pay payloads that return predictable decrypted DPAN or MPAN card data
* **Sandbox Testing** – using encrypted Apple Pay payloads in the sandbox environment with Apple Pay Wallet Decryption enabled on the account

## **General Setup**

* **Content-Type header:** `application/vnd.api+json`
* **HTTP method:** `POST` for card creation
* **GET /cards/{id}** can be used after card creation to retrieve the stored card
* Apple Pay Wallet Decryption supports encrypted Apple Pay payloads using the **EC\_v1** format
* The encrypted payload is sent in the `encrypted_payment_data` object of the **Create Card API** request

Each successful request creates a new CMP card and returns a new `card_id`.

## **What Apple Pay Wallet Decryption Does**

When an encrypted Apple Pay payload is submitted to CMP:

* CMP performs **wallet decryption**
* CMP extracts the **DPAN** or **MPAN**
* CMP creates and stores the card in CMP
* CMP returns the created card object, including wallet metadata

For successful responses, the wallet metadata may include:

* `wallet_type`
* `token_type`
* `wallet_details.payment_data_type`
* `wallet_details.device_manufacturer_identifier`
* `wallet_details.transaction_id`
* `wallet_details.cryptogram` for DPAN
* `wallet_details.merchant_token_identifier` for MPAN

## **Mock Testing**

Use Mock Testing to verify Apple Pay Wallet Decryption behavior without requiring Apple Pay Wallet Decryption to be enabled on the CMP account.

### Mock Testing Requirements

When using mock testing:

* A **CMP account** is required
* A **JWT auth token** is required
* **Apple Pay Wallet Decryption account configuration is not required to be enabled**
* A **new card ID** is generated for each successful request
* The decrypted card content returned by the mock remains otherwise static for the same test payload

### Request Requirements

* **Base URL:** <https://sandbox.vgsapi.com>
* **Header required:** `Content-Type: application/vnd.api+json`
* Send the encrypted Apple Pay payload using the standard **Create Card API** shape

### Mock Testing – DPAN

Use the following encrypted Apple Pay payload to simulate decryption of a **DPAN** token.

```json
{
  "data": {
    "attributes": {
      "encrypted_payment_data": {
        "digital_signature": "TUlBR0NTcUdTSWIzRFFFSEFxQ0FNSUFDQVFFeERUQUxCZ2xnaGtnQlpRTUVBZ0V3Z0FZSktvWklodmNOQVFjQkFBQ2c=",
        "encrypted_payload_text": "OzF2HRdPNYZPixxpyZ3GzTxm/qXSLP65bZ+yM8I0XFjuB72B+dtRPZKjNwNV13Yy2TD+6LInN8LzvZXk9Q0WW+gms+tacfDKsdIR1vidJhsKSZF9yZ5BwyKN3Nv0J7RQsGi8hjILxVBNxnA5vdTHCMOGcy/9cwBDLyU1boTRrxd8gBbu4UWzdDy+8KhCxMpADBbTF0J9DEaa6Iz/uCLlQgv26xxvBSSdDcn1ZhsaHJN+YJlnkcyckPj1zf2F+2EfqOdEvxAWQNAGd2d5zi+tl3LVwVes1xorl7M8qC+LFqo9MNCefhmSsLT8P3RTEkrn2SoZ5qEv0uBXapQWJMnLlkBCpZF0fkTKEzC67i7wiz4qnDaBogaiY/qsaccgJ5xHk2Il2Wgt6Y2+gdk9wBqaRu0kKgEThth6mU/NCOYKoIPzJm6KWa0o3gJ9bhq/SJaVlsVrov81Ps7i03/sHmq/Sve/5uRJys0d0BUHzDrasQH35973JMpxaZ0TdiwHnHU5VWNbV2FKxh6k9e0YqmMZ//DX36h5EOa7iSinfRGQdF6IQ/8e7nazYwtX0iV8IQ4n8P/cwIn9Gn5xmeTSdfOEO1o=",
        "key_hash": "DPAN/4VEn0bzlhTscArIT3Gvbq2MKiZlHAlZc76kAUx=",
        "public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0eamXz+Xza8La9eOAIYf307qxJOVRRf9oTLlm61o0dLPvpXtPiEno2QzvzX/ucbugivotW2+gi5x/Ff8c7adfg==",
        "version": "EC_v1",
        "wallet_type": "apple_pay",
        "wallet_transaction_id": "6e21f9bf4aea3f767c5e48eeae92d8af9b8919c3ad9854fd1320b7867499c6fe",
        "payment_method": {
          "display_name": "Visa 0121",
          "network": "Visa",
          "type": "credit"
        }
      }
    }
  }
}
```

### Expected DPAN Mock Response

A successful mock DPAN request returns a card with:

* `token_type: dpan`
* `wallet_type: apple_pay`
* `payment_data_type: 3DSecure`
* `device_manufacturer_identifier`
* `cryptogram`
* `transaction_id`
* `payment_method` details if provided in the request

#### Example response

```json
{
	"data": {
		"id": "CRDKfukrUmMsUdotydKS4euZ1v2exoN617mWi7avaehqkYh2J5JP",
		"type": "cards",
		"attributes": {
			"pan": "5100260000019206",
			"exp_month": 12,
			"exp_year": 99,
			"cardholder": {
				"name": "John Q. Public",
				"company": "VGS",
				"phone": "+18881112222",
				"address": {
					"address1": "301 Test Loop",
					"city": "San Francisco",
					"region": "California",
					"postal_code": "11111",
					"country": "US"
				}
			},
			"token_type": "dpan",
			"wallet_type": "apple_pay",
			"pan_alias": "tok_sandbox_QfJDZdyBR6pygJ13xPXrkB",
			"bin": "510026",
			"first8": "51002600",
			"last4": "9206",
			"card_fingerprint": "fjLdCHgcSJmnSqzpSQafJvmuPep5vSdV5w2nJC1sWuFp",
			"created_at": "2025-08-01T00:00:00",
			"updated_at": "2025-08-01T00:00:00",
			"wallet_details": {
				"currency_code": "USD",
				"amount": 2500,
				"device_manufacturer_identifier": "040010030273",
				"payment_data_type": "3DSecure",
				"cryptogram": {
					"type": "TAVV",
					"value": "Ab2c/XwBBB/EknV76pyc2NBBCCC=",
					"eci": "7"
				},
				"payment_method": {
					"display_name": "Visa 0121",
					"network": "Visa",
					"type": "credit"
				},
				"transaction_id": "9a0650018c263c03fb34618407fb00a3026aee366b230e013605a12e5201574b"
			}
		}
	},
	"metadata": {
		"observability": {
			"trace_id": "c2a171cff919032f17515338db2527fe",
			"client_id": "ACwmzJCti-3DS_Account-dFbIj",
			"vault_id": "tntfn3pqdcf",
			"account_id": "ACT3Wjs6gwrcHxzjcro4H9G8W",
			"fingerprint": "4GqVMtYY8uohfuZ5zhrAZfs5VexAbihfrL8qyTfudEBpEgWiXCPuEAJtC91"
		}
	}
}
```

### Mock Testing – MPAN

Use the following encrypted Apple Pay payload to simulate decryption of an **MPAN** token.

```json
{
  "data": {
    "attributes": {
      "encrypted_payment_data": {
        "digital_signature": "TUlBR0NTcUdTSWIzRFFFSEFxQ0FNSUFDQVFFeERUQUxCZ2xnaGtnQlpRTUVBZ0V3Z0FZSktvWklodmNOQVFjQkFBQ2c=",
        "encrypted_payload_text": "JFk4RJoiod18IQmwcjtU88ZimrS543kxzoXw2vQjTl08ud6MV9kzf6NiSJ1Ev7HZ8IcrtzUXb69sbO/W/PcV13h+WRtYvmD7GTCSypimqcitvE78zCDRUpV6g2zsapFm2/R3jFcdDlmvP4L5/mkKU/pWx0hA/MiUe7XoGc+2jEUI7tAB8XZebV7lPlSFLBA2Q46JKsmsigkvmY3wfuYKJDg/niD6yL4LgIA0KAnh8YjU/88UjLbvi6mkII7MjJri6RiTqQ3EDGBZX84SlPus1NYVe1yMwqjG8e7Pza8kDZ6C4Wyz/5SksMpEnUxanWAfKnc37nJGkn9KiCktLwXGRLT7hEHszsvs/yu6ZUY3E8SJ9LYb2fAn3IXqJEyDXWZgRdF1tVrW0hqYrWRvUfcJ7gqRCL8/0k9nRGHhw4+r4hiVOz2hadd4T5cxjfWsfCSg4UEFv2rCZ8K7qkS1XQsZmbuqjDNnzS+vPd/Hk7xDJ+cSiySD/KcE8g==",
        "key_hash": "MPAN/3FruspO6vAy8AQ3UKiJeF14wgTUYmGAPwlbiqk=",
        "public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0mrNoedmyYa/Qfp+1GlUIa8x0Fu1tgTattp0678fEUTPEcVfqsizY/8LP/4T34wNGbvLPV8zTEICHaoFWxpeig==",
        "version": "EC_v1",
        "wallet_type": "apple_pay",
        "wallet_transaction_id": "9f0f709cc538c7207169cf9f44e668b8e3cadf73c2d84b0c1b1e2b6caf7f07a1",
        "payment_method": {
          "display_name": "Visa 0121",
          "network": "Visa",
          "type": "credit"
        }
      }
    }
  }
}
```

### Expected MPAN Mock Response

A successful mock MPAN request returns a card with:

* `token_type: mpan`
* `wallet_type: apple_pay`
* `payment_data_type: MerchantToken`
* `device_manufacturer_identifier`
* `merchant_token_identifier`
* `transaction_id`
* `payment_method` details if provided in the request

#### Example response

```json
{
	"data": {
		"id": "CRDqL55P51GVUMbZMDgYakHQTJSoFP2e8NoMXzhQpVPgLh91ZEQo",
		"type": "cards",
		"attributes": {
			"pan": "5100260000009207",
			"exp_month": 12,
			"exp_year": 99,
			"cardholder": {
				"name": "John Q. Public",
				"company": "VGS",
				"phone": "+18881112222",
				"address": {
					"address1": "301 Test Loop",
					"city": "San Francisco",
					"region": "California",
					"postal_code": "11111",
					"country": "US"
				}
			},
			"token_type": "mpan",
			"wallet_type": "apple_pay",
			"pan_alias": "tok_sandbox_oO3YeAP3eDJhPclNtEPcJI",
			"bin": "510026",
			"first8": "51002600",
			"last4": "9207",
			"card_fingerprint": "2kPZBjQpaX6PnxrbvPTYzAC2ckcVNqNTxCAkdAn3tnTn",
			"created_at": "2025-08-01T00:00:00",
			"updated_at": "2025-08-01T00:00:00",
			"wallet_details": {
				"currency_code": "USD",
				"amount": 2500,
				"device_manufacturer_identifier": "040010030273",
				"payment_data_type": "MerchantToken",
				"merchant_token_identifier": "DNITHE302308980001844",
				"payment_method": {
					"display_name": "Visa 0121",
					"network": "Visa",
					"type": "credit"
				},
				"transaction_id": "9a0650018c263c03fb34618407fb00a3026aee366b230e013605a12e5201574b"
			}
		}
	},
	"metadata": {
		"observability": {
			"trace_id": "250631059828f5a07e92f202fde52fa6",
			"client_id": "ACwmzJCti-3DS_Account-dFbIj",
			"vault_id": "tntfn3pqdcf",
			"account_id": "ACT3Wjs6gwrcHxzjcro4H9G8W",
			"fingerprint": "4GqVMtYY8uohfuZ5zhrB2MNc1fKeqyK8VaZ7AqS8oBtqrehfoHhAFsztc3Q"
		}
	}
}
```

### Mock Testing – 5xx Error&#x20;

Use the following encrypted Apple Pay payload to simulate a 5xx error response.

```json
{
  "data": {
    "attributes": {
      "encrypted_payment_data": {
        "digital_signature": "TUlBR0NTcUdTSWIzRFFFSEFxQ0FNSUFDQVFFeERUQUxCZ2xnaGtnQlpRTUVBZ0V3Z0FZSktvWklodmNOQVFjQkFBQ2c=",
        "encrypted_payload_text": "OzF2HRdPNYZPixxpyZ3GzTxm/qXSLP65bZ+yM8I0XFjuB72B+dtRPZKjNwNV13Yy2TD+6LInN8LzvZXk9Q0WW+gms+tacfDKsdIR1vidJhsKSZF9yZ5BwyKN3Nv0J7RQsGi8hjILxVBNxnA5vdTHCMOGcy/9cwBDLyU1boTRrxd8gBbu4UWzdDy+8KhCxMpADBbTF0J9DEaa6Iz/uCLlQgv26xxvBSSdDcn1ZhsaHJN+YJlnkcyckPj1zf2F+2EfqOdEvxAWQNAGd2d5zi+tl3LVwVes1xorl7M8qC+LFqo9MNCefhmSsLT8P3RTEkrn2SoZ5qEv0uBXapQWJMnLlkBCpZF0fkTKEzC67i7wiz4qnDaBogaiY/qsaccgJ5xHk2Il2Wgt6Y2+gdk9wBqaRu0kKgEThth6mU/NCOYKoIPzJm6KWa0o3gJ9bhq/SJaVlsVrov81Ps7i03/sHmq/Sve/5uRJys0d0BUHzDrasQH35973JMpxaZ0TdiwHnHU5VWNbV2FKxh6k9e0YqmMZ//DX36h5EOa7iSinfRGQdF6IQ/8e7nazYwtX0iV8IQ4n8P/cwIn9Gn5xmeTSdfOEO1o=",
        "key_hash": "DPAN/RGVjcnlwdGlvbkVycm9yVGVzdEtleUZvck1vY2=",
        "public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0eamXz+Xza8La9eOAIYf307qxJOVRRf9oTLlm61o0dLPvpXtPiEno2QzvzX/ucbugivotW2+gi5x/Ff8c7adfg==",
        "version": "EC_v1",
        "wallet_type": "apple_pay",
        "wallet_transaction_id": "6e21f9bf4aea3f767c5e48eeae92d8af9b8919c3ad9854fd1320b7867499c6fe",
        "payment_method": {
          "display_name": "Visa 0121",
          "network": "Visa",
          "type": "credit"
        }
      }
    }
  }
}
```

### Expected Error Mock Response

A failed mock request returns an error response with:

* `errors[].detail`
* `errors[].error_code`
* `meta.observability.trace_id`
* `meta.observability.client_id`
* `meta.observability.vault_id`
* `meta.observability.account_id`
* `meta.observability.fingerprint`

#### Example response

```json
{
	"errors": [
		{
			"detail": "Decryption failed due to an internal error",
			"error_code": "INTERNAL"
		}
	],
	"meta": {
		"observability": {
			"trace_id": "ff058f978b58bee834ba2b806a8b0aed",
			"client_id": "ACsPTgxhw-AutoTest5-vP8pD",
			"vault_id": "tntefvvq6tt",
			"account_id": "ACTgSbmT2R7a6pjgi4cCrTkoj",
			"fingerprint": "4GqVMtYY8uohfBxjwFF4PF4ANEYCgGFMrpWzHmgU5zvHBsjXdR78yrY3YJC"
		}
	}
}
```

### Get Card by ID After Mock Creation

You can call **GET /cards/{id}** using the `card_id` returned from either the DPAN or MPAN mock response.

This allows you to verify what wallet metadata is persisted after card creation.

**Static mock CardIDs**

The following static CardIDs can be used with the **Get Card by ID** request for mock test payloads:

* **MPAN:** `CRDifkUMiwjdcZTA6USirUsC7xoN617mWi7avaehqkYhMPAN1JP`
* **DPAN:** `CRDifkUMiwjdcZTA6USirUsC7xoN617mWi7avaehqkYhDPAN1JP`

### Important GET Behavior

Wallet transaction artifacts are not persisted and therefore are not included in GET responses. These artifacts include:

* `currency_code`
* `amount`
* `cryptogram`

For DPAN cards, the GET response will still include persisted wallet details such as:

* `device_manufacturer_identifier`
* `payment_data_type`
* `payment_method` details if provided in the request

For MPAN cards, the GET response will still include persisted wallet details such as:

* `device_manufacturer_identifier`
* `payment_data_type`
* `merchant_token_identifier`
* `payment_method` details if provided in the request

#### Example GET Response – DPAN

```json
{
  "data": {
    "id": "CRDoEYk47qUtndEHR9w8kGKra",
    "type": "cards",
    "attributes": {
      "pan": "4111111111111444",
      "cvc_status": "not-set",
      "exp_month": 8,
      "exp_year": 28,
      "cardholder": {},
      "token_type": "dpan",
      "wallet_type": "apple_pay",
      "pan_alias": "tok_sandbox_kAYsfM1wyRwbJEesrnqFFi",
      "bin": "411111",
      "first8": "41111111",
      "last4": "1444",
      "card_fingerprint": "Qg3rYRJd4gjHYefhxpwfS2XkUovBwF2uVNhUPXgCj2H",
      "created_at": "2026-03-11T01:47:32.601715",
      "updated_at": "2026-03-11T01:47:32.601716",
      "wallet_details": {
        "device_manufacturer_identifier": "040010030400",
        "payment_data_type": "3DSecure",
        "payment_method": {
          "display_name": "Visa 0121",
          "network": "Visa",
          "type": "credit"
        }
      }
    }
  },
  "metadata": {
    "observability": {
      "trace_id": "707a927ca06a9db1d6ac0cc6705cdf11",
      "client_id": "AChkBQQGH-3DS-scope-61fC0",
      "vault_id": "tntiugemxfd",
      "account_id": "ACT9eeBkBsxXe9wWJkQdpG2kC",
      "fingerprint": "4GqVMtYY8uohftF2NdrQjH4TApUbjScwsB5oXACgvq8ATZkzALLtZSGYwo5"
    }
  }
}
```

#### Example GET Response – MPAN

```json
{
  "data": {
    "id": "CRDm3dzAeDCnfkwfqTEufFtz6",
    "type": "cards",
    "attributes": {
      "pan": "4111111111111222",
      "cvc_status": "not-set",
      "exp_month": 11,
      "exp_year": 27,
      "cardholder": {},
      "token_type": "mpan",
      "wallet_type": "apple_pay",
      "pan_alias": "tok_sandbox_kQy6qwjCP2NGGExD81dRpa",
      "bin": "411111",
      "first8": "41111111",
      "last4": "1222",
      "card_fingerprint": "b3p67ZCV6FcVnx9WtyKH2EQtfeax7yyq9cdvSm7k7rRX",
      "created_at": "2026-03-11T01:52:11.803918",
      "updated_at": "2026-03-11T01:52:11.803919",
      "wallet_details": {
        "device_manufacturer_identifier": "040010030299",
        "payment_data_type": "MerchantToken",
        "merchant_token_identifier": "DNITHE302308980001846",
        "payment_method": {
          "display_name": "Visa 0121",
          "network": "Visa",
          "type": "credit"
        }
      }
    }
  },
  "metadata": {
    "observability": {
      "trace_id": "d88aa1542357f9ae5be8b3f53df79762",
      "client_id": "AChkBQQGH-3DS-scope-61fC0",
      "vault_id": "tntiugemxfd",
      "account_id": "ACT9eeBkBsxXe9wWJkQdpG2kC",
      "fingerprint": "4GqVMtYY8uohftF2NdrQjFSG6JsmX1gTaVFegV9uF4zsdjEdKCP7CUyc1tA"
    }
  }
}
```

## Sandbox Testing

### Test Apple Pay decryption in sandbox

Before running sandbox tests, make sure Apple Pay Wallet Decryption is enabled for your CMP account and that your Apple Pay setup is complete, including the required certificate configuration and upload of the signed certificates in VGS. For setup instructions, see [Setting Up Your Apple Certificates](https://docs.verygoodsecurity.com/cmp/payment-credentials/apple-pay#setting-up-your-apple-certificates). VGS uses the configured Apple Pay payment processing certificate to decrypt Apple Pay payment tokens.

Before testing, make sure your Apple Pay setup includes all required Apple-side prerequisites. This includes:

* an Apple Developer account with Apple Pay enabled
* a Merchant Identifier created in Apple Developer
* a Payment Processing Certificate generated for that Merchant Identifier and uploaded to VGS
* if testing Apple Pay on the web, a Merchant Identity Certificate generated and configured on your side for merchant validation
* if testing Apple Pay on the web, a verified domain registered with Apple so the Apple Pay button and merchant validation flow can work correctly

For **Apple Pay on the web**, your integration must also be fully configured to support merchant validation and domain verification. For **app-based integrations**, make sure your Apple Pay entitlement and sandbox test setup are complete.

**The Payment Processing Certificate is required for VGS to decrypt the Apple Pay token.** The Merchant Identity Certificate is not used by VGS for decryption itself, but it is still required for Apple Pay on the web because Apple uses it during merchant validation.

To test Apple Pay decryption, generate an encrypted Apple Pay payload by completing a **real Apple Pay test transaction** in Apple’s sandbox environment. Apple Pay returns the encrypted payment token as part of the payment authorization response, and that token can be sent to VGS for decryption testing. Apple’s sandbox supports testing Apple Pay transactions with sandbox accounts and test cards. ([Apple Developer](https://developer.apple.com/apple-pay/sandbox-testing)).

#### Steps

1. **Set up Apple Pay for your app or website**\
   Make sure your Apple Pay integration is configured in your Apple Developer account. Apple’s implementation guide is here. ([Apple Developer](https://developer.apple.com/apple-pay/implementation)). This setup should include the Merchant Identifier you plan to use for testing. If you are testing Apple Pay on the web, your domain must also be registered and verified with Apple, and your merchant validation flow must be configured using your Merchant Identity Certificate.
2. **Create a Sandbox Apple Account**\
   In App Store Connect, create a sandbox tester account to use for Apple Pay sandbox transactions. ([Apple Developer](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/create-a-sandbox-apple-account))
3. **Add a sandbox test card to Wallet**\
   Sign in to your test device with the sandbox account and add one of Apple’s sandbox test cards to Wallet. Apple’s sandbox testing guide covers this setup. ([Apple Developer](https://developer.apple.com/apple-pay/sandbox-testing/))
4. **Run a test Apple Pay checkout**\
   Start an Apple Pay payment from your app or Safari website on a supported Apple device and complete the authorization using the sandbox card. Apple Pay will return an encrypted payment token in the authorization response. ([Apple Developer](https://developer.apple.com/apple-pay/sandbox-testing/)).&#x20;
   1. For Apple Pay on the web, this step assumes your verified domain, Apple Pay button setup, and merchant validation flow are already working. Without that setup, you may not be able to generate the encrypted Apple Pay payload needed for VGS decryption testing.
5. **Send the encrypted payload to VGS**\
   Use the encrypted Apple Pay token returned by Apple Pay as the Create Card API payload for VGS decryption testing.

VGS will use the Payment Processing Certificate configured for the associated Merchant Identifier to decrypt the payload.

Apple Pay sandbox requires a real card in Apple Wallet.&#x20;

#### Important Sandbox Testing Notes

* Apple Pay sandbox testing requires a **sandbox tester account** and an **Apple Pay sandbox test card** added to Wallet.
* For **web integrations**, Apple Pay sandbox testing also requires successful **domain verification** and **merchant validation**.
* This guide focuses on testing VGS decryption with a real Apple Pay sandbox token. **Customers building the full Apple Pay flow from scratch will also need to complete the surrounding Apple Pay integration, including:**
  * merchant validation for web integrations
  * domain verification for Apple Pay on the web
  * Apple Pay session setup in the app or website
  * extraction of the encrypted Apple Pay token from the payment authorization response
  * mapping the Apple Pay token fields into the VGS Create Card request
  * any required hosted test environment needed for Apple Pay validation flows
* **This guide assumes your Apple Pay integration is already set up and functioning in Apple’s sandbox environment.**

## What to Validate During Testing

For both Mock testing, validate the following:

### DPAN Validation

Confirm that the response includes:

* `token_type: dpan`
* `wallet_type: apple_pay`
* `wallet_details.payment_data_type: 3DSecure`
* `wallet_details.device_manufacturer_identifier`
* `wallet_details.transaction_id`
* `wallet_details.cryptogram`
* `wallet_details.payment_method` if it was provided in the request

### MPAN Validation

Confirm that the response includes:

* `token_type: mpan`
* `wallet_type: apple_pay`
* `wallet_details.payment_data_type: MerchantToken`
* `wallet_details.device_manufacturer_identifier`
* `wallet_details.transaction_id`
* `wallet_details.merchant_token_identifier`
* `wallet_details.payment_method` if it was provided in the request

### GET Validation

After card creation, call **GET /cards/{id}** and confirm that:

* the card is retrievable
* persisted wallet metadata is returned
* `currency_code` is not returned
* `amount` is not returned
* `cryptogram` is not returned

## Troubleshooting: "You don't have enough permissions to the requested resource"

If you receive the error: `You don't have enough permissions to the requested resource`  when generating a certificate or CSR using the VGS CLI, verify the following:

1. **User Permissions**
   * The user account used to log in to the VGS CLI must have **Admin** access to the target vault.
   * Users with only **Read** or **Write** permissions may receive this error when attempting to generate certificates or CSRs.
2. **Command Formatting**
   * Incorrect spacing or formatting in multi-line CLI commands can sometimes result in this error.
   * If you encounter issues, try running the command as a **single-line command** instead.
3. **Vault ID Validation**
   * Ensure the Vault ID specified in the command is correct.
   * Using an incorrect Vault ID can also result in the same permissions error, even if the user has the required access to other vaults.

If the issue persists after validating the above items, please contact VGS Support and include the command used, the Vault ID, and the user account details for further investigation.

## Important Notes

* Apple Pay Wallet Decryption mock testing does **not** require Wallet Decryption to be enabled on the account
* Apple Pay Wallet Decryption sandbox testing **does** require Wallet Decryption to be enabled on the account
* A new `card_id` is generated for each successful request
* `payment_method` is returned in the response only if it is provided in the request
* Wallet transaction artifacts are not persisted and therefore are not included in GET responses


# Product Overview

The VGS Secure Data Suite provides a unified framework for collecting, storing, and exchanging sensitive information safely across your applications and infrastructure.

At its core, the VGS Vault securely holds sensitive data and replaces it with VGS Aliases. Aliases are non-sensitive representations that preserve format and functionality while eliminating storage risk to the organization. Data can be transmitted securely through multiple ingress and egress channels and protocols, including the [**HTTPS Proxies**](/vault/http-proxy), [**Batch File Transmission Tools**,](/vault/batch-file-transmission) and the [**TCP Proxy**](/vault/iso-proxy). The platform also allows organizations to perform complex modifications and cryptographic operations to sensitive data in transit using [**VGS Compute**](/vault/developer-tools/larky)**.**&#x20;

Together, these tools enable an organization to operate on sensitive data such as payment credentials, social security numbers, passport numbers, passwords, and any other information that the organization deems sensitive.


# Vault Dashboard

The [Vault Dashboard](https://dashboard.verygoodsecurity.com) is a front-end experience available to existing and prospective VGS customers. The Vault Dashboard enables users to manage data connections, notifications, and vault configuration settings, create Sandbox vaults, promote Sandbox vaults to Live vaults, view vault metrics, and more.

#### Key Services of the Vault Dashboard <a href="#key-services-within-cmp" id="key-services-within-cmp"></a>

* View Vault metrics and time-based reports

<figure><img src="/files/QMzjLsVJl0H8QpOVu4SM" alt=""><figcaption></figcaption></figure>

* Manage HTTP and SFTP Routes
* Build Forms for Front-end Implementation using [VGS Collect](/vault/developer-tools/vgs-collect)
* Review Proxy and Audit Logs
* Leverage templates for common [Routes](/vault/http-proxy/inbound-connection) and other data connections
* Manage [Service Accounts](/cmp/platform/authentication#id-1-generate-service-account), [Access Credentials](/cmp/platform/authentication#id-3-generate-access-credentials), [mTLS Certificates](/vault/http-proxy/mutual-tls-certificates), and [Webhook Notifications](/cmp/developer-resources/notifications)
* Manage Organization settings and User Access Controls

<figure><img src="/files/COTvLz8swkvGxdncji0y" alt=""><figcaption></figcaption></figure>

* Access enterprise platform capabilities, such as [SAML SSO](/enterprise-platform/access-management/enterprise-identity-providers/saml-2.0-configuration)

{% hint style="info" %}
Note: the Vault Dashboard is a companion experience to the [CMP Dashboard](/cmp/platform/overview/cmp-dashboard).&#x20;

As of 2025, some capabilities CMP users require to utilize the full breath of CMP services are housed in the CMP Dashboard experience. Please note that some CMP activities will require navigation across dashboards until all capabilities are consolidated into a single experience.
{% endhint %}


# VGS Vault

The VGS Vault is a customer-configurable, PCI-compliant storage zone where organizations can securely collect, store, and exchange sensitive data such as payment credentials, personal information, or any other confidential records.

Each data element stored in a Vault is replaced with a VGS Alias, a unique token that represents the original value but carries no inherent value to bad actors.

This aliasing process ensures that your systems, logs, and databases only ever handle non-sensitive representations, while VGS retains the responsibility for safeguarding the real data in a secure and compliant environment.

Vaults can be accessed and integrated through the VGS Secure Data suite of tools, including the [HTTPS Proxies](/vault/http-proxy), [Batch File Transmission Mechanisms](/vault/batch-file-transmission), and [TCP Proxy](/vault/iso-proxy). Vaults can also be accessed securely using the [VGS Vault API](/vault/developer-tools/apis/vault-api).

This flexibility enables secure data exchange across applications, services, and external partners, while preserving end-to-end data privacy and governance.

## Managing Vaults

Organizations can operate multiple VGS Vaults to support different business units, environments, and compliance boundaries. Each Vault is isolated and independently configurable, allowing teams to separate data flows according to security, regulatory, or operational needs.

#### **Identifiers**

Each Vault has a unique identifier, called the **Tenant ID** (also referred to as the Vault ID). The Tenant ID is an alphanumeric string denoted by a prefix *tnt.*&#x20;

The Tenant ID is the primary identifier that connects your Organization and users to VGS products and services.&#x20;

### **Sandbox vs. Live Vaults**

VGS provides two environment categories to support the full software development lifecycle:

#### **Sandbox Vaults**

Sandbox Vaults are designed for development, testing, and automation.  They simulate live data flows without exposing real customer data, allowing developers to safely experiment with integrations, proxy routes, and API configurations. Sandbox Vaults support end-to-end automation, including CI/CD pipelines, QA environments, and contract testing, helping teams validate data flows before promoting to production.

#### **Live Vaults**

Live Vaults handle production traffic and real sensitive data. These Vaults are hosted in VGS’s fully compliant production infrastructure, ensuring adherence to PCI DSS, SOC 2, and other regulatory standards.

Live Vaults are used when applications need to tokenize, store, or exchange real data with downstream partners, such as payment processors, banks, or identity providers.

Together, Sandbox and Live Vaults create a safe progression path for building, testing, and deploying secure data operations.

Organizations can freely migrate configurations and routes between Vaults using the VGS Dashboard or CLI, maintaining consistent policies while isolating environments for compliance and control.

## How to Create a Vault

<figure><img src="/files/UaneSBIikZ6kpCQikIOM" alt=""><figcaption></figcaption></figure>

Vaults are managed via the VGS Dashboard or VGS CLI. There is no limit to the number of Vaults you can create.

When naming a Vault, Vault names may contain only letters (A–Z, a–z), digits (0–9), spaces, and the separators (-, \_, .). Leading or trailing whitespace and consecutive separators are not allowed.

## How Do I Control Access to Vaults

Users can be provisioned to a Vault with a `read`, `write` or `admin` role. Each role provides a different level of access. To implement strong SDLC, customers will typically provide engineers with `write` permissions to Sandbox Vaults and then use a service account to manage promoting the configuration of a Sandbox vault to their Live vault via an automated system.

## Where Are Vaults Located?

VGS supports multiple global deployment regions, allowing customers to meet data residency requirements and minimize latency across geographies.

Regional Vault options enable you to store and process data within your preferred jurisdiction, ensuring minimal network travel time as well as alignment with privacy regulations like GDPR and other local data protection frameworks.

VGS currently supports deployments in North America, Europe, and Asia Pacific. More details on regional deployments and availability zones can be found [here](/vault/vaults).


# Aliases

In VGS, an Alias is the reference identifier that stands in for the true sensitive data value. Under the hood, aliases map back to records stored securely in your Vault. This allows VGS to store the original values and VGS customers to only need to store the Aliases to the original data.

Aliases can be exchanged with the original data as needed, either in transit to third-party APIs or via a "fetch" using the VGS Vault API. This method of data tokenization is what enables VGS to remove sensitive data from our customers' environments while still preserving utility in downstream processing.

## Retention Policies

Aliases within your VGS Vault are created in either [persistent or volatile storage](/vault/storage). Aliases stored in Persistent storage do not have an expiration date and therefore can be used to exchange with the original data until the alias is manually deleted by the VGS customer. Aliases stored in volatile storage have a pre-configured expiration date and will therefore become unusable after the allotted time period.

This segregation allows granular control over data retention policies, which is often required for compliant storage of any sensitive data. This includes providing full PCI level 1 compliance when storing data that is classified as Sensitive Authentication Data (SAD) according to the PCI standards.

Card Verification Codes (CVC, CVV2), PINs and PIN Blocks, and Full Track Data are examples of values typically stored in volatile storage to comply with PCI DSS standards.

## Classification and Tagging

Data classification is the process of organizing data into categories that make it is easy to retrieve, sort and store for future use. A well-planned data classification system makes essential data easy to find and retrieve. This can be of particular importance for risk management, legal discovery and compliance.

Through the use of the [VGS Tokenization API](/vault/developer-tools/apis/vault-api-v1/resource-limits) and [VGS Routes](/vault/http-proxy) you can classify and tag data using either static or dynamic tagging policies.

Routes allow restricting certain classes of data to specific destinations allowing fine grained control over where data within your VGS Vault is routed enabling simple, policy based control of your sensitive data flows from a single centralized location.

## Alias Formats

Formats come in several varieties to choose from based on your use case.

| Format                            | Description                                                                                                                                                                                                                                                                                                                                                                                             |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UUID`                            | Represents any piece of data. Format returns a surrogate value like\`tok\_sandbox\_xxxxxxxxxxxxxxxxxxxxxxxxx\`. You can match this format using the regex: `(vgs\|tok)_[A-Za-z0-9-]+_[a-zA-Z0-9\-]{4,32}`                                                                                                                                                                                               |
| `NUM_LENGTH_PRESERVING`           | Can be used for any number that needs to have it's length maintained for form validation or other reasons where the length returned matters. This does not support numbers less than 3.                                                                                                                                                                                                                 |
| `FPE_SIX_T_FOUR`                  | To be used for Payment cards when you need them to still go through a validation check and capture the BIN (Bank Identification Number) and the last four digits. Example \`4111111111111111\` becomes something like \`4111119381251111\`.                                                                                                                                                             |
| `FPE_T_FOUR`                      | To be used for Payment cards where you do not need a BIN but it is still Luhn Valid to pass validation checks on your system. \`5555555555554444\` would become something like \`9399630812244444\`.                                                                                                                                                                                                    |
| `PFPT`                            | This format makes it easy to distinguish between real sensitive data and the surrogate values. For example \`4012888888881881\` turns into \`9914040119524511881\` The prefix here is \`99\` with \`1\` reserved for versioning of this format. The 4th and 5th digits represent the first two digits of the original PAN and the last four digits represent the last four from the original PAN.       |
| `NON_LUHN_FPE_ALPHANUMERIC`       | This format generates format preserving card number which \*\*does not pass the \[Luhn validation]\(<https://en.wikipedia.org/wiki/Luhn\\_algorithm)\\*\\>\*. This format is useful to make sure that surrogate data can be identified algorithmically. Example: \`7858402423279985\`.                                                                                                                  |
| `FPE_SSN_T_FOUR`                  | Can be used for social security number (SSN). Possible to use ssn with dashes or without. For example \`567-34-5672\` would have alias like \`123-945-5672\`, last four digits are the same.                                                                                                                                                                                                            |
| `FPE_ACC_NUM_T_FOUR`              | Could be used for numeric account number. The length of the value could be in range from 7 to 17. It keep last four digits of the value untouched.                                                                                                                                                                                                                                                      |
| `FPE_ALPHANUMERIC_ACC_NUM_T_FOUR` | Generates an alphanumeric account number string with a length of 7 to 17 characters. It keep last four characters untouched from the value.                                                                                                                                                                                                                                                             |
| `GENERIC_T_FOUR`                  | Can be used for any type of data. This will generate an alias with the last four characters of the original value after the alias - \`tok\_sandbox\_xxxxxxxxxxxxxxxxxxxxxxxxx\_:last\_four\`, where the x’s are alphanumeric characters. The length of the value must be greater or equal to 7.                                                                                                         |
| `RAW_UUID`                        | Can be used for any type of data. This will generate an Alias with a UUID format. Example: \`76b8a972-f0a7-4e87-a07f-a51c92314d56\`.                                                                                                                                                                                                                                                                    |
| `ALPHANUMERIC_SIX_T_FOUR`         | This format generates alias that is the combination of BIN, alphanumeric part and last 4 digits. Example of a generated alias: \`785840aLpH4nUmV9985\`. Last character of alphanumeric part tells if original value was Luhn valid. \`V\` or \`N\` means that is was Luhn valid/not valid. An alias in this format will be created \_only\_ if the value is numeric and length is more than 13 symbols. |
| `VGS_FIXED_LEN_GENERIC`           | <p>This format generates an alias that has a fixed length of 29 digits regardless of input. All aliases generated will have the first 3 characters as `vgs`. The 4th - 6th character will be the environment (ex: `sbx`, `l01`). Example of a generated alias: `vgsl0100VwAc1nxucgPiPAhUcZ3AF`<br><br>l01 - Live US<br>le1 or l01 - Live EU<br>la1 - Live AP<br>sbx - Sandbox</p>                       |

> Length or format preserving will generate a `RAW_UUID` if you provide an invalid value or if you exceed the possible unique combinations of available aliases for the next formats:\
> 1\. *Generic - Numeric Length Preserving*\
> 2\. *Payment Card - Format Preserving, Luhn Valid (T4)*\
> 3\. *Payment Card - Prefixed, Luhn Valid, 19 Digits Fixed Length*\
> 4\. *SSN - Format Preserving (A4)*\
> 5\. *Account Number - Numeric Length Preserving (A4)*\
> 6\. *Account Number - Alphanumeric Length Preserving (A4)*\
> \
> Length or format preserving will generate a `UUID` if you provide an invalid value or if you exceed the possible unique combinations of available aliases for the next formats:\
> 1\. *Generic - VGS Alias last 4*\
> 2\. *Payment Card - Format Preserving, Luhn Valid (6T4)*\
> 3\. *Numeric - Include Alphanumeric, 19 symbols length (6T4)*\\

## Fingerprinting

When the fingerprinting feature is enabled, it ensures that every time a specific value is redacted, the same token alias is returned. This helps to minimize token duplication, which occurs when multiple aliases refer to the same value.

For example, if you redact the string `4111111111111111` twice with the fingerprinting feature enabled, both times you will get the same alias, `tok_live_5TsdDFxbATPKOTJFvRSHGn`.

However, if the fingerprinting feature is disabled, redacting `4111111111111111` twice will yield two different aliases. The first redaction might return `tok_live_5TsdDFxbATPKOTJFvRSHGn`, while the second redaction might return `tok_live_4PdsSGsfZKQLROLDcETGEf`.

It’s important to note that this feature only applies to new redactions. If a value was stored while the feature was off, it will continue to be retrievable (via reveal) with the previous aliases assigned to it. To ensure consistent behavior, you would need to delete the previous aliases.

## Record usage and failed reveals

When revealing aliases, error might occur that indicates that the reveal of data failed. VGS gives a possibility to track success record usage, as well as failed record usage via Observability ([Prometheus](/enterprise-platform/core-platform/observability/accessing-vgs-metrics-via-prometheus-api) integration).

Failed reveals [(record\_usage\_failure metric)](/enterprise-platform/core-platform/observability/metrics-templates#failed-reveals-tracking) might occur due to the following errors:

* **NOT\_FOUND** - Exception raised if searching for an object and it’s not found.
* **ACCESS\_DENIED** - Exception raised if searching for an object and it’s found but access is denied based on request classifiers and tags on a token.
* **TOKENIZATION\_FAILED** - Exception raised if there are issues during tokenization or detokenization of a value.


# Persistent And Volatile Storage

VGS supports two different types of storage, Persistent and Volatile. Persistent storage allows you to store your data with VGS on a permanent basis, such as credit card numbers, account numbers, and Personally Identifiable Information. When card or account numbers are stored in conjunction with names, service codes, and expiration dates, they are considered Cardholder Data. PCI DSS requires Cardholder Data to be protected when stored with card or account numbers, and may be stored in Persistent Storage.

There is a second category of data called Sensitive Authentication Data, which includes:

* Full Card Magstripe Data
* Full Card Chip Data
* Card Verification Codes
* PIN Numbers

<figure><img src="/files/CNPDX8ixmCeomQm6HsYU" alt=""><figcaption></figcaption></figure>

To be PCI compliant, Sensitive Authentication Data cannot be stored in persistent storage, even if it is encrypted. Sensitive Authentication Data must be stored in **volatile storage**, and it must be deleted after the authorization for which it was collected is completed.

To remain compliant, VGS stores Sensitive Authentication Data in Volatile Storage for a predetermined amount of time. The default holding period for volatile storage is 1 hour, although this can be reconfigured with some constraints.

Volatile Storage must be selected on both the Inbound and Outbound routes.

<figure><img src="/files/LxbMG2SJyCsnJjiojIGK" alt=""><figcaption></figcaption></figure>

You will not be able to reveal data that was redacted in Volatile Storage on your Inbound Route if your Outbound Route is set to reveal that field, but has Persistent Storage selected. In the event that you attempt to reveal data that was held in volatile storage that is no longer available, the VGS Alias passed to the request is returned in the corresponding field instead, as there is no unredacted data to reveal.


# Regional Deployments

## Environments

* **Sandbox** is designed for experimentation and development. This environment should not be used for handling sensitive or important data.
* **Live** is intended for use in production. Vaults handling sensitive data should be deployed here. Located in US.
* **Live-EU-1** is intended for use in production. Vaults handling sensitive data should be deployed here. Located in Europe.
* **Live-AP-1** is intended for use in production. Vaults handling sensitive data should be deployed here. Located in Asia-Pacific.

## Breakdown of Environments

| Environment | Purpose               | PCI Level 1 Environment | SLA / Uptime Guarantee | Traffic Introspection | Location     | Price                  |
| ----------- | --------------------- | ----------------------- | ---------------------- | --------------------- | ------------ | ---------------------- |
| Sandbox     | Testing and Debugging | No                      | No                     | Yes                   | US           | Free                   |
| Live        | Production Data       | Yes                     | Yes                    | No                    | US           | Scalable Pricing Plans |
| Live-EU-1   | Production Data       | Yes                     | Yes                    | No                    | Europe       | Scalable Pricing Plans |
| Live-AP-1   | Production Data       | Yes                     | Yes                    | No                    | Asia-Pacific | Scalable Pricing Plans |


# Vault Security

Within the VGS Vault, your company’s sensitive data is located in a logically segregated, exclusive “customer vault”, that belongs only to you. Your data is always protected with multiple layers of security, but you may configure your own unique account-based access rules. There is no direct access from the Internet to your vault.

Inside the VGS Vault, data is encrypted at rest with the Advanced Encryption Standard, adopted by the US Government in 2001 and now used worldwide. VGS uses AES-256-GCM, the longest and most robust AES key size. Your data is further protected with the latest Authenticated Encryption with Associated Data (AEAD) mode symmetric ciphers.

VGS key management is state-of-the-art. We use dedicated hardware security modules (HSM) for key storage. Encryption and decryption keys are kept in highly-secure, separate envelopes that are segmented from your vaulted data. Keys are rotated on a regular basis. Key access requires multiple layers of authentication. Role-based access controls ensure that only the VGS Vault application processes can touch the encrypt and decrypt operations. Data thieves and hackers cannot make use of any stolen information without the keys.

Clients have two choices for data aliasing: multiple token formats as defined by ANSI X9.119-2-2017 (Tokenization), in which your sensitive data is replaced with a data token; and NIST SP800-38G (Format Preserving Encryption), in which the output preserves the format of your original data.

The VGS Vault is continuously hardened against infrastructure, system level, and configuration vulnerabilities and exposures. It is shielded against viruses and other forms of malware. We regularly test our systems, and always apply the latest applicable security patches and secure configurations to all operating systems, containers, applications, and infrastructure, to minimize exposure to vulnerabilities.

The VGS platform is continuously scanned using best-of-breed security experts and tools, including HackerOne. We undergo regular application and network vulnerability assessments, including architecture reviews, performed by independent Managed Security Services Providers (MSSP). VGS conducts annual internal/external penetration tests and bi-annual segmentation tests. All vulnerabilities discovered are documented and immediately remediated, including post-mortem analyses to identify root causes and implement future controls.

VGS employs 24/7 threat monitoring, intrusion detection, anomaly analysis, threat analytics, end-to-end event correlation, audit logging, change management controls, and traceability. VGS monitors, tests, and reviews all employees, customers, vendors, and operations, and we investigate all suspicious behavior and unauthorized activities.

The VGS incident response program includes clearly documented escalation and notification procedures. All incidents and vulnerabilities are immediately escalated to our security team, evaluated, risk ranked, and assigned for resolution by trained VGS personnel. Remediation takes place with minimal customer impact and interaction. We provide detailed customer post-mortems for all major incidents within 3 business days.


# HTTPS Proxies

VGS HTTPS Proxy sits in front of your backend and filters sensitive data out of incoming requests. By configuring the filtering rules (aka [routes](/vault/http-proxy/inbound-connection#what-does-it-allow-you-to-do)) via the VGS Dashboard, you ensure that sensitive data never hits your systems. Instead of storing the sensitive data, you store VGS-provided [aliases](https://www.verygoodsecurity.com/blog/posts/tokenization-vs-encryption-vs-aliasing-how-to-truly-minimize-compliance/).

When the time comes to use the data — for example to charge a credit card via a payment processor — the data is again passed through the VGS HTTPS Proxy on its way to a payment gateway or other 3rd party, and VGS substitutes the aliased data in transit with the original value.

![http-proxy](/files/sDZHwmLDcwNK1I3GlIEg)

## Configuring the HTTPS Proxy

VGS HTTPS Proxy processes big variety of data types and 3rd party processors, check [Operations Examples](/vault/http-proxy/operations#operations-examples) for detailed examples.

To make sure your sensitive data is fully secured use one of [VGS Collect](/vault/developer-tools/vgs-collect) solutions for web and mobile apps.

Essential steps to integrate with VGS HTTPS Proxy are described in our [Getting Started Guide](/vault/developer-tools/vgs-collect/js/index).

## Inbound and Outbound Routes Definition

The difference between the inbound and outbound routes is that Inbound Routes utilize a reverse proxy, and can therefore be accessed by third parties (such as a website or app), and the Outbound Routes utilize an HTTPS forward proxy, which sits between your server and third parties. Both tools can be used in conjunction for accepting and sending requests using a secure data infrastructure.

### Integration Examples

See [Integration Templates](/vault/http-proxy/integration-templates) and [Example Integrations](/vault/example-integrations).


# Inbound Routes

Inbound Routes are designed for receiving requests into your environment. Requests will be routed through an Inbound Route a vault-specific reverse proxy URL.

## What does it allow you to do?

* Rewrite requests or responses on the fly before data enters or leaves your system.
* Operate on data outside of the scope of your backend systems.
* Set/Change/Strip Headers.
* Modify the payload even if it's not a strict redaction/replacement.

## How does it work?

* You point your client API or Frontend to our reverse proxy and set the upstream in our [dashboard](https://dashboard.verygoodsecurity.com/) to your server DNS.

**Example:**

* BEFORE: client.foo.com → server.foo.com\\
* AFTER: client.foo.com → \<VAULT\_ID>.sandbox.verygoodproxy.com → server.foo.com
  * NOTE: The intended value for \<VAULT\_ID> is your **Tenant ID** (also referred to as Vault ID), beginning with prefix *tnt*.
* ALTERNATIVELY: you can load your client website/app *through* the proxy. This is useful if your client and backend do not communicate via API. We can provide a CNAME to whitelabel this when you're ready to use it for production.

The inbound/reverse proxy directs traffic between the client-side (inbound) traffic, the VGS vault (where sensitive data is stored), and your backend systems, as illustrated by the image below.&#x20;

<figure><img src="/files/3yVZMXERhWaadDCSzAGJ" alt=""><figcaption></figcaption></figure>

## Try it out

Run this sample code snippet in your terminal to see an example of data redaction. Please note, this is a sample test vault.

{% tabs %}
{% tab title="Curl" %}

```bash
curl https://tntsfeqzp4a.sandbox.verygoodproxy.com/post \
  -H "Content-type: application/json" \
  -d '{"account_number": "ACC00000000000000000"}'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

response = requests.post("https://tntsfeqzp4a.sandbox.verygoodproxy.com/post",
                          json={'account_number': 'ACC00000000000000000'})
print(str(response.text))
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
  "bytes"
  "encoding/json"
  "io/ioutil"
  "fmt"
  "net/http"
)

type Payload struct {
  Account string `json:"account_number"`
}

func main() {
  data := Payload{
    Account: "ACC00000000000000000",
  }
  payloadBytes, err := json.Marshal(data)
  if err != nil {
    fmt.Println(err)
  }

  body := bytes.NewReader(payloadBytes)

  req, err := http.NewRequest("POST", "https://tntsfeqzp4a.sandbox.verygoodproxy.com/post", body)
  if err != nil {
    fmt.Println(err)
  }
  req.Header.Set("Content-Type", "application/json")

  resp, err := http.DefaultClient.Do(req)
  if err != nil {
    fmt.Println(err)
  }

  defer resp.Body.Close()

  respB, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    fmt.Println(err)
  }
  fmt.Println(string(respB))
}
```

{% endtab %}

{% tab title="Java" %}

```java
package com.verygoodsecurity;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class InboundIntegration {
  public static void main(String[] args) throws IOException, InterruptedException {
    final HttpClient client = HttpClient.newBuilder().build();
    final HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://tntsfeqzp4a.sandbox.verygoodproxy.com/post"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString("{"account_number":"ACC00000000000000000"}"))
        .build();
    final HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

    System.out.println("response=" + response.body());
  }
}
```

{% endtab %}

{% tab title="Node.js" %}

```js
const axios = require('axios');

const instance = axios.create({
  baseURL: 'https://tntsfeqzp4a.sandbox.verygoodproxy.com',
  headers: {
      'Content-Type': 'application/json',
  },
});

async function getData() {
  let result;

  try {
    const response = await instance.post('/post', {
        account_number: 'ACC00000000000000000',
    });
    console.log('Response data:', response.data);
    return response.data;
  } catch (error) {
    console.error('Error caught during request:', error.message);
    throw error;
}
}

getData().then(response => console.log('Post request via proxy succeeded.'));
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'uri'
require 'json'
require 'net/https'

uri = URI.parse('https://tntsfeqzp4a.sandbox.verygoodproxy.com/post')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
request.body = {account_number: 'ACC00000000000000000'}.to_json
response = http.request(request)
puts "Response #{response.code} #{response.message}: #{response.body}"
```

{% endtab %}
{% endtabs %}

### Example with a html form submit

Let's take the easiest use case, an HTML form posting credit card data. You can serve your content via the proxy `https://<VAULT_ID>.SANDBOX.verygoodproxy.com` and this form will work with a sample echo server filter.

```html
<form class="form-horizontal2 boxed" method="post" action="/post">
    <!--CREDIT CARD PAYMENT-->
    <div class="panel panel-info">
        <div class="form-group">
            <div class="col-md-12">
                <label for="pan_number" id="pan_number_label">Credit Card Number</label>
                <input class="form-control" placeholder="Card Number" type="text" name="cc_number" id="pan_number" value="">
            </div>
        </div>
        <div class="form-group">
            <label for="pan_exp" id="pan_exp_label">CC Expiration</label>
            <input class="form-control" placeholder="Card Expiration" type="text" name="cc_exp" id="pan_exp">
        </div>
    </div>
    <div class="form-group">
        <label for="pan_cvv" id="pan_cvv_label">CC CVV</label>
        <input class="form-control" placeholder="CVV" type="text" name="cc_cvv" id="pan_cvv" value="">
    </div>
    <div class="form-group">
        <span>Pay securely using your credit card</span>
    </div>
    <button type="submit">Place Order</button>
</form>
```

In this example form, on any press of the submit button, we post to the path in the action attribute in the form tag:

Once you have this set-up you can work on your [transformers and filters](/vault/http-proxy/operations).

### Encrypted Communication

VGS supports encryption to protect communications between VGS and your web application. VGS supports the TLS cryptographic protocol. Support for anything less than TLS1.2 is officially deprecated.

For more information regarding TLS:

* [Upgrading your application](https://support.cloudways.com/en/articles/5121355-how-to-update-the-tls-version)
* [PCI Standards Blog: TLS1.2](https://blog.pcisecuritystandards.org/are-you-ready-for-30-june-2018-sayin-goodbye-to-ssl-early-tls)
* [PCI TLS1.2 Guidance](https://www.pcisecuritystandards.org/documents/Migrating-from-SSL-Early-TLS-Info-Supp-v1_1.pdf)

If you need any help contact us on site chat or <support@vgs.io>.


# Branded Domains

## Overview

When integrated with VGS, by default, the traffic is passed via VGS proxy, which looks like either **tntdcjppp6x.sandbox.verygoodproxy.com** or **tntdcjppp6x.live.verygoodproxy.com**, where **tntdcjppp6x** is your Tenant (or *Vault*) identifier. Branded Domains allow VGS customers to publish public APIs that utilize their self-maintained domain names but are protected by VGS. Any request to a branded domain will be proxied through the Inbound Route to which it is connected based on the customer-defined VGS configuration.

## Terms

**CNAME**: a canonical name, an entry within the Domain Name System (DNS) that specifies where someone can find your web pages.

**Default hostname**: VGS term for the default domain with the form {{environment}}.verygoodsecurity.com

**Domain alias**: term for additional branded domains assigned to a site.

**DNS provider**: a company that maintains the DNS servers that translate a domain name to a destination.

**TLS certificate**: TLS stands for Transport Layer Security, together with the now-deprecated predecessor, Secure Sockets Layer (SSL), are cryptographic protocols designed to provide communications security over a computer network.

### Add a Branded Domain

Add a new CNAME and a TLS certificate will be issued for it by VGS.

**Dedicated TLS certificates are automatically generated and propagated through our global content delivery network, providing robust encryption, along with lightning-fast performance and compatibility.**

Add a custom Hostname on the dashboard:

1. Log in to the VGS dashboard.
2. Go to the Vault Settings > Custom Hostnames
3. Click Add
4. Enter the domain alias (CNAME domain). For example payments.brandeddomain.com
5. Click Save

<figure><img src="/files/jdBoNgjKUg9F2lmSBmZJ" alt=""><figcaption></figcaption></figure>

The validation and deployment process completes in \~90 seconds. After adding the Branded Domain, view the provisioning status under the Status column in the CNAMEs section. The provisioning takes up to 30 minutes. **VGS defaults to auto-renewal of the TLS certificate.**

If the provisioning was successful - you will see "Activate for SDKs" button. Verifying allows you to use this CNAME with VGS Collect/Show/Checkout products.

If the hostname is invalid:

* Visit your DNS provider
* Add a CNAME record for mydomain pointing to either \<vault\_id>.sandbox.verygoodproxy.com or \<vault\_id>.live.verygoodproxy.com
  * NOTE: The intended value for \<vault\_id> is the **Tenant ID** (also known as *Vault ID*), beginning with prefix *tnt*.

If you’ve already done this, allow up to 24 hours for the changes to propagate. Once issued, certificates are valid for 90 days, and renew automatically 21 days before expiration. Renewals require no action from your side.

### Connect a Branded Domain to an Inbound Route

To assign a branded domain to an inbound route:

1. Go to Routes › click Manage
2. Click on the + icon in the Custom Hostnames section
3. Select a custom hostname from the list or add a new CNAME
4. Save the route

The Default CNAME is the VGS hostname used by your service/s. The default CNAME can be used only once. To change it, choose one of the CNAMEs from the list and then remove the default one.

### Removing a CNAME

1. Go to the Vault Settings > Custom Hostnames
2. Press the ‘delete’ icon next to the custom hostname that needs to be removed.

### CNAMEs Errors

In case your CNAME becomes invalid. If, for instance, the CNAME value points to the incorrect domain, the status field on the Custom Hostnames tab changes from ‘Valid’ to ‘Invalid’.


# Configuring Multiple Inbound Routes

The default Inbound Route configuration for a Vault allows VGS customers to proxy traffic to *one* destination domain. For example, the Inbound Route URL (`<vault_id>.<env>.verygoodproxy.com)`, can be used to proxy data between a client and a VGS customer server (`secure-api.customer.com`).

As enterprises grow, there are often multiple data ingress points that security, compliance, and engineering teams want to protect using VGS Aliases.&#x20;


# Web Application Firewalls with Inbound Routes

`VGS + WAF = ❤`

The long, complex history of HTTP provides fertile ground for [HTTP desync attacks](https://www.youtube.com/watch?v=_A04msdplXs), and there remain no guardrails for application security flaws. Website compromise and data breaches are still common, leading to the loss of revenue and customer trust, as well as lawsuits and even the extinction of many businesses. Therefore, it is essential that web app owners up their security game and invest in a Web Application Firewall (WAF).

Traditional firewalls sit at the network or transport layer of the OSI model, between trusted and untrusted networks. But today, you can deploy a WAF at the highest layer (the application layer), where it sits right in front of your users and data. Both types of firewalls handle access control and network defense, but in unique positions with unique tools and strategies. Working together, they offer your enterprise greater [defense-in-depth](https://www.youtube.com/watch?v=uuojtUx-LOU).

WAFs protect your enterprise against a wide range of attacks that specifically target web apps, including remote code execution, insufficient authentication, exploits, SQL injection, cross-site scripting (XSS), cross-site request forgery (CSRF), directory traversal, file inclusion, HTTP floods, malicious scanning, and more. Many of these attacks are detailed in the Open Web Application Security Project’s [Top 10 Web Application Security Risks](https://owasp.org/www-project-top-ten/).

There are [three different types of WAFs](https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/): network, host, and cloud. Network and host-based devices are typically located on-premises, while a cloud model is a SaaS solution. There are both commercial and non-commercial WAFs. One open-source WAF, [ModSecurity](https://en.wikipedia.org/wiki/ModSecurity), is a part of OWASP and has its own rule configuration language called “SecRules.” Commercial WAFs vary significantly in price depending on interface, options, requirements, etc. [Typical costs](https://www.youtube.com/watch?v=GkahSN6I4p0) are based on the number of rules you configure and the number of HTTP requests you receive. All things considered, we believe that most VGS customers would be best served with a cloud-based WAF.

## How does a WAF work? <a href="#how-does-a-waf-work" id="how-does-a-waf-work"></a>

A WAF intercepts and inspects inbound web requests (HTTP/HTTPS) to detect and prevent malicious traffic from reaching your web apps. WAFs are powerful and can dig deep into network packets to evaluate what is inside the payload. They can parse data, identify malicious signatures, and evaluate suspicious behavior. All of this is necessary to recognize and stop sophisticated network attacks.

A web request must adhere to your [security rules](https://www.youtube.com/watch?v=p8CQcF_9280), often called policies, or it does not get permission to touch your web app. As with traditional firewalls, WAFs can make decisions based on “positive” or “negative” logic. Positive security policies, such as an allowlist, typically run first and may allow only a certain type of inbound request or from a certain location (or both). Negative security policies, which usually run second, can block an inbound request that matches a malicious signature (e.g., SQL injection) or an attempted denial-of-service.

Each strategy has its strengths and weaknesses, and it is often necessary to leverage both. However, you are highly encouraged to create allowlists because they are designed to deny everything except that which is specifically allowed. They also consume fewer resources than a blacklist and go a long way toward preventing zero-day exploits.

## WAF Configuration <a href="#waf-configuration" id="waf-configuration"></a>

A WAF has three [components](https://www.youtube.com/watch?v=5e4BUKeGZNk):

1. **Conditions:** the characteristics of an inbound web request used for decision-making, such as source IP address, hostname, geography, time, or type of attack (e.g., XSS).
2. **Rules:** with boolean logic, you tell your WAF what to do, including whether to stop the request or simply alert on specific behavior.
3. **Web access control list (ACL):** “A B C” stands for allow, block, or count (the latter is used for rate-based rules, in which you allow a maximum number of requests matching specific criteria, and then block the rest).

WAF rule sets can quickly become long and complicated. There are many sketchy IP addresses out there and thousands of malicious signatures to consider. The attack space is constantly growing, and hackers have the incentive to innovate. With rate-based defenses, it can be difficult to stop offensive behavior without creating your own denial-of-service in the process.

In spite of these challenges, help is never too far away. Some WAF providers offer [pre-built templates](https://www.youtube.com/watch?v=SmF_wQuZ7z4) to get you started. The open-source ModSecurity WAF [Core Rule Set](https://github.com/coreruleset/coreruleset/tree/v3.4/dev/rules) covers many popular web apps and common threats, and offers a high level of security for [Apache web servers](https://www.youtube.com/watch?v=MB7nQrlP5Yc). One of the strengths of a WAF is the ability to modify policies quickly; for example, in the event of a DDoS attack, rate limiting can be set to slow the barrage.

Finally, WAFs have a transparent mode and a proxy mode. In the first case, a WAF sends web requests directly to the web application. In the latter, a WAF provides additional protection to the server by acting as an intermediary hop -- which can increase security, but unfortunately also increase latency.

## Testing & Remediation <a href="#testing-and-remediation" id="testing-and-remediation"></a>

Due to the size, speed, and complexity of today’s networks, security can be hard to achieve and is always a moving target. You must continually test your WAF configuration. Vulnerability scanners and penetration testing can find software coding errors and discover unknown vulnerabilities.

Many web apps can be quite unique, with their own intrinsic vulnerabilities and exploits. Furthermore, enterprises often have numerous web apps to protect.

Positive rules are highly restrictive, but can be a challenge to create and maintain. Negative rules are often complex and voluminous, result in a high number of false positives, and still have trouble identifying every malicious web request.

Hackers engage in [numerous strategies to bypass WAFs](https://www.youtube.com/watch?v=iQqwQXHwQk0). Here are some examples:

1. **Pre-processor exploitation:** deceiving a WAF into skipping input validation
2. **Impedance mismatch:** a WAF interprets input differently than the backend
3. **Rule-set bypassing:** sending payloads undetectable by a WAF

Once security vulnerabilities become known, it is critical to fix them, and the sooner, the better. For some hard-to-kill bugs, it may be necessary to apply virtual patches or immediate but temporary fixes.

For any modern enterprise, a WAF plays a vital role in a cloud-based defense-in-depth security strategy. Not only does it protect against malicious web traffic and hedge against web app vulnerabilities, but it also helps to fulfill information security guidelines and compliance requirements such as [PCI DSS](https://www.pcisecuritystandards.org/) and [SOC2](https://www.verygoodsecurity.com/compliance-solutions/soc-2). And as a bonus, filtering out all of that junk traffic can reduce costs and improve your customer [user experience](https://www.youtube.com/watch?v=xXxYJB3B8WY).

## WAF Placement <a href="#waf-placement" id="waf-placement"></a>

One of the most important configuration questions you will face is whether to place your WAF in front of VGS or behind. Whichever placement you choose, there will be benefits, drawbacks, and tradeoffs. Fortunately, the VGS proxy protocol is both secure and flexible, allowing you to tailor your architecture in a way that best suits your needs.

A good way to approach this question is to consider exactly how you want your clients to interact with your backend. You know your enterprise and web apps best, and only you can fine-tune all of the options to their ideal state. That said, in the end, a major determinant will be which type of WAF you choose: network, host, or cloud-based.

### **VGS First**

Network- and host-based WAFs are on-premises, co-located with your backend. In this scenario, your WAF is your primary ingress, and you are already familiar with its role in protecting your backend services. Therefore, we recommend that you maintain this architecture, as you can easily route your traffic through the VGS proxy first.

<figure><img src="https://docs.verygoodsecurity.com/~gitbook/image?url=https%3A%2F%2F2096104711-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FUreALQAfVnRMQEz110rC%252Fuploads%252Fgit-blob-089b86c2bb336d5d88cc43fa278c1d611dcaf9a5%252Fvgs-waf.png%3Falt%3Dmedia&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=6a7ce403&#x26;sv=2" alt=""><figcaption></figcaption></figure>

By putting VGS first, you take advantage of numerous VGS security features. This includes our default capability to rate-limit traffic, which significantly helps to minimize the harmful effects of a denial-of-service and is typically a feature for which WAF providers add a surcharge. Furthermore, VGS provides other types of traffic restrictions, such as IP allowlisting, in which only specific, pre-authorized source IP addresses have the right to access your backend.

### **WAF First**

Now let’s consider a cloud- or SaaS-based WAF. In this scenario, your WAF is the edge ingress, has initial access to the unredacted web requests, and restricts traffic before it routes to VGS. Thus, VGS sits behind your WAF but in front of your backend. This architecture has some significant design advantages -- as well as some important caveats.

<figure><img src="https://docs.verygoodsecurity.com/~gitbook/image?url=https%3A%2F%2F2096104711-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FUreALQAfVnRMQEz110rC%252Fuploads%252FuEnWVHiVbLekwDFgT4aO%252Fimage.png%3Falt%3Dmedia%26token%3Da7e8eec2-ecc4-4f97-83da-5486d26823e8&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=a15201df&#x26;sv=2" alt=""><figcaption></figcaption></figure>

First, VGS customers should take advantage of our IP allowlisting feature. Depending on your cloud WAF implementation, the request routing to VGS may be known, or it could be hidden. This could happen, for example, when the route is configured with a DNS CNAME (and even if you do not use a CNAME, your vault DNS is not expected to be a secret). Thus, allowlisting is an important part of securing your APIs, as specifying your WAF egress IPs helps to ensure that your WAF is not easily bypassed. Most WAF providers provide easy access to their egress IPs (e.g., Cloudflare: <https://www.cloudflare.com/ips/>).

Second, placing your WAF first is a smart choice for VGS clients because VGS currently does not have the capacity of a global content delivery network (CDN). SSL termination points that are physically closer to the end user dramatically improve connection speeds. A global CDN can improve user experience via faster initial connections and SSL handshakes that normally require multiple back-and-forth requests and response messages, which can lead to significant latency.

Third, if your WAF sits in front of VGS, your WAF must process the web requests first and perform the rate limiting. The simple reason is that VGS cannot determine the original source of the requests. Therefore, you should inform VGS so that we can disable this vault feature. This is necessary to avoid a VGS rate limit against the WAF (which would include the traffic of all your clients combined).

Fourth, when your WAF is in front of VGS, your WAF vendor is now within your compliance scope. Because the WAF must perform SSL termination, your WAF provider will see the sensitive contents of your web requests before VGS has had a chance to alias them. However, there are many great cloud-based WAF providers with strong compliance certifications, so make sure you choose one aligned with your organization’s compliance goals.

## Better Visibility = Increased Security <a href="#better-visibility-increased-security" id="better-visibility-increased-security"></a>

Whichever configuration you choose, the goal is the same: better visibility into your web requests and increased security for your enterprise.

If you have an on-prem WAF (and VGS processes your web requests first), VGS will provide you with an accurate source IP in the X-Real-IP request header. Please ensure that your on-prem WAF or other ingress does not replace this field with a VGS egress IP. Additionally, VGS provides the X-Forward-For in the header, but this must be used with caution, as an attacker can append new, incorrect values to this field.

If your WAF sits in front of VGS and proxies web requests through VGS, please note that VGS appends the X-Real-IP from your upstream WAF. You can configure your WAF to inject an alternate header, such as X-Forward-For. However, you should only do so if your WAF is capable of ignoring user-supplied values; remember that an attacker may try to hide their origin by specifying an incorrect or fake value in this field. An alternative, if the WAF provides the capability, is to use a new and unique header.

When used in tandem, VGS + WAF integration offers numerous potential advantages for your enterprise. Remember that security is a journey, not a destination, and there is always more to do. If you have any questions, [please ask](https://www.verygoodsecurity.com/contact)!


# Outbound Routes

Our outbound connection uses an outbound/forward [proxy](/vault/http-proxy).

## What does it allow you to do?

* Like the [inbound connection](/vault/http-proxy/inbound-connection), the outbound/forward proxy allows you to rewrite requests and responses on the fly.
* Lets you operate on data outside of the scope of your backend systems.
* Set/Change/Strip Headers - perform any operation on the payload.
* Modify the payload, even if it's not a strict redaction/replacement.
* Perform Edge Computing, as needed for computing outside of the scope of your system (enterprise plans)
* Adds an additional layer of security requiring proxy-authorization credentials and a root certificate to be set.
* Is used to integrate into third party services and allows for configurations that are processor specific as mentioned in the [integrations](/vault/http-proxy/integration-templates) page.
* Our outbound/forward proxy also allows for IP Anonymization as an additional upgrade.

## How does it work?

The outbound/forward proxy directs traffic between your server (outbound) traffic, the VGS vault (where sensitive data is stored), and your third party integration

**Example:**

* BEFORE: server.foo.com → api.worldpay.com
* AFTER: server.foo.com → `<VAULT_ID>`.`<ENVIRONMENT>`.verygoodproxy.com → api.worldpay.com
  * NOTE: The intended value for `<VAULT_ID>` is the **Tenant ID** (also known as *Vault ID*), beginning with prefix *tnt*.

To achieve that you should set your server to send traffic through our outbound/forward proxy and create routes, filters and operations for your different API endpoints.

## TLS Certificates

The outbound/forward proxy requires a TLS certificate. We have a different server certificate for each environment, **SANDBOX** and **LIVE**. You can find these certificates within the 'Code snippets' section of your dashboard.

## Code Samples

1. Download and use appropriate TLS certificate for your vault environment to use in your application.&#x20;

<details>

<summary>sandbox.pem</summary>

```bash
-----BEGIN CERTIFICATE-----
MIID2TCCAsGgAwIBAgIHAN4Gs/LGhzANBgkqhkiG9w0BAQ0FADB5MSQwIgYDVQQD
DBsqLnNhbmRib3gudmVyeWdvb2Rwcm94eS5jb20xITAfBgNVBAoMGFZlcnkgR29v
ZCBTZWN1cml0eSwgSW5jLjEuMCwGA1UECwwlVmVyeSBHb29kIFNlY3VyaXR5IC0g
RW5naW5lZXJpbmcgVGVhbTAgFw0xNjAyMDkyMzUzMzZaGA8yMTE3MDExNTIzNTMz
NloweTEkMCIGA1UEAwwbKi5zYW5kYm94LnZlcnlnb29kcHJveHkuY29tMSEwHwYD
VQQKDBhWZXJ5IEdvb2QgU2VjdXJpdHksIEluYy4xLjAsBgNVBAsMJVZlcnkgR29v
ZCBTZWN1cml0eSAtIEVuZ2luZWVyaW5nIFRlYW0wggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDI3ukHpxIlDCvFjpqn4gAkrQVdWll/uI0Kv3wirwZ3Qrpg
BVeXjInJ+rV9r0ouBIoY8IgRLak5Hy/tSeV6nAVHv0t41B7VyoeTAsZYSWU11deR
DBSBXHWH9zKEvXkkPdy9tgHnvLIzui2H59OPljV7z3sCLguRIvIIw8djaV9z7FRm
KRsfmYHKOBlSO4TlpfXQg7jQ5ds65q8FFGvTB5qAgLXS8W8pvdk8jccmuzQXFUY+
ZtHgjThg7BHWWUn+7m6hQ6iHHCj34Qu69F8nLamd+KJ//14lukdyKs3AMrYsFaby
k+UGemM/s2q3B+39B6YKaHao0SRzSJC7qDwbWPy3AgMBAAGjZDBiMB0GA1UdDgQW
BBRWlIRrE2p2P018VTzTb6BaeOFhAzAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQE
AwIBtjAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAwDQYJKoZI
hvcNAQENBQADggEBAGWxLFlr0b9lWkOLcZtR9IDVxDL9z+UPFEk70D3NPaqXkoE/
TNNUkXgS6+VBA2G8nigq2Yj8qoIM+kTXPb8TzWv+lrcLm+i+4AShKVknpB15cC1C
/NJfyYGRW66s/w7HNS20RmrdN+bWS0PA4CVLXdGzUJn0PCsfsS+6Acn7RPAE+0A8
WB7JzXWi8x9mOJwiOhodp4j41mv+5eHM0reMh6ycuYbjquDNpiNnsLztk6MGsgAP
5C59drQWJU47738BcfbByuSTYFog6zNYCm7ACqbtiwvFTwjneNebOhsOlaEAHjup
d4QBqYVs7pzkhNNp9oUvv4wGf/KJcw5B9E6Tpfk=
-----END CERTIFICATE-----
```

</details>

<details>

<summary>live.pem</summary>

```bash
-----BEGIN CERTIFICATE-----
MIID0jCCArqgAwIBAgIGPraFBmGCMA0GCSqGSIb3DQEBDQUAMHYxITAfBgNVBAMM
GCoubGl2ZS52ZXJ5Z29vZHByb3h5LmNvbTEhMB8GA1UECgwYVmVyeSBHb29kIFNl
Y3VyaXR5LCBJbmMuMS4wLAYDVQQLDCVWZXJ5IEdvb2QgU2VjdXJpdHkgLSBFbmdp
bmVlcmluZyBUZWFtMCAXDTE2MDIwOTIzNTMzNloYDzIxMTcwMTE1MjM1MzM2WjB2
MSEwHwYDVQQDDBgqLmxpdmUudmVyeWdvb2Rwcm94eS5jb20xITAfBgNVBAoMGFZl
cnkgR29vZCBTZWN1cml0eSwgSW5jLjEuMCwGA1UECwwlVmVyeSBHb29kIFNlY3Vy
aXR5IC0gRW5naW5lZXJpbmcgVGVhbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAIaWead09ni5HVb6Z35MblQGzwQChshwO120nfyBsAUCGfK2SsIjFrV3
Nn0zlFn9h4SHplJPtxLHPiqFQLplv9sH4m78mK7EQ0I5CRPBc0FieOyFH5+UXZOv
Pl1NHstiAE2eHXpZQBKr7QO5h1dezILf88aK6aX9uojshxpXCrzlf2BlzYY8D4yb
IEedG61/aEjTQY+ATPW9oWDAeEIotgsC2aITw4qW3OxpP4f16QP/k8xazv23Pcha
JfQxjCnPIx1/IwQQi14qEqqGCKnreGL8KnAN1W3uz4JtRou01uAUGhhB+zkqSz9a
0P7RA0rWD5Sy34YNOiR4Dt8H8R8E+jECAwEAAaNkMGIwHQYDVR0OBBYEFBV0Bvd3
w6UGIgls8VKnooKjkmQYMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgG2MCMG
A1UdJQQcMBoGCCsGAQUFBwMBBggrBgEFBQcDAgYEVR0lADANBgkqhkiG9w0BAQ0F
AAOCAQEAEwrq/aEgjjbcRZTbtrbIOLNsEoE4YSM/ZwFeCjGP9MWmq/qX3DZECwIC
gIc6kUQEdeAe3lt7GFfc+eY0HmximG0dnISSfzzpL33HQOhud6LITT0YAfqz0hxr
NLra+XfkIRMH/vs7PqzH8siqYXxW6w52PvwX1tbMJnoq1fUGSIyxF3wZ5i+OElP9
93KcZHeI6x8KSuCc+eNAV0eovsd9XN6Pzovf9BC3/HZANndI6JJ65XJ9MygdRNF7
qR90C8HYJYGpRE6nglQi0QOTHYC7xVqrU5bxuY7znWOEGfkFug4leuKdj12TkW73
bbTjK25TlDkdvsPq4otwBkXemYcoYA==
-----END CERTIFICATE-----
```

</details>

2. Run this sample code snippet in your terminal to see an example of data revealing.

{% tabs %}
{% tab title="Curl" %}

```bash
curl https://echo.sandbox.verygoodvault.com/post --cacert path/to/sandbox.pem \
  -x https://USiyQvWcT7wcpy8gvFb1GVmz:2b48a642-615a-4b3c-8db5-e02a88147174@tntsfeqzp4a.sandbox.verygoodproxy.com:8443 \
  -H "Content-type: application/json" \
  -d '{"account_number": "tok_sandbox_w8CBfH8vyYL2xWSmMWe3Ds"}'
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
  "bytes"
  "encoding/json"
  "io/ioutil"
  "fmt"
  "net/http"
  "os"
  "crypto/tls"
  "crypto/x509"
)


type Payload struct {
  Account string `json:"account_number"`
}

func main() {
  // You can set the proxy as an HTTPS env variable proxyUrl and go will use by default:
  os.Setenv("HTTPS_PROXY", "https://USiyQvWcT7wcpy8gvFb1GVmz:2b48a642-615a-4b3c-8db5-e02a88147174@tntsfeqzp4a.sandbox.verygoodproxy.com:8443")

  data := Payload{
    Account: "tok_sandbox_w8CBfH8vyYL2xWSmMWe3Ds",
  }
  payloadBytes, err := json.Marshal(data)
  if err != nil {
    fmt.Println(err)
  }

  body := bytes.NewReader(payloadBytes)

  caCert, err := ioutil.ReadFile("path/to/sandbox.pem")
  if err != nil {
    fmt.Println(err)
  }
  caCertPool := x509.NewCertPool()
  caCertPool.AppendCertsFromPEM(caCert)

  client := &http.Client{
    Transport: &http.Transport{
      Proxy: http.ProxyFromEnvironment,
      TLSClientConfig: &tls.Config{
        RootCAs: caCertPool,
        InsecureSkipVerify: true,
      },
    },
  }

  req, err := http.NewRequest("POST", "https://echo.apps.verygood.systems/post", body)
  if err != nil {
    fmt.Println(err)
  }
  req.Header.Set("Content-Type", "application/json")

  resp, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
  }

  defer resp.Body.Close()

  respB, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    fmt.Println(err)
  }
  fmt.Println(string(respB))
}
```

{% endtab %}

{% tab title="Java" %}

```java
package com.verygoodsecurity;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

public class OutboundIntegration {

  public static void main(String[] args) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    tlsProxy();
  }

  private static void tlsProxy() throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    final int proxyPort = {SECURE_PORT};
    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
        new AuthScope("tntsfeqzp4a.sandbox.verygoodproxy.com", proxyPort),
        new UsernamePasswordCredentials("USiyQvWcT7wcpy8gvFb1GVmz", "2b48a642-615a-4b3c-8db5-e02a88147174"));
    HttpHost proxy = new HttpHost("tntsfeqzp4a.sandbox.verygoodproxy.com", proxyPort, "https");
    HttpHost target = new HttpHost(new URL("https://echo.apps.verygood.systems").getHost(), 443, "https");

    CloseableHttpClient httpclient = HttpClients.custom()
        .setSSLSocketFactory(getSslConnectionSocketFactory())
        .setDefaultCredentialsProvider(credsProvider).build();

    try {

      RequestConfig config = RequestConfig.custom()
          .setProxy(proxy)
          .build();
      HttpPost httpPost = getRequest(config);


      CloseableHttpResponse response = httpclient.execute(target, httpPost);
      try {
        System.out.println("status code=" + response.getStatusLine());
        System.out.println("response=" + EntityUtils.toString(response.getEntity()));
      } finally {
        response.close();
      }
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      httpclient.close();
    }
  }

  private static HttpPost getRequest(RequestConfig config) throws UnsupportedEncodingException {
    HttpPost httpPost = new HttpPost("/post");
    HttpEntity requestEntity = new StringEntity("{"account_number":"{ALIAS}"}");
    httpPost.setHeader("Content-Type", "application/json");
    httpPost.setEntity(requestEntity);
    httpPost.setConfig(config);
    return httpPost;
  }

  private static SSLConnectionSocketFactory getSslConnectionSocketFactory() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {

    SSLContext sslcontext = SSLContexts.custom()
        .loadTrustMaterial(getKeystore(), null)
        .build();
    return new SSLConnectionSocketFactory(
        sslcontext,
        new String[] { "TLSv1.2" },
        null,
        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

  }

  private static KeyStore getKeystore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, "vgs".toCharArray());

    FileInputStream fis = new FileInputStream("path/to/sandbox.pem");
    X509Certificate vgsSelfSigned = (X509Certificate) CertificateFactory.getInstance("X.509")
        .generateCertificate(new BufferedInputStream(fis));
    ks.setCertificateEntry("VGS Self Signed Certificate", vgsSelfSigned);
    URL destinationURL = new URL("https://" + "tntsfeqzp4a.sandbox.verygoodproxy.com");
    HttpsURLConnection conn = (HttpsURLConnection) destinationURL.openConnection();
    conn.connect();
    Arrays.stream(conn.getServerCertificates()).forEach(certificate -> {
      try {
        ks.setCertificateEntry(String.valueOf(certificate.hashCode()), certificate);
      } catch (KeyStoreException e) {
        e.printStackTrace();
      }
    });
    return ks;
  }
}
```

{% endtab %}

{% tab title="Python" %}

```python
import json
import tempfile
import os

import requests # requires requests==2.26.0 and urllib3==1.26.7
from requests import utils

def send_post_request(url, proxy, payload, headers, ca):
    return requests.post(url, proxies={f'https': proxy},
                         data=json.dumps(payload),
                         headers=headers, verify=ca)


def vgs_proxy():
    payload = {'account_number': 'tok_sandbox_w8CBfH8vyYL2xWSmMWe3Ds'}
    path_to_lib_ca = utils.DEFAULT_CA_BUNDLE_PATH
    path_to_vgs_ca = 'path/to/sandbox.pem'
    with tempfile.NamedTemporaryFile() as ca_file:
        ca_file.write(read_file(path_to_vgs_ca))
        ca_file.write(str.encode(os.linesep))
        ca_file.write(read_file(path_to_lib_ca))
        read_file(ca_file.name)
        return send_post_request(
            url=f'https://echo.apps.verygood.systems/post',
            proxy=f'https://USiyQvWcT7wcpy8gvFb1GVmz:2b48a642-615a-4b3c-8db5-e02a88147174@tntsfeqzp4a.sandbox.verygoodproxy.com:8443',
            payload=payload,
            headers={
                'Content-type': 'application/json',
                'User-Agent': "requests-python"
            },
            ca=ca_file.name).content


def read_file(path):
    with open(path, mode='rb') as file:
        return file.read()


print(vgs_proxy())
```

{% endtab %}

{% tab title="Ruby" %}

{% endtab %}
{% endtabs %}

> For Spring-based Java applications, you can use our [vgs-proxy-spring](https://github.com/verygoodsecurity/vgs-proxy-spring) library.

**Example Use Case:** You need to send a customer’s Social Security number (SSN) to the Acme Background Check Service. You:

* have previously collected the social security number
* exchanged it for a VGS token to store in your database.

Now you should:

1. Create an outbound route in your VGS dashboard
2. Set Acme’s endpoint as the upstream host
3. Add a reveal filter in the request phase to replace the tokenized SSN with the real value
4. Add the route to your network as a forward proxy

The outbound/forward proxy directs traffic between your server (outbound), the VGS vault (where sensitive data is stored), and your third-party integrations, as illustrated by the image below.&#x20;

<figure><img src="/files/sXoxnFPhfCEHktkYl6sC" alt=""><figcaption></figcaption></figure>

Use this command for testing the setup to simulate your back end (using cURL)

\`simulate-backend-integration\`

### How to implement?

We have several examples of API Call specific outbound implementations [here](https://github.com/vgs-samples/vgs-proxy-examples).

\`forward-implementation-example\`

For many languages, setting the proxy as an environmental variable enables the outbound/forward proxy to be used at a framework or library level.

### HTTP Basic Authentication

This enables a password of your VGS vault, so that only your application can reveal and access sensitive data. You must provide the [username and password](/vault/http-proxy/outbound-connection/access-credentials) via the following URL format. `https://<USERNAME>:<PASSWORD>@<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com:8443`

***Note: Some backend languages require you to access this url by passing auth in a different manner.***

VGS outbound/forward proxy reveal operations require HTTP Basic Authentication using the [username and password](/vault/http-proxy/outbound-connection/access-credentials) provided in the VGS dashboard.

It is up to you to protect these credentials; treat them like an API key. Please refer [Basic Authentication](http://en.wikipedia.org/wiki/HTTP_Authentication) for more information.

### Tips on storing HTTP Basic Authentication Secrets Securely

* Do not embed secrets directly in code.
* Do not store secrets in files inside your application, including the application’s source tree.
* If you do accidentally commit secrets to version control, revoke it immediately and generate a new one.
* Ensure secrets do not appear in URLs or anywhere they can be captured in web server logs.
* Review your code carefully and ensure it doesn’t contain secrets or any other private information before publicly releasing it.
* Put the configuration file containing the secrets in the revision control ignore. This prevents committing them by mistake in the future.
* Limit the usage of secrets
* Restrict your secrets to be used by only the IP addresses, referrer URLs, and mobile apps that need them. Don't share your secrets with different applications. If more than one application uses the same API, register each application so you get a new set of secrets and update the secrets.
* Delete unneeded secrets.
* Update (Regenerate) your secrets periodically.

**References:**

* [Best practices for securely using Secrets](https://support.google.com/cloud/answer/6310037?hl=en)
* [REST Security Cheat Sheet - OWASP](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html)

### Encrypted Communication

VGS supports encryption to protect communications between VGS and your web application. VGS supports the TLS cryptographic protocol. Support for anything less than TLS1.2 is officially deprecated.

For more information regarding TLS:

* [Upgrading your application](https://support.cloudways.com/en/articles/5121355-how-to-update-the-tls-version)
* [PCI Standards Blog: TLS1.2](https://blog.pcisecuritystandards.org/are-you-ready-for-30-june-2018-sayin-goodbye-to-ssl-early-tls)
* [PCI TLS1.2 Guidance](https://www.pcisecuritystandards.org/documents/Migrating-from-SSL-Early-TLS-Info-Supp-v1_1.pdf)

### Alternative Using Reverse Proxy

If your server making outbound requests is already behind a proxy, it can be cumbersome to add a second, chained proxy. You can instead set up a VGS reverse proxy between your server and external services. This is simpler to implement, and suitable for testing, development, and building proof of concepts.

To implement, follow these steps:

1. If you already have an inbound route configured (which you likely do in order to securely collect PII), create a custom hostname for this route. For this example, suppose your custom hostname is backgroundcheck.yourcompany.com
2. Create an inbound route in your VGS dashboard
3. Set Acme’s endpoint as the upstream host
4. Set the route to allow requests to your custom hostname
5. Add a reveal filter in the request phase to replace the tokenized SSN with the real value
6. Modify your back end code to send the background check request to the custom hostname.

The data flow now looks like this.&#x20;

<figure><img src="/files/vmlzdMcoUMFLB7pHjkR5" alt=""><figcaption></figcaption></figure>

To test the setup using cURL to simulate your back end, run this cURL command.

```
curl https://backgroundcheck.yourcompany.com/post -k \
  -x https://tntsfeqzp4a.sandbox.verygoodproxy.com \
  -X POST \
  -H "Content-type: application/json"  \
  -d '{"ssn": "$VGS_TOKEN"}'
```

If you need any help setting up outbound connections, please contact us on site chat or at <support@vgs.io>.


# Outbound Access Credentials

Access Credentials are used to connect to VGS to send data to third parties via Outbound Routes

## Generating new Access Credentials

Access Credentials are automatically created for the user when a vault is created. *To help ensure security, credentials are never stored in plaintext within VGS systems.* When Access Credentials are generated you will be prompted to download them. If you lose these credentials, you can generate a new pair via the settings page for your vault.&#x20;

Access Credentials can be generated and read only by organization admins.

**Please note that the credential’s secret can be downloaded&#x20;*****only*****&#x20;at the time of generation.**

## Rotating credentials

Rotating credentials is a security best practice as it shortens the period access credentials can be used. This also reduces any possible business impact if they are compromised.

Remember to always check whether the new credentials are active and working before you delete your current credentials. **You cannot retrieve your credentials once they are deleted.**

**How to rotate your credentials**:

1. Go to your vault on the VGS Dashboard, select Vault Settings, and find the  Access Credentials section. Each vault has at least one set of access credentials by default. In order to perform rotation you’d need at least two. To add a new set of credentials click on “Generate Credentials”. This will show newly generated username/password pair. Store these credentials securely on within your environment .
2. You should now have 2 active credentials for your vault. You need to make sure to distribute new username/password pair to all applications which use VGS.
3. At this point you need to change the status of old credentials to “Inactive”. This will disable credentials in a way that they couldn’t be used for outbound traffic anymore .
4. Make sure to validate all applications are working. In case everything is working as expected feel free to go to step 5. If anything has broken by mistake, for example you forgot to update one of applications using VGS vault, you can quickly make them “Active” again and go back to step 2.
5. After you’ve verified everything is working it’s safe to delete old credentials. Deleted credentials cannot be restored. That’s why VGS asks for additional confirmation before they’re deleted .


# Integration Templates

> Integration templates is still in beta and currently enabled only in **Sandbox Environment**.

VGS Integrations templates - are pre-configured and checked by VGS configurations with description for securely collect data and integrating with best-in-class third-parties. For example, Visa Direct, Stripe, Authorize.Net, etc. We are constantly improving and adding new templates to provide a better variety of useful integrations.

Use these pre-configured integrations to quickly get up and running. If you don't see the vendor you're working with on the list, we can still support you.

## How to use

Go to **Integrations** on the VGS Dashboard and you will see the list of pre-configured VGS Integrations. You can search Integrations by names.&#x20;

<figure><img src="/files/jColWac9ba31VugqETWO" alt=""><figcaption></figcaption></figure>

Select the integration you need, and you will see a description and option to **Enable** the Integration version or type. &#x20;

<figure><img src="/files/TEk5PCpMciG2Sb8NIY1o" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/gxPE85bOFqCEPeqwrea8" alt=""><figcaption></figcaption></figure>

After **VGS Integration** is **Enabled**, your Route is created and you can test it by clicking **Verify** button. To preview the Route you can click on the Integration version or type link. &#x20;

<figure><img src="/files/896t59vO9AkkRdDoCVej" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/TC0ZkKpcr4vSE3zWTmLm" alt=""><figcaption></figcaption></figure>


# Monitoring and Inspecting Proxy Traffic

## Using the Access Logger

The access logger has two properties. One is for recording specific payloads to create routes, filters, and operations on your payloads to be secured. The second property is recording traffic, status codes, and showing you what requests are being made through VGS to and from your server.

Enabling the record function will record traffic for 1 hour. During this time, you can introspect on traffic and fine-tune your configurations.

<figure><img src="/files/76eolwIQVA2yefNyZ0B9" alt=""><figcaption></figcaption></figure>

## Viewing Payloads

To view the requests that were captured, after you've clicked record and sent data through, click 'Load New Requests' if it hasn't populated. Recorded requests will show a little database icon to the left.

Once you click an entry a pop-up showing you all the details of the payload (Headers and Body, Request and Response) will be viewable.

<figure><img src="/files/wyChvRurx9Q4soktDl4M" alt=""><figcaption></figcaption></figure>

Within this view, we have more context around the request, including headers, body, origin, etc.

Right now, you can see the Request Body with the original value being rewritten to the alias.

<figure><img src="/files/fGE0XPbzqcUwNo3MdQDB" alt=""><figcaption></figcaption></figure>

From here, we can select the payload we want to operate on and generate filters and a route for and get the following options to operate on our data. Redact/Reveal, Storage, and Format.

<figure><img src="/files/kNoAUGARuEqxbHtjlEZP" alt=""><figcaption></figcaption></figure>

## Debugging

If an error occurs while sending data, the access logs are an extremely useful tool. Here we have a 405 Method not allowed error.

Clicking on the item with the error status code reveals the full error message response and enables us to inspect the Request that caused the error.&#x20;

In this case, this particular endpoint only allows for HEAD, OPTIONS, and POST. Our request caused an error because it was a GET to a `/post` route.

&#x20;Our access logs show the body of the payloads and the response messages. It is also useful for making sure headers, endpoints, paths, etc., align with the filters set up.

While setting up filters, you may need some insights into whether filters' conditions and operations are matched in requests - pay attention to the Match Information section of the General tab.

## Access Logs

The additional functionality of the Access Logs is that in the Live environment and Sandbox environment, you will see the most recent requests that traveled through VGS, their status codes, and the time of the action. This is useful for seeing which of your requests finished with good status codes and those that have failed. These are distinct from the other requests that are recorded by their lack of the database icon.

## Request pin/unpin mechanism

To enhance the debugging experience for our internal and external users, we have added and expanded the existing functionality of Access Logs and implemented a pin/unpin mechanism.

Access Logs help to debug issues with route configuration; however, their lifetime is short: 24h for logs, 1h for a log with the payload. From now on, there is a possibility to save the needed requests and reproduce the issue/test scenario without fear of losing the context.

**Pin/Unpin mechanism allows:**

* Pin a request with or without the payload
* Unpin a request from the table
* Filter by pinned-only requests&#x20;

**Pin Request restrictions:**

* Pin Request works on the Sandbox environment only, as the Live payload contains sensitive data
* A maximum of 50 requests can be pinned at the same time
* Pinned requests are kept for 90 days or until they are unpinned

## Download logs

For performing a more detailed analysis of your requests and applying more advanced filtering, use the download logs feature.

**Downloaded logs restrictions:**

* Last 24 hours
* Last 10,000 requests
* Payloads can’t be downloaded

Data format: JSON&#x20;

## Tips

* A 407 error, an authentication error, will prevent you from seeing an upstream response in your Access Logs because the request will terminate at our authentication check before going through our service.
* A 504 response will not produce an error code in the logger. Instead, this means that our service was unable to connect to the destination on the outbound connection (e.g., no status code was returned)
* If you see a request and no response, it may mean that your request didn’t complete its route through the tunnel to its destination.
* If you don’t see anything on the Access Logs page (*and* logging is enabled), you’re not hitting the VGS service.
* The Access Logs also allow you to see what inbound data your server will receive and what outbound data third parties will see.

If you have any questions, comments, or feedback on this guide, contact us at <support@vgs.io>.


# Identifying Upstream Status Codes

When perform an HTTPS request using the VGS HTTPS Proxy, VGS will always attempt to forward the status code that it receives from the upstream server. That said, it is hypothetically possible that the VGS system can provide a different response code than what was returned from the third-party.

In order to verify that the upstream server and VGS are returning the same response codes, VGS appends a "VGS-Upstream-Status-Code" header to the HTTP response. This value contains the exact response code that VGS received from the upstream service and should always match the actual HTTP response status code.

The following is a diagram showcasing how the status code is used during an HTTPS request through the VGS proxy.

<figure><img src="/files/Q82hmUpGr1K0Z3o6Hg6l" alt=""><figcaption></figcaption></figure>

### Sample Response

Below is an example of an HTTPS request that is proxied through the VGS Outbound Route. The response shows both the "200" response from VGS, and the VGS-Upstream-Status-Code of "200" that VGS received from the upstream.

```shellscript
curl -i https://echo.sandbox.verygoodvault.com/post --cacert sandbox.pem \
  -x https://$VGS_USERNAME:@VGS_PASSWORD@tntsfeqzp4a.sandbox.verygoodproxy.com:8443  
  
HTTP/1.1 200 Connection established
Connection: keep-alive
Via: 1.1 proxy

HTTP/1.1 200 OK
Date: Tue, 13 Jan 2026 06:28:17 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH
content-length: 0
VGS-Upstream-Status-Code: 200
Via: 1.1 proxy
VGS-Request-Id: b7415b02f87edf0b2e89448b6dd578c5
```


# Intercepting Request and Response Payloads

Filters are key to securing your data using the VGS Platform. Filters are the logic that dictates which data is segmented to our secure vault and what passes through directly to your systems or third-party systems. In this tutorial, we'll discuss a bit about filters. Filters go hand in hand with [Operations](/vault/http-proxy/operations)

**How to configure filters**

Use [`Routes` menu on the Dashboard](https://dashboard.verygoodsecurity.com/dashboard/v/VLTor87V5Gu72PrMQEKw7aLZF/routes). VGS routes have an extensive set of features, including a wide range of applicable filters, IP allowlisting, and custom hostnames.

A Filter has three parts: an 'Attribute', an 'Operator' (in, not in, matches, equals, etc.), and a final 'Variable' field that ties it all together.

### Attributes

The image below shows the expanded Filter Attributes drop-down. Beneath that is a brief definition.&#x20;

<figure><img src="/files/60b0QZ6JlLR5IYSg2ciq" alt=""><figcaption></figcaption></figure>

* `HTTP Method`: GET, POST, PATCH, PUT, DELETE, HEAD, CONNECT, OPTIONS, TRACE (this is the only attribute with set variables)
* `PathInfo`: The path where your filter will fire. /payments, depending on the operator, this can be beginsWith, or matches (using Regex), or equals, among other options
* `ContentType` : Header Information ex. application/json
* `Status`: ex: 200, 301

### Operators

The operators are expanded below. With brief descriptions under that.&#x20;

<figure><img src="/files/wb75SUc3OZqJ65S9vyRY" alt=""><figcaption></figcaption></figure>

* `equals`: exact match case sensitive
* `does not equal`: is not an exact match, case sensitive
* `in`: contains the variable
* `not in`: does not contain the variable
* `begins with`: the path, content-type, et,c begins with the variable
* `does not begin with`: exclusionary operator
* `matches`: REGEX pattern matching option
* `ends with`: Whatever the attribute ends with should match your variable
* `does not end with`: exclusionary ends with
* `is empty`: does not require a variable - just tells if the attribute is empty
* `is not empty`: does not require a variable - just tells if the attribute has a value
* `equals (media type)`: matches the media type according to [RFC7231](https://tools.ietf.org/html/rfc7231#section-3.1.1.1) (applicable to `Content-Type` header only)

### Variables

The final field in the Filter condition, blank on everything but HTTP Methods. You should fill this field out.&#x20;

<figure><img src="/files/koFtTzw4mHvitMN9sfgv" alt=""><figcaption></figcaption></figure>

* Aside from HTTP Methods, this field is for you to enter information and build filter conditions.

### Common Filter Examples

* `'HTTP Method' 'equals' 'POST'`
* `Status Code' 'equals' '200'`
* `'ContentType' 'equals' 'text/xml'`
* `'PathInfo' 'begins with' '/cards'`
* `'ContentType' 'begins with' 'text/html;'`

### Why Filters are Important

The filters are the logic that tells the platform to segment your data on the fly to the vault and replace it with alias values, or let the payload pass through untouched.

If you need help, have questions, or comments regarding this page, contact us at <support@vgs.io>


# Selecting Data Elements to Redact or Reveal

## What are operations?

Operations are different ways to navigate structured data and transform a piece of it by either redacting or replacing the value with a surrogate value.

## Operations Examples

**Most Common:**

* JSONPath (JSON)
* XPath (XML)
* Form
* HTML / CSS
* Regex

## JSONPath

```json
{
    "customers": {
        "first_customer": {
            "first_name": "John",
            "last_name": "Doe",
            "credit_card": "4111111111111111",
            "card_exp": "9/23",
            "card_cvv": "123"
            },
        "second_customer": {
            "first_name": "Jane",
            "last_name": "Smith",
            "credit_card": "4222222222222222",
            "card_exp": "9/23",
            "card_cvv": "123"
        }
    }
}
```

To redact the PCI data in this, we would simply need to create two JSONPath Operations.

Nesting with JSONPath is fairly straightforward. Every level down you go in standard JSON is just `$.toplevelkey.midlevelkey.finallevelkey` like if there are lists in between; you select the item using the index (or you can use wildcards).

To redact the `credit_card` number. All we have to do is select the key. With JSONPath selected as the operation, enter this snippet on the line next to it:

`$.customers..credit_card`

To redact `credit_card` number only for the `first_customer,` we would need to select the next snippet:

`$.[0].credit_card`

If you want to experiment with JSONPath, check out this [tool.](https://jsonpath.curiousconcept.com/)

In advanced options, you can select FPE\_6\_T\_4 to keep the credit card format for mod 10/ Luhn validation.

To redact the CVV, we need to store that in memory, not persistently. So, we add an "Add Entry".

Do exactly the same thing, but change JSONPath to:

`$.[0].card_cvv`

In the advanced options, we need to select Storage *Volatile*

## Xpath

```xml
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schp.org/e/" xmlns:xsd="http:rg/2chema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <AddCardResponse xmlns="">
            <ResponseCode>00</ResponseCode>
            <ResponseDesc>New Card Purchase Order Completed Successfully (932501******1238)</ResponseDesc>
            <NewCardNumber>
                    <Number>4111111111111111</Number>
                <ExpiryDate>092019</ExpiryDate>
            </NewCardNumber>
            <Balance>0.00</Balance>
            <TransId>F378</TransId>
            <CustomerId>3250033</CustomerId>
            <Fee>0.00</Fee>
            <ReferenceID>32513325</ReferenceID>
            <NameOnCard>Andrew</NameOnCard>
        </AddCardResponse>
    </soapenv:Body>
</soapenv:Envelope>
```

An example of how to correctly specify the path to get ***Number*** data:

`//Number`

or

`/Envelope/Body/AddCardResponse/NewCardNumber/Number`

Invalid path:

`/soapenv:Envelope/soapenv:Body/AddCardResponse/NewCardNumber/Number`

> You do not need to specify *Namespace* in your path

To check XPath navigation, use this [tool](https://www.freeformatter.com/xpath-tester.html#ad-output).

## Form

The last type of transformer in this guide is the Form operation. We just use the form field input names as the selector.

HTML form example:

```html
<div class="creditCardForm">
    <div class="heading">
        <h1>Confirm Purchase</h1>
    </div>
    <div class="payment">
        <form action="https://<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com" method="post">
            <div class="form-group owner">
                <label for="owner">Owner</label>
                <input type="text" class="form-control" name="owner" id="owner">
            </div>
            <div class="form-group CVV">
                <label for="cvv">CVV</label>
                <input type="text" class="form-control" name="cvv" id="cvv">
            </div>
            <div class="form-group" id="card-number-field">
                <label for="cardNumber">Card Number</label>
                <input type="text" class="form-control" name="cardNumber" id="cardNumber">
            </div>
            <div class="form-group" name="expiration-date" id="expiration-date">
                <label>Expiration Date</label>
                <select>
                    <option value="01">January</option>
                    <option value="02">February </option>
                    <option value="03">March</option>
                    <option value="04">April</option>
                    <option value="05">May</option>
                    <option value="06">June</option>
                    <option value="07">July</option>
                    <option value="08">August</option>
                    <option value="09">September</option>
                    <option value="10">October</option>
                    <option value="11">November</option>
                    <option value="12">December</option>
                </select>
                <select>
                    <option value="16"> 2016</option>
                    <option value="17"> 2017</option>
                    <option value="18"> 2018</option>
                    <option value="19"> 2019</option>
                    <option value="20"> 2020</option>
                    <option value="21"> 2021</option>
                </select>
            </div>
            <div class="form-group" id="pay-now">
                <button type="submit" class="btn btn-default" id="confirm-purchase">Confirm</button>
            </div>
        </form>
    </div>
</div>
```

For forms, the "name" of the input field is all that's required to replace with a surrogate value. If the Form is URL encoded, make sure you enter the filters as they look decoded.

Select the "Form" transformer and just enter:

`cardNumber`

and under a new entry, volatile storage for CVV

`cvv`

## HTML

You can select this transformer option to select data in HTML forms by using [CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors).

If you have used a JS library like Sizzle or jQuery, you will already be familiar with these.

The simplest selectors allow you to match on

* class names through a `.` e.g. `.myClassName`
* an identifier via a `#` e.g. `#myId`
* an attribute using a series of brackets, with an attribute name and optionally a value inside, e.g. `[attr=value]`
* an element type by simply typing the name of the element, e.g. `input`

You can nest these selectors in order to achieve precise selection of data on the page, e.g. `#myId .myClassName` will match the input element in the following section

```html
<html>
  <body>
    <div id="myId">
      <span class="myClassName">
        Text that will be operated on
      </span>
    </div>
  </body>
</html>
```

## Regex

If the above examples do not cover the type of selection you need, then you can always fall back to a regex. VGS provides a series of named prefixes to assist with complex matching. These are

* `prefix` - Anything to match before
* `token` - The data to match
* `suffix` - Anything matched after

If these are omitted, then anything matched by the regex in its entirety will be operated on.

Here are two examples

* `(\d{16})` - would operate on any 16-digit sequence
* `(?<prefix>foo)(?<token>\d{16})(?<suffix>\d{3})` - would operate on a 16 digit sequence prefixed with `foo` and suffixed with three digits e.g. `foo1234567890123456123` would become `footok_sandbox_asd123123` where the prefix is `foo`, the suffix is `123` and the 16 digit value `1234567890123456` is replaced with the value `tok_sandbox_asd123`

These examples cover the most common operation use cases.

### Replace the value with any text and aliased value.

Replacement parameter: `any text <alias placeholder>`

Route config:&#x20;

<figure><img src="/files/Ay5Aesbtf86SneNiHtEr" alt=""><figcaption></figcaption></figure>

```yaml
transformer: REGEX
transformer_config: - '\b[0-9 ]{13,20}\b'
transformer_config_map:
    patterns: - '\b[0-9 ]{13,20}\b'
    replacement: 'any text:%s'
```

Input:

```json
{
    "first_name": "JOHN",
    "card_number": "4111 1111 1111 1111",
    "ssn": "444411111",
    "dob": "1931-01-01"
}
```

Output:

```json
{
    "first_name": "JOHN",
    "card_number": "any text:tok_sfvDwkNetJGnNWaPqPeYhY",
    "ssn": "444411111",
    "dob": "1931-01-01"
}
```

### Replace the value with Aliased value and preserved group

Replacement parameter: `<regexp group placeholder> any text <alias placeholder>`

Route config:&#x20;

```yaml
transformer: REGEX
transformer_config: - '4313-35(?<card1>00)-(?<card2>0000)-(?<lastFour>\d{4})'
transformer_config_map:
    patterns: - '4313-35(?<card1>00)-(?<card2>0000)-(?<lastFour>\d{4})'
    replacement: '%s:${lastFour}'
```

Input:

```json
{
    "first_name": "JOHN",
    "card_number": "4313-3500-0000-1234",
    "ssn" : "444411111",
    "dob" : "1931-01-01"
}
```

Output:

```json
{
    "first_name": "JOHN",
    "card_number": "tok_mTkSAHoAvvNiFUCEiYSWtj:1234",
    "ssn": "444411111",
    "dob": "1931-01-01"
}
```

If you have any questions or trouble, please contact us at <support@vgs.io>


# Redacting Files via the HTTPS Proxy

You can redact any file through VGS HTTP proxy by sending this file in your request. For example to redact an image:

1. Convert an image into the base64 format.
2. Create JSON file with the base64 text of the image.
3. Create a new inbound route in VGS dashboard with default settings. Add the field from your file in JSON path in the filter section to redact this particular field.

![redact\_through\_http](/files/hoRHAeeMMXdWDJKF0G0A)

4. Use this curl request in order to send an image to VGS proxy:
   1. NOTE: The intended value for `<VAULT_ID>` is the **Tenant ID** (also known as *Vault ID*), beginning with prefix *tnt*.

```bash
curl https://<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com/post \
    -H "Content-type: application/json" \
    -d @ABSOLUTE_PATH_TO_JSON_FILE
```

5. To make sure request was sent successfully, monitor routes activity either with the logger widget (open by clicking `Show Logs` button) or via the [Access Logs](/vault/http-proxy/access-logger) page.&#x20;

   <figure><img src="/files/HMVfpH8WzqzSUWtqaSsC" alt=""><figcaption></figcaption></figure>

You can upload files up to 24MB in size. The [Vault API](/vault/developer-tools/apis/vault-api) supports files up to 32MB in size.


# Redacting and Revealing Headers

To work with headers set `headers["headername"]` target and `^(.*)$` RegExp.

![headers](/files/gjVBNLOp0aBhiKBziXJ0)


# Redacting and Revealing Query Parameters

To redact or reveal a query parameter data use a regex and set `uri` as a target. Check if the request was processed correctly in the [Access Logger](/vault/http-proxy/access-logger)

**Note**: pathinfo filter won't match the query parameters, that's why a RegExp is used.

![queryparameters](/files/F6uiXgJBRzgEJgEQeMLk) ![queryparameters-logger](/files/UFL1CYThTnLt5X9ElWtd)


# Performing Cryptographic Operations on Sensitive Data

Enterprise security teams and third-party APIs commonly require signing, hashing, and encryption processes when sharing sensitive data. To support these requirements, VGS allows customers to write their own Python-based operations to perform complex operations on data in transit using the [VGS Compute](/vault/developer-tools/larky).




---

[Next Page](/llms-full.txt/1)

