What are Customer Wallets?
Think of customer wallets as digital piggy banks for your users. Every customer gets one automatically when you create their account. You can use these wallets to:
Track credit balances in USD and INR
Build API credit systems like OpenAI or Claude
Create prepaid billing where customers buy credits upfront
Handle refunds as wallet credits instead of cash
Manage complex billing with detailed transaction history
Every customer automatically gets a wallet when you create their account. Wallets support USD and INR currencies with separate balances for each.
How It Works
Customer wallets are simple: they hold money (credits) that customers can spend on your services. When a customer makes a purchase, their wallet balance is checked first, and any available credits are used before charging their payment method.
Automatic Setup
When you create a new customer, Dodo Payments automatically creates a wallet with zero balance. It’s ready to use immediately through our API.
Multi-Currency Support
Each wallet can hold balances in different currencies:
Balance in US Dollars (stored in cents)
Balance in Indian Rupees (stored in paise)
Currently, only USD and INR balances are available. More currencies coming soon.
Working with Wallets
Check Customer Balances
See how much credit a customer has across all currencies. Perfect for checking if they have enough funds before processing a purchase.
Get Customer Wallet Balances Check a customer’s wallet credit balances in all supported currencies.
Add or Remove Credits
Give customers credits (like welcome bonuses) or deduct credits (like usage charges). You can add reasons for each transaction to keep track of what happened.
Create Customer Wallet Ledger Entry Add or remove credits from a customer’s wallet.
View Transaction History
See every credit and debit transaction for a customer. Great for debugging billing issues or showing customers their spending history.
List Customer Wallet Ledger Entries View every credit and debit transaction for a customer.
Real-World Examples
API Credit System (Like OpenAI)
Build a system where customers buy credits and spend them on API calls:
// Give new customers welcome credits
async function giveWelcomeCredits ( customerId ) {
await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: 10000 , // $100 in cents
currency: 'USD' ,
entry_type: 'credit' ,
reason: 'Welcome bonus - 100 API credits' ,
idempotency_key: `welcome_ ${ customerId } _ ${ Date . now () } `
});
}
// Charge customers for API usage
async function chargeForApiUsage ( customerId , usageCost ) {
try {
await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: usageCost , // Cost in cents
currency: 'USD' ,
entry_type: 'debit' ,
reason: `API usage - ${ usageCost } credits consumed` ,
idempotency_key: `usage_ ${ customerId } _ ${ Date . now () } `
});
} catch ( error ) {
if ( error . status === 400 ) {
console . log ( 'Customer needs to buy more credits' );
}
}
}
Prepaid Billing System
Let customers buy credits upfront and spend them over time:
Welcome New Customers
Give new customers some free credits to get started. await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: 5000 , // $50 welcome bonus
currency: 'USD' ,
entry_type: 'credit' ,
reason: 'Welcome bonus for new customer' ,
idempotency_key: `welcome_ ${ customerId } `
});
Handle Credit Purchases
When customers buy credits, add them to their wallet. await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: purchaseAmount , // Amount paid in cents
currency: 'USD' ,
entry_type: 'credit' ,
reason: `Credit purchase - ${ purchaseAmount } credits` ,
idempotency_key: `purchase_ ${ paymentId } `
});
Charge for Usage
Deduct credits when customers use your service. await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: usageCost ,
currency: 'USD' ,
entry_type: 'debit' ,
reason: `Service usage - ${ usageCost } credits` ,
idempotency_key: `usage_ ${ usageId } `
});
Monitor Balances
Check if customers are running low on credits. const wallets = await client . customers . wallets . list ( customerId );
const usdWallet = wallets . items . find ( w => w . currency === 'USD' );
const balance = usdWallet . balance ;
if ( balance < 1000 ) { // Less than $10
// Send low balance notification
await sendLowBalanceNotification ( customerId , balance );
}
Multi-Currency Support
Handle customers in different countries:
Give USD credits to US-based customers. await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: 20000 , // $200 in cents
currency: 'USD' ,
entry_type: 'credit' ,
reason: 'USD credit purchase' ,
idempotency_key: `usd_purchase_ ${ paymentId } `
});
Give INR credits to Indian customers. await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: 1500000 , // ₹15,000 in paise
currency: 'INR' ,
entry_type: 'credit' ,
reason: 'INR credit purchase' ,
idempotency_key: `inr_purchase_ ${ paymentId } `
});
Best Practices
Prevent Duplicate Transactions
Use idempotency keys to make sure you don’t accidentally charge customers twice for the same thing:
async function addCreditsSafely ( customerId , amount , reason ) {
const idempotencyKey = ` ${ reason } _ ${ customerId } _ ${ Date . now () } ` ;
try {
const result = await client . customers . wallets . ledgerEntries . create ( customerId , {
amount: amount ,
currency: 'USD' ,
entry_type: 'credit' ,
reason: reason ,
idempotency_key: idempotencyKey
});
return { success: true , wallet: result };
} catch ( error ) {
if ( error . status === 400 && error . message . includes ( 'Insufficient balance' )) {
return { success: false , error: 'INSUFFICIENT_BALANCE' };
}
if ( error . status === 409 ) {
// Transaction already processed
return { success: true , wallet: null , duplicate: true };
}
throw error ;
}
}
Check Balances Before Charging
Always verify customers have enough credits before processing expensive operations:
async function checkBalanceBeforeOperation ( customerId , requiredAmount ) {
const wallets = await client . customers . wallets . list ( customerId );
const usdWallet = wallets . items . find ( w => w . currency === 'USD' );
if ( ! usdWallet || usdWallet . balance < requiredAmount ) {
throw new Error ( 'Not enough credits for this operation' );
}
return usdWallet . balance ;
}
What’s Coming Next
These features are planned for future releases:
Credit Expiration : Set credits to expire after a certain time
Better Analytics : Detailed spending reports and usage insights
More Webhooks : Real-time notifications for balance changes and low credits
Start simple with basic credit/debit operations, then add more complex features as your business grows.