# Virtual Accounts Bank Transfer Integration Guide | EBANX Docs

> Virtual Accounts in Indonesia allow customers to complete payments by transferring funds to a unique, transaction-specific bank account number generated at checkout.

# Virtual Accounts

**Virtual Accounts** is a bank transfer payment method in **Indonesia** that allows customers to complete payments by transferring funds to a unique, transaction-specific bank account number generated at checkout. After selecting bank transfer as the payment method, customers receive a Virtual Account (VA) number and can complete the payment through their bank's mobile app, internet banking, or ATM.

By integrating Virtual Accounts, merchants can collect payments securely and efficiently through Indonesia's banking network, providing a widely adopted and trusted payment alternative for Indonesian customers who rely on bank transfers.

This guide outlines the key concepts and implementation details required to integrate Virtual Accounts via API. It covers essential steps such as creating a payment request, displaying the VA number to the customer, and monitoring the payment status.

## Requirements

- **API authentication** - All API requests must be authenticated using [JWS (JSON Web Signature)](/docs/get-started/api-authentication/jws-authentication). The legacy `integration_key` is being deprecated — if you still use it, follow the [Migration Guide](/docs/get-started/api-authentication/jws-migration) to transition to JWS. If you don't have credentials yet, complete the [Merchant Signup Form](https://www.ebanx.com/en/contact/).
- **Familiarity with EBANX Direct** - This setup follows the same general structure as other payment methods, with a few unique parameters. See [EBANX Direct](/docs/pay-in/solution/integration-methods/direct-api) for more info.

## How it works

### Web and App Flow

1. The **customer** selects Bank Transfer (Virtual Account) as the payment method during checkout.
2. A unique Virtual Account (VA) number is generated for the transaction, along with the amount and expiry time.
3. The **merchant** displays the VA number and payment instructions to the customer.
4. The **customer** completes the payment by logging into their bank app, internet banking, or visiting a bank ATM and entering the VA number.
5. The **customer** confirms the bill details and completes the necessary authentication process.
6. EBANX sends a real-time notification (webhook) to the **merchant** confirming the payment status.
7. The order status is updated to "Paid" upon receiving a successful payment notification.

> **Payment channels**
> Customers can enter the VA number in their bank's mobile app, internet banking portal, or at a bank ATM.

### Technical flow

- **Request payment** - Call the `ws/direct` endpoint with the parameters defined below.
- **Payment instructions** - In response to this request, EBANX will return a `voucher_url` containing the Virtual Account number and payment details for the customer.
- **Customer completes the payment** - The customer transfers the specified amount using the VA number. During this time, the transaction will be set on our platform with the status **pending (PE)**.
- **Payment confirmation** - Once the transaction is successful, the customer receives a confirmation on their banking app, and the merchant is updated with the transaction status.
- **EBANX notification** - EBANX sends you a [webhook](/docs/pay-in/management/status-and-retrieval/payment-notifications) notification confirming the successful transaction, allowing you to fulfill your customer's order.

- [Learn more about Payment Notifications](/docs/pay-in/management/status-and-retrieval/payment-notifications)
- [Learn more about Retrieving Payment Status](/docs/pay-in/management/status-and-retrieval/retrieve-payment)

## Instructions

Follow the steps below.

### Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.

- **Cross-border sandbox:** `https://sandbox.ebanxpay.com/ws/direct`
- **Cross-border production:** `https://api.ebanxpay.com/ws/direct`
- **Local sandbox:** `https://sandbox-local-latam.ebanxpay.com/ws/direct`
- **Local production:** `https://api-local-latam.ebanxpay.com/ws/direct`

Check the method's availability for your country and tenant in [Payment Methods by Country](/docs/pay-in/processing/payment-methods/payment-methods-overview#payment-methods-by-country). Questions about tenant and environment? Check our [API Operability](/docs/get-started/api-operability) and [API Endpoints](/docs/get-started/api-endpoints).

### Define your parameters

To create a Virtual Account payment, you need to define the parameters in your request. The following tables outline the required parameters for the payment process.

#### Basic parameters

| **Parameter**       | **Requirement** | **Description**                    |
| ------------------- | --------------- | ---------------------------------- |
| `operation`         | Required        | Set to `request`                   |
| `integration_key`   | Required        | Your EBANX integration key         |
| `payment_type_code` | Required        | Set to `virtual-account`           |
| `country`           | Required        | Set to `id` for Indonesia          |

#### Customer data

| **Parameter**  | **Requirement** | **Description**  |
| -------------- | --------------- | ---------------- |
| `name`         | Required        | Customer name    |
| `email`        | Required        | Customer email   |
| `phone_number` | Optional        | Customer phone   |

#### Charge parameters

| **Parameter**           | **Requirement** | **Description**                                                   |
| ----------------------- | --------------- | ----------------------------------------------------------------- |
| `merchant_payment_code` | Required        | Unique merchant payment code                                      |
| `currency_code`         | Required        | Set to `IDR`                                                      |
| `amount_total`          | Required        | Total amount to be charged                                        |
| `bank_details.bank_code`| Required        | Bank code for the Virtual Account (see supported banks below)     |
| `redirect_url`          | Required        | URL the customer will be redirected to after completing payment   |

#### Supported bank codes

| **Bank Code** | **Bank Name**            |
| ------------- | ------------------------ |
| `cimb`        | CIMB Niaga               |
| `bsi`         | Bank Syariah Indonesia   |
| `bca`         | BCA                      |
| `bnc`         | Bank Neo Commerce        |
| `bni`         | BNI                      |
| `mandiri`     | Mandiri                  |
| `bri`         | BRI                      |
| `btn`         | BTN                      |
| `permata`     | Permata                  |
| `danamon`     | Danamon                  |
| `bss`         | Bank Sahabat Sampoerna   |
| `maybank`     | Maybank                  |
| `sinarmas`    | Sinarmas                 |

