McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Assigning Dedicated Virtual Accounts to Users at Signup
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Assigning Dedicated Virtual Accounts to Users at Signup

To assign a DVA at signup: create a Paystack customer when the user registers, immediately call the dedicated_account endpoint with the customer code, store the returned account number in your database, and display it to the user. Handle creation failures with a retry queue so users are not blocked from completing registration if the Paystack API is temporarily unavailable.

In this article

  1. 1. The Signup Flow
  2. 2. Making DVA Creation Non-Blocking
  3. 3. User Experience Patterns
  4. 4. BVN Validation Before DVA Creation
  5. 5. DVA Assignment at Scale
  6. 6. Stay Up to Date

The Signup Flow

app.post('/api/register', async function(req, res) {
  var email = req.body.email;
  var firstName = req.body.firstName;
  var lastName = req.body.lastName;
  var phone = req.body.phone;
  var password = req.body.password;

  // Step 1: Create the user in your database
  var user = await db.users.create({
    email: email,
    first_name: firstName,
    last_name: lastName,
    phone: phone,
    password: hashPassword(password),
    dva_status: 'pending',
  });

  // Step 2: Create Paystack customer
  try {
    var customerResponse = await fetch('https://api.paystack.co/customer', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email: email,
        first_name: firstName,
        last_name: lastName,
        phone: phone,
      }),
    });

    var customerData = await customerResponse.json();
    var customerCode = customerData.data.customer_code;

    await db.users.update(user.id, {
      paystack_customer_code: customerCode,
    });

    // Step 3: Create DVA
    var dvaResponse = await fetch('https://api.paystack.co/dedicated_account', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        customer: customerCode,
        preferred_bank: 'wema-bank',
      }),
    });

    var dvaData = await dvaResponse.json();

    if (dvaData.status) {
      await db.users.update(user.id, {
        dva_account_number: dvaData.data.account_number,
        dva_bank_name: dvaData.data.bank.name,
        dva_account_name: dvaData.data.account_name,
        dva_status: 'active',
      });
    } else {
      // DVA creation failed - queue for retry
      await retryQueue.add('create-dva', { userId: user.id, customerCode: customerCode });
    }
  } catch (err) {
    // Paystack API error - queue for retry
    await retryQueue.add('create-dva', { userId: user.id });
  }

  // Return success regardless - user can start using the app
  res.json({ success: true, userId: user.id });
});

Making DVA Creation Non-Blocking

The Paystack API call takes time and can fail. If you block the registration on DVA creation, users will see a slow signup or get errors they do not understand. The better pattern: complete registration immediately and create the DVA in the background.

// Background job processor
async function processDvaCreation(job) {
  var userId = job.data.userId;
  var user = await db.users.findById(userId);

  if (user.dva_status === 'active') {
    return; // Already created
  }

  // Ensure Paystack customer exists
  var customerCode = user.paystack_customer_code;
  if (!customerCode) {
    var customerResponse = await fetch('https://api.paystack.co/customer', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email: user.email,
        first_name: user.first_name,
        last_name: user.last_name,
        phone: user.phone,
      }),
    });

    var customerData = await customerResponse.json();
    customerCode = customerData.data.customer_code;

    await db.users.update(userId, { paystack_customer_code: customerCode });
  }

  // Create DVA
  var dvaResponse = await fetch('https://api.paystack.co/dedicated_account', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      customer: customerCode,
      preferred_bank: 'wema-bank',
    }),
  });

  var dvaData = await dvaResponse.json();

  if (dvaData.status) {
    await db.users.update(userId, {
      dva_account_number: dvaData.data.account_number,
      dva_bank_name: dvaData.data.bank.name,
      dva_account_name: dvaData.data.account_name,
      dva_status: 'active',
    });

    // Notify the user
    await sendEmail(user.email, 'dva_ready', {
      accountNumber: dvaData.data.account_number,
      bankName: dvaData.data.bank.name,
    });
  } else {
    throw new Error('DVA creation failed: ' + dvaData.message);
    // Job framework will retry automatically
  }
}

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

User Experience Patterns

Immediate display: If DVA creation succeeds during registration, show the account number on the welcome screen. "Your personal account number is 0123456789 at Wema Bank. Transfer any amount to deposit into your wallet."

Pending state: If DVA creation is still processing, show a placeholder. "Your account number is being set up. We will notify you when it is ready. You can start exploring the app in the meantime."

Ready notification: When the background job completes, send a push notification, email, or SMS. "Your account number is ready! Transfer to 0123456789 at Wema Bank to make your first deposit."

Error state: If DVA creation fails permanently after retries, show a support contact. "We could not set up your account number. Please contact support." This should be rare.

