---
name: cas-virtual-account
description: "Integrate Cas Virtual Account (scopes: virtual_account): integration steps, the APIs to call and the pre-production checklist."
---

# Cas — Virtual Account

> Source: https://cas.so/en/product/virtual-account · Markdown: https://cas.so/en/product/virtual-account.md

_This skill is generated from the Cas documentation. When you need details (schemas, error codes, examples), fetch the latest Markdown from the links below instead of guessing._

## When to use this skill

When integrating, extending or debugging Cas **Virtual Account** in your system.

## Scopes

`virtual_account`

## Integration flow

Below are the steps to integrate Virtual Account into your product.

1. Create a grant [/grant/token](https://cas.so/en/general/api/grant/create.md) with `scopes` set to `virtual_account`,  
   `virtualAccountNumber` configured based on the structure provided by Cas, and `fiServiceId` being the financial service code registered for this VA.
   - **virtualAccountNumber**: will be configured specifically for each application and corresponding financial service.
   - **fiServiceId**: you can call the API [/fi-services](https://cas.so/en/general/api/institutions/get-fi-services.md) to retrieve this information.
   - **user** (optional): the customer information already stored in your system, used to prefill the linking form
     on Cas Link and to help verify the account information. [See details](#user-info)

2. Open Cas Link interface using the `grantToken` returned in the previous step. [See details](https://cas.so/en/general/link.md)

3. After the user completes authentication, your frontend will receive a `publicToken`. Use this token to obtain the accessToken for the grant.

4. After getting the `accessToken`, call the [Get Virtual Account Identity API](https://cas.so/en/general/api/get-virtual-account-identity.md) to verify account details and begin adding it to your system.

5. If the VA is not valid in your system, call the API [/grant/remove](https://cas.so/en/general/api/grant/remove.md) to revoke the grant.

#### Customer information (`user`) {#user-info}

`user` is an **optional** field when creating a grant. If your system already stores the customer's information, send it so that Cas Link can:

- **Prefill the linking form**: Cas Link fills in the account holder name, identification number, phone number and email,
so the user does not have to re-enter what you already have.
- **Help verify the account**: this information is sent along when Cas Link checks the account with the financial service,
which surfaces early any case where the account registering the Virtual Account does not match the customer in your system.

| Field | Type | Description |
| --- | --- | --- |
| `legalName` | string | Account holder name (individual) |
| `idNumber` | string | Personal identification number (ID card) of the account holder |
| `companyName` | string | Company name |
| `companyLegalId` | string | Tax code / business registration number |
| `mobileNumber` | string | Phone number registered with the bank |
| `email` | string | Customer email |

:::note
Depending on whether the financial service is of type **personal** or **enterprise**, send either
`legalName`/`idNumber` or `companyName`/`companyLegalId`. Any field you omit is left blank for the user to fill in.
:::

## APIs used in this flow

- [Create grant token](https://cas.so/en/general/api/grant/create.md)
- [List of Financial Services](https://cas.so/en/general/api/institutions/get-fi-services.md)
- [Virtual Account](https://cas.so/en/general/api/get-virtual-account-identity.md)
- [Remove Grant](https://cas.so/en/general/api/grant/remove.md)
- [Exchange public token for an access token](https://cas.so/en/general/api/grant/exchange.md)

## Read before writing code

- [Cas core](https://cas.so/en/skills/cas-core/SKILL.md)
- [Cas Link](https://cas.so/en/general/link.md)
- [Webhook](https://cas.so/en/general/api/webhook.md)
- [Errors](https://cas.so/en/errors.md)

## Rules you must follow when writing code

- `clientId` / `secretKey` live on the server in environment variables only — never ship them to a client, never commit them.
- Request only the `scopes` the product needs; extra scopes mean extra cost and risk.
- Avoid duplicate grants: check your database for a live grant before opening Cas Link again.
- Store `accessToken` and `grantId` encrypted and linked to your user; one user may hold several grants. Never surface these values in the UI.
- Log `requestId` (on every response) and `grantId` (on grant-related responses) for every call — this is what Cas support needs to trace an issue.
- Every API call needs a timeout and backoff retry for transient failures; never blindly retry money-moving calls (use your own idempotency key).
- Webhooks: accept them only from Cas IPs, return 2xx fast and process asynchronously, and make handling idempotent — deliveries can repeat or arrive out of order.
- Handle `GRANT_LOGIN_REQUIRED` by reopening Cas Link in Update mode instead of making the user relink from scratch.
- Handle `GRANT` webhooks: `USER_PERMISSION_REVOKED`, `GRANT_DELETED`, `GRANT_PAUSED`, `DEFAULT_UPDATE` — reflect the link state in your system.
- Call `/grant/remove` when a user unlinks in your app, and handle the OTP-verification branch.
- Run the whole flow on `https://sandbox.bankhub.dev` first; switch to `https://production.bankhub.dev` together with the production secrets.

## Before going to production

Verify against the **entire** production checklist: https://cas.so/en/launch-checklist.md

For every checklist item, point at the code (file path + line) that proves it is handled, or state why it does not apply. Never tick an item without evidence.

## Other Cas skills

Full catalogue (use it to add more Cas products later):

https://cas.so/en/skills/index.json
