Skip to main content
A Virtual Account application is one request for bank details in one country and one currency. It can contain a LOCAL result, a SWIFT result, or both.
Updating an existing integration? Start with Upgrade Your Virtual Account Integration.
HTTP 200 from Create means the application was accepted for processing. It does not mean bank details are ready. Use only bank-detail records whose status is ACTIVE.

Before you start

  • Complete onboarding and enable Global Account for the target account.
  • Configure the Virtual Account Application Webhooks.
  • For a connected account, send its account ID in x-on-behalf-of on Create, List, and Retrieve.
  • Generate a unique x-idempotency-key for each new application.

Choose what to request

Select a country and currency to see the supported payment methods. The generated JSON can be used in Create Virtual Account.
The following list contains every supported combination when payment_method is provided. If you omit payment_method, UQPAY evaluates LOCAL and SWIFT separately for the selected country and currency.
Send LOCAL or SWIFT when you need one receiving method. Omit payment_method, or send null, an empty string, or whitespace, to evaluate both. Do not send ALL or AUTO.

Create an application

Call Create Virtual Account with one country and one currency. UQPAY removes surrounding whitespace and accepts lowercase values for country, currency, and payment_method. Omitted, null, empty, and whitespace-only nickname values are treated the same. Undocumented JSON fields are ignored. Use the same x-idempotency-key only when retrying the same request for the same account. A successful identical retry returns the original application. Reusing the key with different application input returns parameter_conflict. After HTTP 200:
  1. Store account_id and direct_id with the application so you can preserve its account hierarchy.
  2. Store application_id and public_version.
  3. Process every entry in results[] and identify it by payment_method.
  4. Continue tracking any SUBMITTED result.
  5. Do not show payment instructions until an individual bank-detail record is ACTIVE.
When both methods are evaluated, LOCAL appears before SWIFT, but your code must not depend on array position. One method can be SKIPPED while the other is SUBMITTED. A synchronous 400 means the application was not created. Do not wait for an application webhook. If every evaluated method is unavailable, Create returns one top-level error rather than an application containing only skipped results.

Track the application

Use both queries for different tasks:
  • List Virtual Account Applications finds application summaries. Results are newest first. Optional status, country, and currency filters are combined. An empty or out-of-range page returns HTTP 200 with data: [].
  • Retrieve Virtual Account Application returns the latest full details for one application. A missing application and an application owned by another account return the same HTTP 400 error.
Both responses include account_id and direct_id. Use them to associate each application with the correct account hierarchy. Use Virtual Account Application Webhooks for asynchronous changes. If a delivery is missing or appears out of order, call Retrieve and keep the highest public_version for that application_id.

Read the three status levels

Handle errors

API validation and business errors contain type, code, and message. Use code for programmatic handling. Authentication and other errors returned before the endpoint processes the request can use the common gateway error format. When a receiving method is skipped or fails, results[].error contains a code and message. It is null when no error applies.

Use issued bank details

When a result becomes COMPLETED, process every entry in virtual_accounts[]:
  • Use only records whose status is ACTIVE.
  • Treat account_bank_id as an opaque string. Store it as returned to correlate later changes to the same record.
  • Show account_holder, account_number, bank_name, bank_address, country_code, and currency exactly as returned.
  • Store clearing_system.type and clearing_system.value together and preserve both values.
  • Stop using a record as soon as its status is CLOSED.
close_reason is always present. It is "" for a non-closed record. For a closed record, it contains a reason when one was recorded and otherwise remains "". Never wait for a non-empty value before stopping use. Use List Virtual Accounts during startup or reconciliation to refresh issued bank details. This existing endpoint lists bank details, not applications.

Reconcile incoming funds

A Virtual Account provides payment instructions. A Deposit is the transaction created when funds arrive.
  1. Store the Virtual Account and owning account mapping when bank details become active.
  2. Listen for Deposit Status events.
  3. For a connected account, use the webhook account_id as x-on-behalf-of when retrieving the deposit.
  4. Call Retrieve Deposit.
  5. Match the deposit using receiver_account_number, currency, and the owning account_id. Use sender details and deposit_reference as additional signals when available.