// API endpoint to check DVA status
app.get('/api/my-dva', async function(req, res) {
  var user = await db.users.findById(req.userId);

  if (user.dva_status === 'active') {
    res.json({
      ready: true,
      accountNumber: user.dva_account_number,
      bankName: user.dva_bank_name,
      accountName: user.dva_account_name,
    });
  } else {
    res.json({
      ready: false,
      message: 'Your account number is being set up. Check back shortly.',
    });
  }
});

BVN Validation Before DVA Creation

If your Paystack account requires BVN validation before DVA creation, split the signup into two phases:

  1. Phase 1: Register - Collect email, name, phone, password. Create the user account. Create the Paystack customer.
  2. Phase 2: Verify identity - Collect BVN, validate with Paystack, wait for validation webhook, then create DVA.

This means the user can start using the app immediately but cannot deposit until their identity is verified and the DVA is created. This is standard practice for fintech apps that need KYC compliance.

Show the verification status clearly in the app: "Identity verification in progress" during validation, "Verification complete" when done, and the account number once the DVA is created.

DVA Assignment at Scale

If you expect thousands of signups per day, batch DVA creation and manage rate limits:

  • Rate limiting: Paystack has API rate limits. Do not fire 1,000 DVA creation requests simultaneously. Use a queue with concurrency limits.
  • Preferred bank distribution: If one partner bank hits capacity or has issues, distribute DVA creation across available banks.
  • Monitoring: Track DVA creation success rates. If failures spike, investigate before thousands of users are stuck without account numbers.
  • Backfill: If you launch DVA support after already having users, run a migration job that creates DVAs for existing users.

For the full DVA implementation guide, see dedicated virtual accounts complete implementation. For reconciling deposits, see reconciling DVA deposits.

Stay Up to Date

DVA features and requirements evolve as Paystack adds new partner banks and updates compliance requirements.

Sign up for the McTaba newsletter to stay informed about Paystack DVA updates.

Key Takeaways

  • ✓Create the Paystack customer and DVA as part of your user registration flow. The user gets their account number right after signing up.
  • ✓Make DVA creation non-blocking. If the Paystack API is slow or down, complete the registration and create the DVA asynchronously.
  • ✓Store DVA details in your database. Do not call Paystack every time you need to show the user their account number.
  • ✓Use a retry queue for failed DVA creations. A background job retries until the DVA is created, then notifies the user.
  • ✓Handle the edge case where a user registers but the DVA creation fails permanently. Show a message like "Your account number is being set up" until it is ready.
  • ✓If BVN validation is required before DVA creation, split the flow: register first, collect BVN, validate, then create DVA.

Frequently Asked Questions

How long does DVA creation take?
DVA creation is usually instant or takes a few seconds. The Paystack API returns the account number in the response. In rare cases, there may be a delay if the partner bank system is under load.
Can I create DVAs for users who signed up before I added DVA support?
Yes. Run a migration script that creates Paystack customers and DVAs for existing users. Process them in batches with delays between batches to respect rate limits.
What if a user changes their email or name after signup?
The DVA account name is set at creation time based on the customer name you provided. Changing the name on your platform does not automatically update the DVA account name. You may need to update the Paystack customer record separately.
Can I let the user choose which bank their DVA is at?
Yes. You can offer a choice of preferred_bank values (e.g., wema-bank, providus-bank) during signup and pass the selection to the DVA creation call. Not all partner banks may be available in all regions.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Accepting Payments with Paystack: Complete Guide

Everything you need to accept your first payment with Paystack: choosing between Initialize Transaction and the Charge API, handling amounts in kobo, attaching metadata, setting callback URLs, and designing transaction references that keep your system clean.

Read more

Paystack Metadata: Passing Custom Data Through a Transaction

Paystack metadata lets you attach arbitrary JSON data to a transaction that flows through the entire lifecycle: from initialization to verification to webhooks. This guide shows you what to put in metadata, how to structure it for different use cases, and the limits you need to stay within.

Read more

Paystack Product API for Simple Storefronts

The Paystack Product API lets you create products with names, prices, and descriptions, then generate payment links for each one. For simple storefronts selling a handful of products, this is faster than building a full e-commerce backend. This guide covers creating products, linking them to payment pages, and knowing when to outgrow this approach.

Read more

Building a Wallet Top-Up Flow on Paystack

A step-by-step guide to building wallet top-up flows with Paystack. Initialize payment, handle webhooks, credit wallets safely, enforce minimum amounts, and prevent double-crediting in production.

Read more

Storing Raw Paystack Webhook Payloads for Audit

Store every raw Paystack webhook payload before processing it. This gives you an audit trail for compliance, a debugging tool for production issues, and a safety net for replaying failed events. Covers database schema, store-then-process pattern, retention policies, and querying for investigations.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.