Skip to main content
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

Do not treat the synchronous SUCCESS response from Create Virtual Account as proof that the Virtual Account is ready to receive funds. It only confirms that UQPAY accepted the request for processing.

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.
  • 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 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 for the account that should receive the Virtual Account. 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.
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 and contact UQPAY support.
The webhook payload includes identifiers you should store:

Step 3: Query active Virtual Accounts

Use 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:
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.

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. 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 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 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 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.
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.

API and webhook map