---
title: "Generate a virtual account"
method: POST
path: "/v1/customers/{customerId}/virtual_accounts"
tags: ["Virtual Accounts"]
---

# Generate a virtual account

`POST /v1/customers/{customerId}/virtual_accounts`

## Request

- Base URL: `https://api.sandbox.alfredpay.io`
- URL: `https://api.sandbox.alfredpay.io/v1/customers/{customerId}/virtual_accounts`
- Auth: one of:
  - HTTP bearer
  - API key in header `api-key` and API key in header `api-secret`

Issues a collection instrument in the customer's own name, with ACH, wire and SWIFT coordinates.

Two things have to be true first: the customer holds the endorsement the chosen `purpose` needs, and that purpose is among the `accountPurposes` they declared at onboarding.

`purpose` is fixed at generation and decides what happens to every deposit that ever lands here. There's no way to change it later.

Idempotency is scoped to `(customerId, label)`. Repeating a label returns the account you already have. Repeating it with a different purpose is a `409`.

**Wait on** `virtual_account.activated`. See [Webhooks and events](/docs/webhooks-and-events).

## Headers

- `Idempotency-Key` string, uuid, required

## Request body

- VirtualAccountCreate
  - `purpose` 'CONVERSION' | 'BALANCE' | 'PAYMENT', required: On a virtual account it routes every deposit. On the customer profile (plural) it is the declared intent that gates which may be created.
  - `currency` 'USD' | 'HKD' | 'CNY' | 'MXN' | 'DOP' | 'COP' | 'BRL' | 'ARS' | 'CLP' | 'PEN' | 'BOB' | 'PYG' | 'USDC' | 'USDT', required: Fourteen members, reconciled to the countries a customer can be onboarded in. USDC and USDT are stablecoins and require `chain`.
  - `label` string, required: The instrument's identity. Idempotency scope is (customerId, label).

## Response `201`

Created

- VirtualAccount
  - `id` string
  - `customerId` string
  - `purpose` 'CONVERSION' | 'BALANCE' | 'PAYMENT': On a virtual account it routes every deposit. On the customer profile (plural) it is the declared intent that gates which may be created.
  - `currency` 'USD' | 'HKD' | 'CNY' | 'MXN' | 'DOP' | 'COP' | 'BRL' | 'ARS' | 'CLP' | 'PEN' | 'BOB' | 'PYG' | 'USDC' | 'USDT': Fourteen members, reconciled to the countries a customer can be onboarded in. USDC and USDT are stablecoins and require `chain`.
  - `label` string
  - `status` 'active' | 'suspended' | 'migrating' | 'closed'
  - `instructions` object
    - `beneficiary_name` string: The customer's own legal name.
    - `ach` object
      - `routing_number` string
      - `account_number` string
    - `wire` object
      - `routing_number` string
      - `account_number` string
      - `bank_name` string
      - `bank_address` string
    - `swift` object
      - `bic` string
      - `account_number` string
  - `destination` object: Fixed at creation.
    - `asset` string
    - `chain` 'SOL' | 'ETH' | 'MATIC' | 'BASE' | 'ARB' | 'OP' | 'AVAX' | 'BNB' | 'TRX' | 'XLM' | 'CELO'
  - `createdAt` string, date-time

## Other responses

- `403`: `endorsement_not_enabled`: the purpose's endorsement is not `APPROVED`, or the purpose is not among the customer's declared `accountPurposes`.
- `409`: Label already exists with a different purpose or currency.

## Changes

- **2026-11-03** `20fef4fd2ab3`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/changes/v1/customers/:customerId/virtual_accounts/post.md)

---

[API](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation.md) - [All operations](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/llms.txt) - [OpenAPI document](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/revisions/20fef4fd2ab3?raw)
