# Virtual Account

Create temporary bank accounts to receive payments via bank transfer. When a customer transfers money to a virtual account, the payment is automatically matched and settled to your account.

**Required permission:** `virtual_account`

## Create Virtual Account

```
POST /v1/checkout/virtual-account
```

### Authentication

Requires a **secret key** (`sk_*`).

### Request body

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `amount` | string | Yes | Expected amount in naira (e.g., `"5000.00"`) |
| `validity_minutes` | integer | No | How long the account stays active. Default: `4320` (72h). Max: `4320` |
| `amount_validation` | string | No | Amount validation rule. See [Dynamic PayID amount rules](/api/dynamic-payid#amount-validation-rules). Default: provider default |
| `metadata` | object | No | Custom key-value data stored with the account |

::: tip Settlement
Payments received on this virtual account are settled to your API key's configured settlement ledger. To change where payments are settled, update your API key's settlement configuration in the [dashboard](https://business.zevpay.ng).
:::

### Example request

::: code-group

```bash [cURL]
curl -X POST https://api.zevpaycheckout.com/v1/checkout/virtual-account \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_test_your_secret_key" \
  -d '{
    "amount": "5000.00",
    "validity_minutes": 1440,
    "metadata": {
      "order_id": "ORD-12345"
    }
  }'
```

```javascript [Node.js]
const response = await fetch(
  "https://api.zevpaycheckout.com/v1/checkout/virtual-account",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": "sk_test_your_secret_key",
    },
    body: JSON.stringify({
      amount: "5000.00",
      validity_minutes: 1440,
      metadata: { order_id: "ORD-12345" },
    }),
  }
);
const data = await response.json();
```

:::

### Response

```json
{
  "success": true,
  "data": {
    "public_id": "abc123def456ghi78",
    "account_number": "4601234567",
    "merchant_name": "My Business",
    "provider": "vfd",
    "reference": "ZVP-VA-1772906868046-d5aa1c",
    "amount": "5000.00",
    "status": "pending",
    "expires_at": "2026-03-09T12:00:00.000Z",
    "completed_at": null,
    "source": "api",
    "created_at": "2026-03-08T12:00:00.000Z"
  }
}
```

The `account_number` is the bank account number your customer should transfer to. The bank is **VFD Microfinance Bank**.

---

## List Virtual Accounts

```
GET /v1/checkout/virtual-account
```

### Query parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `page` | integer | 1 | Page number |
| `page_size` | integer | 20 | Items per page (max 100) |
| `status` | string | — | Filter: `"pending"`, `"completed"`, `"expired"`, `"cancelled"` |

### Example request

```bash
curl "https://api.zevpaycheckout.com/v1/checkout/virtual-account?status=pending&page_size=10" \
  -H "x-api-key: sk_test_your_secret_key"
```

### Response

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "public_id": "abc123def456ghi78",
        "account_number": "4601234567",
        "merchant_name": "My Business",
        "provider": "vfd",
        "reference": "ZVP-VA-1772906868046-d5aa1c",
        "amount": "5000.00",
        "status": "pending",
        "expires_at": "2026-03-09T12:00:00.000Z",
        "completed_at": null,
        "source": "api",
        "created_at": "2026-03-08T12:00:00.000Z"
      }
    ],
    "total": 1,
    "page": 1,
    "page_size": 10,
    "total_pages": 1
  }
}
```

---

## Get Virtual Account

```
GET /v1/checkout/virtual-account/:publicId
```

### Path parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `publicId` | string | Virtual account public ID |

### Example request

```bash
curl https://api.zevpaycheckout.com/v1/checkout/virtual-account/abc123def456ghi78 \
  -H "x-api-key: sk_test_your_secret_key"
```

---

## Status lifecycle

| Status | Description |
|--------|-------------|
| `pending` | Account is active and awaiting payment |
| `completed` | Payment received and settled |
| `expired` | Account expired without receiving payment |
| `cancelled` | Account creation failed at the provider |

---

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `public_id` | string | Unique public identifier |
| `account_number` | string\|null | Bank account number (assigned by provider) |
| `merchant_name` | string\|null | Your business name displayed on the account |
| `provider` | string | Banking provider (e.g., `"vfd"`) |
| `reference` | string | Unique internal reference |
| `amount` | string\|null | Expected payment amount (naira) |
| `status` | string | Account status (see [lifecycle](#status-lifecycle)) |
| `expires_at` | string\|null | ISO 8601 expiry timestamp |
| `completed_at` | string\|null | ISO 8601 completion timestamp |
| `source` | string | Creation source (`"api"`, `"dashboard"`, etc.) |
| `created_at` | string | ISO 8601 creation timestamp |

## Try it — Create Virtual Account

<ApiPlayground
  method="POST"
  endpoint="/v1/checkout/virtual-account"
  :bodyFields="[
    { name: 'amount', type: 'string', required: true, placeholder: '5000.00', description: 'Amount in naira' },
    { name: 'validity_minutes', type: 'integer', placeholder: '4320', description: 'Default: 4320 (72h)' },
    { name: 'metadata', type: 'object', placeholder: '{ &quot;order_id&quot;: &quot;ORD-12345&quot; }' },
  ]"
/>

## Try it — List Virtual Accounts

<ApiPlayground
  method="GET"
  endpoint="/v1/checkout/virtual-account"
  :queryParams="[
    { name: 'page', type: 'integer', placeholder: '1', default: '1' },
    { name: 'page_size', type: 'integer', placeholder: '20' },
    { name: 'status', type: 'select', options: [{ label: 'Pending', value: 'pending' }, { label: 'Completed', value: 'completed' }, { label: 'Expired', value: 'expired' }, { label: 'Cancelled', value: 'cancelled' }] },
  ]"
/>
