> ## Documentation Index
> Fetch the complete documentation index at: https://doc.seerbit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Virtual Account

> Reserve dedicated bank account numbers for your customers.

**Ideal for**: Giving a customer their own bank account number to pay into, again and again — wallet top-ups, recurring collections, marketplace sellers, or any case where you need to know who sent money without asking.

## Virtual account or bank transfer?

Both have the customer send money to a SeerBit-controlled bank account. The difference is **how long the account lives and who it belongs to**.

| | [Transfer](/payment-methods/transfer) | Virtual Account |
| - | - | - |
| **Account lifetime** | Generated per transaction, then discarded | Reserved for the customer, reusable indefinitely |
| **Belongs to** | One payment | One customer |
| **Created** | As part of initialising a payment | Ahead of time, via this API |
| **The amount** | Fixed — the account expects that payment | Any amount, any time |
| **Reconciliation** | Matched to the transaction it was created for | Matched to the customer the account belongs to |
| **Customer experience** | New account details every time they pay | The same account number they can save |
| **Best for** | A one-off checkout paid by transfer | Wallet funding, recurring collections, per-customer ledgers |

Use a plain [transfer](/payment-methods/transfer) when the customer is paying once at checkout. Use a virtual account when the same customer will pay repeatedly and you want every inbound payment attributed to them automatically.

## How it works

You create an account against a customer, supplying their name, email and a `reference` of your own. SeerBit returns a real bank account number at a partner bank. Give that number to the customer; anything they transfer into it is credited to you and attributed to the reference you set.

Because the account persists, you do not need to generate anything at payment time — the customer can pay whenever they like, and you match the inbound payment by the account number or your reference.

## Authentication

Virtual Account calls are authenticated with a **bearer token**, generated from your public and secret keys.

```bash theme={null}
POST https://seerbitapi.com/api/v2/encrypt/keys
```

<Card title="Authentication" icon="key" href="/authentication#bearer-token">
  How to generate the token, and which credential every other SeerBit API expects.
</Card>

## Create Virtual Account

<Badge color="blue">POST</Badge>

```bash theme={null}
https://seerbitapi.com/api/v2/virtual-accounts
```

#### Request Sample

