---
title: "Create a virtual account"
method: POST
path: "/api/virtual-account"
tags: ["Virtual Accounts"]
---

# Create a virtual account

`POST /api/virtual-account`

Provisions a new virtual account for the authenticated merchant in the requested deposit currency. EUR creates an IBAN/BIC that settles to EURC on Base, USD creates an ACH account number/routing number that settles to USDC on Base. When `X-On-Behalf-Of` is set, the virtual account is provisioned for the targeted sub-merchant.

A merchant can hold at most one virtual account per currency. The merchant must already have a custodial wallet and a dedicated provider customer (otherwise the request is rejected).

## Request body

- CreateVirtualAccountDto
  - `depositCurrency` 'usd' | 'eur', required — Currency in which funds will be deposited to this virtual account. `eur` provisions an IBAN/BIC and settles to EURC; `usd` provisions an ACH account number/routing number and settles to USDC.

## Response `201`

Virtual account created successfully

- VirtualAccountResponseDto
  - `id` string, required — Unique identifier of the virtual account.
  - `depositCurrency` 'usd' | 'eur', required — Currency in which funds must be deposited to this virtual account.
  - `countryCode` string, required — ISO-3166 alpha-2 country code derived from the deposit instructions. For EUR accounts this is taken from the IBAN prefix; USD accounts default to `US`.
  - `iban` string, nullable — IBAN of the virtual account. Only set for EUR virtual accounts.
  - `bic` string, nullable — BIC of the virtual account. Only set for EUR virtual accounts.
  - `accountNumber` string, nullable — Bank account number of the virtual account. Only set for USD virtual accounts.
  - `routingNumber` string, nullable — Bank routing number of the virtual account. Only set for USD virtual accounts.
  - `accountOwnerName` string, nullable — Name of the account owner / beneficiary.
  - `bankName` string, nullable — Name of the bank holding the virtual account.
  - `bankAddress` string, nullable — Address of the bank holding the virtual account.
  - `beneficiaryAddress` string, nullable — Address of the beneficiary. Only set for USD virtual accounts.
  - `externalId` string, required — Identifier of the virtual account at the underlying provider.
  - `userId` string, required — Identifier of the merchant owning this virtual account.
  - `createdAt` string, date-time, required — Date the virtual account was created.
  - `updatedAt` string, date-time, required — Date the virtual account was last updated.

## Other responses

- `400` — Merchant already has a virtual account for this currency, has no customer ID, or has no custodial wallet
- `401` — Unauthorized - Invalid API key
- `404` — Merchant not found

---

[API](https://skmtc.dev/inflowpay/apis/inflow-api.md) · [All operations](https://skmtc.dev/inflowpay/apis/inflow-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/inflowpay/inflow-api/revisions/3012dd3dd14a/schema)
