Skip to main content

Getting Paid with Dynamic Virtual Accounts

Create flexible, non-flexible, and pass-through dynamic virtual accounts for Pay with Transfer collections.

Written by Nosa O

Dynamic virtual accounts help you collect payments by generating account numbers for specific payment flows. They are useful for checkout payments, invoices, wallet top-ups, school fees, donations, rent, and other transfer-based collections.

The main service type is:

ADMIN_CREATE_DYNAMIC_COLLECTION_ACCOUNT

Use DYNAMIC_COLLECTION_ACCOUNT_TSQ to check payment status.

Dynamic account types

Type

Best for

Amount rule

Flexible

Installments or partial payments

Set target amount and isFlexiblePayment: true.

Non-flexible

One-time full payment

Set target amount and isFlexiblePayment: false.

Pass-through

Open-ended collections, wallet top-ups, donations

Set amount: 0 and isPassThrough: true.

Amounts are in kobo.

Create a flexible account

Use flexible accounts when the payer can make multiple payments until the target amount is reached.

{
  "serviceType": "ADMIN_CREATE_DYNAMIC_COLLECTION_ACCOUNT",
  "requestRef": "DVA20260603001",
  "data": {
    "amount": 5000000,
    "isFlexiblePayment": true,
    "accountName": "School fees",
    "remittingAccounts": [
      {
        "splitPercentage": 100,
        "accountNumber": "2000000000"
      }
    ]
  }
}

Create a non-flexible account

Use non-flexible accounts when the payer must send the full amount once.

{
  "serviceType": "ADMIN_CREATE_DYNAMIC_COLLECTION_ACCOUNT",
  "requestRef": "DVA20260603002",
  "data": {
    "amount": 12500000,
    "isFlexiblePayment": false,
    "accountName": "Invoice 10045",
    "remittingAccounts": [
      {
        "splitPercentage": 100,
        "accountNumber": "2000000000"
      }
    ]
  }
}

Create a pass-through account

Use pass-through accounts when there is no fixed expected amount.

{
  "serviceType": "ADMIN_CREATE_DYNAMIC_COLLECTION_ACCOUNT",
  "requestRef": "DVA20260603003",
  "data": {
    "amount": 0,
    "isPassThrough": true,
    "accountName": "Wallet top-up"
  }
}

For pass-through accounts, accountName can be omitted. If omitted, Kuda may default the account name to the business/API profile name.

Split payments

Use remittingAccounts when incoming payments should be split across accounts.

{
  "remittingAccounts": [
    {
      "splitPercentage": 70,
      "accountNumber": "2000000000"
    },
    {
      "splitPercentage": 30,
      "accountNumber": "2000000001"
    }
  ]
}

Make sure split percentages add up to 100.

Response

A successful response includes the dynamic account number and account name.

{
  "message": "Request successful.",
  "status": true,
  "data": {
    "accountNumber": "3020000000",
    "accountName": "Invoice 10045"
  }
}

Show the returned account number to the payer with clear payment instructions.

Check payment status

Use DYNAMIC_COLLECTION_ACCOUNT_TSQ.

Send the original creation requestRef, the returned accountNumber, or both. Sending both makes reconciliation easier.

{
  "serviceType": "DYNAMIC_COLLECTION_ACCOUNT_TSQ",
  "requestRef": "DYTSQ20260603001",
  "data": {
    "accountCreationRequestRef": "DVA20260603002",
    "accountNumber": "3020000000"
  }
}

Important account-number behavior

Dynamic account numbers can be reused under some conditions. This can happen when expired account numbers return to a business-specific pool.

To avoid reconciliation issues:

  • track the creation requestRef

  • track the returned accountNumber

  • track the customer, invoice, order, or payment purpose in your own system

  • use webhooks and TSQ together for final payment confirmation

  • design your payment matching logic around references and account state, not account number alone

Recommended checkout flow

  1. Customer starts checkout.

  2. Your backend creates a dynamic account.

  3. Your app shows the account number and amount.

  4. Customer pays by transfer.

  5. Your webhook endpoint stores incoming transaction notifications.

  6. Your backend checks DYNAMIC_COLLECTION_ACCOUNT_TSQ when final confirmation is needed.

  7. Your app marks the order paid only after confirmed payment.

Common mistakes

  • Creating dynamic accounts from frontend code.

  • Not storing the creation requestRef.

  • Matching payment only by account number.

  • Treating account creation as payment confirmation.

  • Not handling partial payments for flexible accounts.

  • Not using TSQ when webhook delivery is delayed.

Did this answer your question?