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

# Virtual Account API Lifecycle

> Create, track, query, and use virtual accounts for deposits through the Global Account API.

Use this guide when you create Virtual Accounts through the API instead of the Dashboard. A Virtual Account application is asynchronous: the create request is accepted first, the usable account details are delivered later, and deposits are reconciled separately after funds arrive.

## Lifecycle overview

```mermaid theme={null}
sequenceDiagram
    participant You as Your system
    participant UQPAY
    participant Payer

    You->>UQPAY: Create Virtual Account
    UQPAY-->>You: SUCCESS acknowledgement
    UQPAY-->>You: virtual.account.create
    UQPAY-->>You: virtual.account.update status=Active
    You->>UQPAY: List Virtual Accounts
    UQPAY-->>You: Active account details and capability
    Payer->>UQPAY: Send bank transfer using VA details
    UQPAY-->>You: deposit.pending / deposit.completed / deposit.compliance.rejected
    You->>UQPAY: Retrieve Deposit
```

<Warning>
  Do not treat the synchronous `SUCCESS` response from [Create Virtual Account](/global-account/v1.6/api-reference/create-virtual-account) as proof that the Virtual Account is ready to receive funds. It only confirms that UQPAY accepted the request for processing.
</Warning>

## Prerequisites

Before creating Virtual Accounts through the API:

* Complete the required onboarding and enable the Global Account product for the target account.
* Confirm that the requested currency and receiving method are available for that account. See [Supported Regions and Currencies](/global-account/v1.6/guide/supported-regions-and-currencies).
* Decide whether the Virtual Account belongs to the master account or a sub-account. For a sub-account, pass its `account_id` in the `x-on-behalf-of` header.
* Configure and test the [Virtual Account Create / Update webhook](/global-account/v1.6/webhooks/virtual-account-create-update) before sending production create requests.
* Generate a unique `x-idempotency-key` for each create request. If you also send `x-request-id`, store it because it is returned as `request_id` in the Virtual Account webhook payload.

## Step 1: Submit the create request

Call [Create Virtual Account](/global-account/v1.6/api-reference/create-virtual-account) for the account that should receive the Virtual Account.

| Input               | How to use it                                                                                                                      |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `x-on-behalf-of`    | Use this header when creating a Virtual Account for a sub-account. Omit it for the master account.                                 |
| `x-idempotency-key` | Required. Use a unique UUID so retries do not create duplicate applications.                                                       |
| `x-request-id`      | Optional. Use your own request identifier to match the create request with later webhook events.                                   |
| `currency`          | Required. Send one or more supported currency codes, separated by commas when requesting multiple currencies.                      |
| `payment_method`    | Optional. Request `LOCAL` or `SWIFT` when you need a specific receiving capability and it is supported for the requested currency. |

The API response contains `message = SUCCESS`. This means the request was accepted for processing. It does not mean account details have been issued, and you should not show payment instructions to payers yet.

## Step 2: Track provisioning status by webhook

Virtual Account creation is completed asynchronously through the [Virtual Account Create / Update webhook](/global-account/v1.6/webhooks/virtual-account-create-update).

| Event                                           | What it means                                                                                                                                 | What to do                                                                                                                  |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `virtual.account.create`                        | UQPAY accepted the application for the requested currency. The webhook data can still have `status = Processing` and incomplete bank details. | Store the event and continue waiting for an update.                                                                         |
| `virtual.account.update` with `status = Active` | The Virtual Account is ready to use. Bank details and receiving capability are available.                                                     | Call [List Virtual Accounts](/global-account/v1.6/api-reference/list-virtual-accounts) and save the latest account details. |
| `virtual.account.closed`                        | The Virtual Account has been closed.                                                                                                          | Stop showing the account details to payers and prevent new collection instructions from using it.                           |

<Warning>
  No webhook is sent if the Virtual Account application fails. If you do not receive an Active update within the expected window, check [List Virtual Accounts](/global-account/v1.6/api-reference/list-virtual-accounts) and contact UQPAY support.
</Warning>

The webhook payload includes identifiers you should store:

| Field                       | Why it matters                                                              |
| --------------------------- | --------------------------------------------------------------------------- |
| `account_id`                | Identifies the master account or sub-account that owns the Virtual Account. |
| `account_bank_id`           | Identifies the issued Virtual Account bank detail record.                   |
| `account_number`            | The account number or IBAN shown to the payer after activation.             |
| `currency`                  | The receiving currency.                                                     |
| `capability.payment_method` | The receiving method for this bank detail record.                           |
| `request_id`                | Your `x-request-id`, when provided in the create request.                   |

