> For the complete documentation index, see [llms.txt](https://docs.verygoodsecurity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verygoodsecurity.com/cmp/platform/vgs-for-platforms-multi-mid-implementation-guide.md).

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

## 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/platform/overview.md) 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.md) 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.md).

***

### 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.md).

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.

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verygoodsecurity.com/cmp/platform/vgs-for-platforms-multi-mid-implementation-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