The code snippet below shows an example request for creating a virtual account

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://seerbitapi.com/api/v2/virtual-accounts' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_ENCRYPTED_KEY' \
  --data-raw '{
      "publicKey": "YOUR_PUBLIC_KEY",
      "fullName": "Jane Smith",
      "bankVerificationNumber":"",
      "currency": "NGN",
      "country": "NG",
      "reference": "FIRST_VIRTUAl_17",
      "email": "js@emaildomain.com"
  }'
  ```

  ```javascript NODE theme={null}
  var request = require('request');
  var options = {
    method: 'POST',
    url: 'https://seerbitapi.com/api/v2/virtual-accounts',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer YOUR_ENCRYPTED_KEY',
    },
    body: JSON.stringify({
      publicKey: 'YOUR_PUBLIC_KEY',
      fullName: 'Jane Smith',
      bankVerificationNumber: '',
      currency: 'NGN',
      country: 'NG',
      reference: 'FIRST_VIRTUAl_17',
      email: 'js@emaildomain.com',
    }),
  };
  request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
  });
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://seerbitapi.com/api/v2/virtual-accounts',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS =>'{
      "publicKey": "YOUR_PUBLIC_KEY",
      "fullName": "Jane Smith",
      "bankVerificationNumber":"",
      "currency": "NGN",
      "country": "NG",
      "reference": "FIRST_VIRTUAl_17",
      "email": "js@emaildomain.com"
  }',
    CURLOPT_HTTPHEADER => array(
      'Content-Type: application/json',
      'Authorization: Bearer YOUR_ENCRYPTED_KEY'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  echo $response;
  ```
</CodeGroup>

#### Response Sample

The code snippet below shows an example response for creating a virtual account

```json theme={null}
{
  "status": "SUCCESS",
  "data": {
    "code": "S20",
    "payments": {
      "reference": "FIRST_VIRTUAl_7",
      "walletName": "SEERBIT(Business Name)",
      "bankName": " 9PAYMENT SERVICE BANK",
      "accountNumber": "Account Number"
    },
    "message": "Account created "
  }
}
```

#### Parameter description

| Name | Type | Description |
| - | - | - |
| publicKey | `string` | Your SeerBit public key, from **Settings > API Keys**. |
| fullName | `string` | Name of the customer the account is reserved for. |
| email | `string` | Customer's email address. |
| reference | `string` | Your own unique reference for this account. Use it to [retrieve](#get-virtual-account) or [delete](#delete-a-virtual-account) the account later. |
| currency | `string` | Currency of the account, e.g. `NGN`. See [currency codes](/development-resources/currency-codes/overview). |
| country | `string` | Country the account is issued in, e.g. `NG`. |
| bankVerificationNumber | `string` | The customer's BVN. May be required depending on your account configuration and the partner bank — send an empty string when it is not. |

#### Response fields

| Name | Type | Description |
| - | - | - |
| code | `string` | `00` on success. See [status codes](/development-resources/responses/seerbit-status-code). |
| payments.accountNumber | `string` | The bank account number to give the customer. This is what they pay into. |
| payments.bankName | `string` | Partner bank holding the account. |
| payments.walletName | `string` | Account name the customer will see when they transfer. |
| payments.reference | `string` | Echoes the reference you supplied. |
| payments.linkingReference | `string` | SeerBit's own identifier for the account. |

## Get Virtual Account

<Badge color="green">GET</Badge>

```bash theme={null}
https://seerbitapi.com/api/v2/virtual-accounts/{{paymentReference}}
```

#### Request Sample

The code snippet below shows an example request to get virtual account

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://seerbitapi.com/api/v2/virtual-accounts/{{paymentReference}}' \
  --header 'Authorization: Bearer YOUR_ENCRYPTION_KEY'
  ```

  ```javascript NODE theme={null}
  var request = require('request');
  var options = {
    method: 'GET',
    url: 'https://seerbitapi.com/api/v2/virtual-accounts/{{paymentReference}}',
    headers: {
      Authorization: 'Bearer YOUR_ENCRYPTION_KEY',
    },
  };
  request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
  });
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://seerbitapi.com/api/v2/virtual-accounts/{{paymentReference}}',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(
      'Authorization: Bearer YOUR_ENCRPTION_KEY'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  echo $response;
  ```
</CodeGroup>

#### Response Sample

The code snippet below shows an example response to get all created links

```json theme={null}
{
  "status": "SUCCESS",
  "data": {
    "code": "00",
    "payments": {
      "reference": "VA_1",
      "linkingReference": "9PSB641860391656618499020",
      "walletName": "SEERBIT(Business Name)",
      "wallet": "Account Number",
      "bankName": "_9PAYMENT_SERVICE_BANK",
      "accountNumber": "Account Number"
    },
    "message": ""
  }
}
```

## Delete a Virtual Account

<Badge color="red">DELETE</Badge>

```bash theme={null}
https://seerbitapi.com/api/v2/virtual-accounts/{{reference}}
```

#### Request Sample

The code snippet below shows an example request for deleting virtual account

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://seerbitapi.com/api/v2/virtual-accounts/{{reference}}' \
  --header 'Authorization: Bearer YOUR_ENCRYPTION_KEY'
  ```

  ```javascript NODE theme={null}
  var request = require('request');
  var options = {
    method: 'DEL',
    url: 'https://seerbitapi.com/api/v2/virtual-accounts/{{reference}}',
    headers: {
      Authorization: 'Bearer YOUR_ENCRYPTION_KEY',
    },
  };
  request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
  });
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://seerbitapi.com/api/v2/virtual-accounts/{{reference}}',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'DEL',
    CURLOPT_HTTPHEADER => array(
      'Authorization: Bearer YOUR_ENCRPTION_KEY'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  echo $response;
  ```
</CodeGroup>

#### Response Sample

The code snippet below shows an example response for deleting a virtual account

```json theme={null}
{
  "status": "SUCCESS",
  "data": {
    "code": "00",
    "message": "Virtual account has been deleted"
  }
}
```

## Get Payment

<Badge color="green">GET</Badge>

```bash theme={null}
https://seerbitapi.com/api/v2/virtual-accounts/YOUR_PUBLIC_KEY/{{accountNumber}}
```

#### Request Sample

The code snippet below shows an example request to get payments

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://seerbitapi.com/api/v2/virtual-accounts/YOUR_PUBLIC_KEY/{{accountNumber}}' \
  --header 'Authorization: Bearer YOUR_ENCRYPTION_KEY'
  ```

  ```javascript NODE theme={null}
  var request = require('request');
  var options = {
    method: 'GET',
    url: 'https://seerbitapi.com/api/v2/virtual-accounts/YOUR_PUBLIC_KEY/{{accountNumber}}',
    headers: {
      Authorization: 'Bearer YOUR_ENCRYPTION_KEY',
    },
  };
  request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
  });
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://seerbitapi.com/api/v2/virtual-accounts/YOUR_PUBLIC_KEY/{{accountNumber}}',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => array(
      'Authorization: Bearer YOUR_ENCRPTION_KEY'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  echo $response;
  ```
</CodeGroup>

#### Response Sample

The code snippet below shows an example response for getting a payment

```json theme={null}
{
  "status": "SUCCESS",
  "data": {
    "code": "00",
    "payload": [
      {
        "id": 14705414,
        "fullName": "Customer Name",
        "publicKey": "YOUR_PUBLIC_KEY",
        "processor": "_9PAYMENT_SERVICE_BANK",
        "paymentType": "TRANSFER",
        "shopperReference": null,
        "amount": 100.0,
        "productId": null,
        "productDescription": null,
        "email": "customeremail@gmail.com",
        "quantity": null,
        "maskedPan": null,
        "gateway": "_9PAYMENT_SERVICE_BANK",
        "gatewayMessage": "Successful",
        "gatewayCode": "00",
        "transactionRef": "GT-01",
        "gatewayRef": "100004230627104826104793084015",
        "businessName": "Business Name",
        "fee": null,
        "mode": "LIVE",
        "callbackUrl": null,
        "redirectUrl": null,
        "channelType": "transfer",
        "paymentKey": null,
        "sourceIP": null,
        "deviceType": null,
        "clientAppCode": null,
        "cardBin": null,
        "lastFourDigits": null,
        "type": null,
        "linkingreference": null,
        "country": "NG",
        "currency": "NGN",
        "smsProvider": null,
        "customerId": null,
        "internalreference": "_SBT_N7N7EU523C",
        "accountNumber": "customer account number",
        "narration": null,
        "creditAccountName": "Seerbit(Tola Sambo)",
        "transferType": "RESERVE_ACCOUNT",
        "paymentReference": "GT-01_SBT_N7N7EU523C",
        "batchId": null,
        "sessionId": null,
        "bankName": "",
        "creditAccountNumber": "4015310501",
        "bankCode": null,
        "alternatePaymentReference": null,
        "settlementCode": "00",
        "settlementMessage": "Push Successful",
        "settlementTime": "2023-06-27 11:49:37",
        "orderStatusCode": null,
        "orderStatusMessage": null,
        "status": "PUSHED",
        "mobileNumber": "404",
        "dateOfBirth": null,
        "branchPhoneNumber": null,
        "transferedAmount": 100.0,
        "scheduleId": null,
        "isCardInternational": "LOCAL",
        "reason": "Successful",
        "retry": false,
        "metaData": null,
        "event": [],
        "order": [],
        "createdAt": "2023-06-27T10:49:28.000+0000",
        "updatedAt": "2023-06-27T10:49:28.000+0000",
        "cardName": null,
        "isNigeriancard": null,
        "cardCountry": null,
        "intCurrency": null,
        "rate": null,
        "inCardProcessingFee": null,
        "intAmountCharge": null,
        "processorCode": "00",
        "processorMessage": "Successful",
        "invoiceNumber": null,
        "billId": null,
        "locationPhoneNumber": null,
        "pocketReferenceId": null,
        "transferAccountType": "STATIC",
        "bearer": "MERCHANT",
        "transLink": null,
        "vendorId": null,
        "payLinkEnvironment": null,
        "payLinkStatus": null,
        "payLinkAmount": null,
        "payLinkAdditionalData": null,
        "payLinkName": null,
        "payLinkDescription": null,
        "payLinkRedirectUrl": null,
        "payLinkSuccessMessage": null,
        "paymentLinkId": null,
        "payLinkCustomizationName": null,
        "payLinkFrequency": null,
        "payLinkIsOneTimeUse": false,
        "terminalId": null,
        "stan": null,
        "transactionComplete": null,
        "cardExpiryMonth": null,
        "cardExpiryYear": null,
        "tokenize": false
      }
    ],
    "message": "successful"
  }
}
```

## Notes

* **The account number is permanent until you delete it.** Give it to the customer once and let them save it — regenerating on every payment defeats the purpose.
* **Your `reference` is how you attribute payments.** Make it unique per customer and store it against their record, or you will not be able to tell inbound payments apart.
* **Deleting an account frees the number.** A deleted account stops accepting payments; do not delete one a customer may still pay into.
* **Payments arrive without warning.** A customer can transfer at any time, so rely on [webhooks](/online-payments/after-payments/webhook-events) rather than polling — see the virtual account transaction event.
* Accounts created with test keys only work in test mode. See [Test and live modes](/test-and-live).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.