Module 5: Funding Virtual Cards
🧠 Learning Objectives
By the end of this module, you’ll be able to:
Understand how prepaid virtual card funding works
Know what assets can be used to fund cards
Learn how to combine card registration, issuance, and funding into one clean flow
Handle common edge cases (errors, fees, FX behavior)
What Does “Funding a Virtual Card” Mean?
Funding is the act of preloading money onto a virtual card. Since virtual cards are prepaid by design, they must be funded before use.
Think of it like putting money into a secure digital envelope that only works on the internet.
The money typically comes from:
A fiat wallet (NGN, GHS, ZAR, etc.)
A stablecoin balance (e.g. USDT)
A treasury float controlled by your platform
How Funding Works (Conceptually)
Here’s the typical flow:
Supported Funding Assets
Asset Type | Examples | Auto-Converted to |
---|---|---|
Stablecoins | USDT (TRC20/ERC20), USDC | USD |
Bitcoin | BTC | USD |
Most virtual card systems (including Bitnob) handle automatic FX conversion. You don’t need to fund cards in native USD — it’s abstracted behind the scenes.
Top-Up Rules and Limits
Rule | Value (Example) |
---|---|
Minimum top-up | $3 |
Maximum per top-up | $2,500 |
Maximum card balance | $50,000 |
Flat top-up fee | $1 (per up to $100) |
FX markup (if applicable) | Varies per platform |
These limits help control risk and fraud. They’re also adjustable based on business model.
Full Flow: Register → Issue → Fund
Let’s now walk through the combined MVP flow:
Step 1: Register the Card User
POST /virtualcards/registercarduser
➡ Store the returned card_user_id
.
Step 2: Create a Card for the User
POST /virtualcards/createcard
➡ You’ll receive card metadata (card ID
, masked PAN, expiry, etc.) ➡ Store cardId
securely.
🔹 Step 3: Fund the Card
POST /virtualcards/topup
➡ Response includes status, exchange rate, new card balance.
What to Show the User
Step | UX Element |
---|---|
Register | No UI shown — background action |
Create | Show virtual card details (one time only) |
Fund | Show balance immediately, with success banner |
Failed Top-Up | Display failure reason (e.g. insufficient wallet balance) and retry CTA |
Common Funding Errors
Error | Reason |
---|---|
insufficient_funds | Wallet doesn’t have enough to cover top-up + fees |
card_not_active | You tried funding a frozen or terminated card |
invalid_card_id | The cardId doesn’t exist or doesn’t belong to your account |
rate_expired | Market price changed; retry with a fresh quote (if rate locking used) |
Funding Use Cases
Use Case | Pattern |
---|---|
User-triggered top-up | Let users tap “Add Funds” manually in UI |
Auto-fund after payout | When user receives crypto or fiat payment, auto-top-up a card |
Budgeted card issuance | Top-up the card with $200 monthly allowance |
Pay-as-you-spend | Top-up in real time based on transaction attempt (advanced) |
Best Practices
Practice | Why |
---|---|
Show current card balance in UI | Helps users understand availability before spending |
Validate card status before funding | Prevent wasteful operations and stuck funds |
Show fee breakdown and FX conversion | Builds transparency and trust |
Always log top-up reference IDs | Helps with reconciliation and dispute handling |
Use webhooks to confirm top-up success | Never assume success from just a 200 response |
Recap Exercise
You're building an app that gives each new user a $50 shopping card after KYC.
Sketch out your backend flow in pseudocode or sequence:
Register user
Issue card
Fund with $50 from marketing wallet
Display card
Listen to virtualcard.topup.success
webhook
This is your basic card distribution engine.
✅ Key Takeaways
Virtual cards must be funded before use — they’re not credit-based
Most systems support funding from crypto, fiat, or wallet balances
You can combine registration, issuance, and top-up into a smooth experience
Design your UI and backend to show status clearly, handle errors, and listen to webhooks