> **Transaction limits**
> Transaction limits vary by bank and transfer type:
> | **Bank**    | **Min Amount** | **Max Amount**        | **Notes**   |
> | ----------- | -------------- | --------------------- | ----------- |
> | BCA         | IDR 10,000     | IDR 50,000,000        |             |
> | CIMB        | IDR 10,000     | IDR 50,000,000,000    |             |
> | BNI         | IDR 10,001     | IDR 50,000,000        |             |
> | BSI         | IDR 10,002     | IDR 100,000,000       |             |
> | Mandiri     | IDR 10,004     | IDR 300,000,000       | Same bank   |
> | Mandiri     | IDR 10,005     | IDR 500,000,000       | Interbank   |
> | BRI         | IDR 10,006     | IDR 50,000,000,000    | Same bank   |
> | BRI         | IDR 10,007     | IDR 500,000,000       | Interbank   |
> | Danamon     | IDR 10,008     | IDR 2,000,000,000     | Same bank   |
> | Danamon     | IDR 10,009     | IDR 200,000,000       | Interbank   |
> | Maybank     | IDR 10,010     | IDR 10,000,000,000    | Same bank   |
> | Maybank     | IDR 10,011     | IDR 200,000,000       | Interbank   |
> | Sinarmas    | IDR 10,012     | IDR 5,000,000,000     | Same bank   |
> | Sinarmas    | IDR 10,013     | IDR 50,000,000        | Interbank   |
> | Permata     | IDR 10,014     | IDR 9,999,999,999     |             |
> | BTN         | IDR 10,015     | IDR 9,999,999,999     |             |

### Payment request

Once your customer selects a bank and submits a Virtual Account payment, create a payment request using the **ws/direct** endpoint.

**Sample request**

```bash
curl -X POST \
  --location 'https://sandbox.ebanxpay.com/ws/direct' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration_key": "{{integration_key}}",
    "payment": {
        "name": "John Doe",
        "email": "john.doe@example.com",
        "country": "id",
        "payment_type_code": "virtual-account",
        "bank_details": {
            "bank_code": "{{bank_code}}"
        },
        "redirect_url": "https://merchant.example.com/callback",
        "merchant_payment_code": "{{unique_merchant_code}}",
        "currency_code": "IDR",
        "amount_total": 10000
    }
}'
```

### Payment successful response

Each request returns a response similar to the example below.

```json
{
  "payment": {
    "hash": "59acc5f00945fa382ab051651440826da7701533249b3a475",
    "country": "id",
    "merchant_payment_code": "{{unique_merchant_code}}",
    "order_number": null,
    "status": "PE",
    "status_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "open_date": "{{YYYY-MM-DD HH:mm:ss}}",
    "confirm_date": null,
    "transfer_date": null,
    "amount_br": "10000.00",
    "amount_ext": "10000.00",
    "amount_iof": "1",
    "currency_rate": "1",
    "currency_ext": "IDR",
    "due_date": "{{YYYY-MM-DD}}",
    "instalments": "1",
    "payment_type_code": "virtual-account",
    "pre_approved": false,
    "capture_available": null,
    "voucher_url": "https://sandbox.ebanxpay.com/print/voucher"
  },
  "status": "SUCCESS"
}
```

[Merchant Area](https://dashboard.ebanx.com)

> **Timeout**
> For Virtual Account payments, the timeout is 1 hour. Ensure the customer completes the payment within this time frame.

### Display Virtual Account number

Redirect your customer to the URL provided in the `voucher_url` parameter. The page will display the Virtual Account number that the customer needs to use for the bank transfer.

```json
"voucher_url": "https://sandbox.ebanxpay.com/print/voucher?hash=59acc5f00945fa382ab051651440826da7701533249b3a475"
```

Below is how the Virtual Account payment instructions page will look:

![Virtual Account payment instructions page showing VA number, payment amount, expiry date, and bank name](/img/docs/pay-in/processing/payment-methods/country-specific/indonesia/virtual-account-payment-instructions.png)

> **Sandbox behavior**
> When testing in **sandbox**, a simulator environment will be rendered to accept or decline the payment.

### Monitor payment for status changes

**Notifications**

- EBANX will send a notification whenever a payment status changes.

- Make sure your system is set up to receive notifications from EBANX for any changes in payment status.

- [Learn more about Payment Notifications](/docs/pay-in/management/status-and-retrieval/payment-notifications)

**Status**

- After receiving a notification that the status has changed, retrieve the payment status.

- When a payment is confirmed, the status will change from **pending (PE)** to **confirmed (CO)**.
  If the customer does not complete the payment, the status will eventually change to **cancelled (CA)**.

- [Learn more about Retrieving Payment Status](/docs/pay-in/management/status-and-retrieval/retrieve-payment)

### Congratulations!

You have successfully integrated **Virtual Accounts**.

For more information, refer to the [Direct API reference guide](/api-reference?api=pay-in&page=direct)

## Resources

Use the following resources when testing in your sandbox environment.
- [API Reference](/api-reference)
- [Mock Customer Data](/docs/pay-in/dev-tools/sandbox-simulation/test-customer-data)
- [Error Codes](/docs/pay-in/dev-tools/response-codes/api-error-codes)
## Still need help?

If you still have questions, you can explore the following options:

- **Merchant support:** Contact our support team at [sales.engineering@ebanx.com](mailto:sales.engineering@ebanx.com) for assistance.
- **Not a partner yet?** Complete the [Merchant Signup Form](https://business.ebanx.com/en/request-contact), and our commercial team will reach out to you.
