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.

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?