## Step 3: Query active Virtual Accounts

Use [List Virtual Accounts](/global-account/v1.6/api-reference/list-virtual-accounts) after the Active webhook, during service startup, and whenever you need to refresh your stored account details.

You can filter by `currency`. When querying for a sub-account, pass the same `x-on-behalf-of` value you used when creating or operating on behalf of that sub-account.

Store the returned details in your system:

| Field                                              | Use                                                                      |
| -------------------------------------------------- | ------------------------------------------------------------------------ |
| `account_bank_id`                                  | Stable identifier for the bank detail record.                            |
| `account_holder`                                   | Account holder name shown in payment instructions.                       |
| `account_number`                                   | Account number or IBAN shown to the payer.                               |
| `country_code`                                     | Country where the account is held.                                       |
| `currency`                                         | Currency the account can receive.                                        |
| `bank_name` and `bank_address`                     | Bank details for payer instructions.                                     |
| `clearing_system.type` and `clearing_system.value` | Routing information such as local clearing code or BIC/SWIFT identifier. |
| `capability.payment_method`                        | Whether the account receives via `LOCAL` or `SWIFT`.                     |
| `status`                                           | Only use active accounts for new payer instructions.                     |

<Note>
  Webhook status values and List API status values use different casing. For example, the webhook can send `Active`, while the List API can return `ACTIVE`. Normalize status values in your own system before applying business logic.
</Note>

## Step 4: Use the receiving capability

Each returned Virtual Account bank detail record has a receiving capability. Use the payer instructions that match the expected payment rail.

| Capability | Use it for                                                    | Implementation notes                                                                                                                                                                   |
| ---------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LOCAL`    | Domestic or local clearing transfers in the supported market. | Show the local account number and `clearing_system` details returned by the API. Do not assume the same account can receive SWIFT transfers unless a SWIFT-capable record is returned. |
| `SWIFT`    | International bank transfers through the SWIFT network.       | Show the SWIFT-capable account details returned by the API. Make sure the payer uses the currency and bank details exactly as provided.                                                |

If you request a currency that supports both local and SWIFT receiving methods, treat each returned bank detail record independently. A payer should receive instructions for the capability you intend them to use.

## Step 5: Reconcile deposits against Virtual Accounts

A Virtual Account identifies where funds should be sent. A [Deposit](/global-account/v1.6/guide/deposit) is the transaction record created when funds arrive and are processed.

For reconciliation:

1. Store the Virtual Account mapping when the account becomes active.
2. Listen for [Deposit Status](/global-account/v1.6/webhooks/deposit-pending-rejected-completed) webhook events.
3. Use the webhook `account_id` as `x-on-behalf-of` when retrieving the deposit for a sub-account.
4. Call [Retrieve Deposit](/global-account/v1.6/api-reference/retrieve-deposit) with the `deposit_id`.
5. Match the deposit response back to your Virtual Account mapping using `receiver_account_number`, `currency`, and the owning `account_id`. Use sender details and `deposit_reference` as additional reconciliation signals when available.

<Tip>
  Cache the Virtual Account mapping after activation. Deposit webhooks identify the receiving account and deposit transaction; keeping this mapping helps you match deposits to the right Virtual Account, sub-account, and receiving method without re-querying the Virtual Account list during every reconciliation.
</Tip>

## API and webhook map

| Need                                 | Public API / documentation                                                                                                                    |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Submit a Virtual Account application | [Create Virtual Account](/global-account/v1.6/api-reference/create-virtual-account)                                                           |
| List issued Virtual Account details  | [List Virtual Accounts](/global-account/v1.6/api-reference/list-virtual-accounts)                                                             |
| Receive provisioning events          | [Virtual Account Create / Update webhook](/global-account/v1.6/webhooks/virtual-account-create-update)                                        |
| Track incoming funds                 | [Deposit Status webhook](/global-account/v1.6/webhooks/deposit-pending-rejected-completed)                                                    |
| Query received funds                 | [List Deposits](/global-account/v1.6/api-reference/list-deposits) and [Retrieve Deposit](/global-account/v1.6/api-reference/retrieve-deposit) |
