Auto Top-Up Configuration
Auto top-up automatically replenishes customer wallet balances when they fall below a configurable threshold. This ensures customers can always start and complete rides without manually adding funds.
Overview
When enabled, the system monitors wallet balances and automatically charges the customer's saved payment method when their balance drops too low. This creates a seamless riding experience where customers don't need to worry about running out of funds mid-ride.
Key Features
- Automatic charging - Charges saved payment method when balance is low
- Configurable threshold - Set the trigger point for automatic top-ups
- Configurable amount - Set how much to add each time
- Dual consent required - Both operator and customer must enable
- Stripe integration - Secure off-session payments via Stripe
- Concurrent protection - Database locks prevent duplicate charges
How It Works
Wallet Balance: $4.50
Threshold: $5.00
Top-Up Amount: $15.00
1. Customer starts ride
2. System checks: $4.50 ≤ $5.00 threshold
3. Auto top-up triggered
4. Stripe charges default card $15.00
5. New balance: $19.50
6. Ride proceeds normally
Requirements
Auto top-up requires ALL of the following:
| Requirement | Who Sets It | Where |
|---|---|---|
| Subaccount enabled | Fleet operator | Dashboard Settings |
| Customer enabled | Customer | Mobile app wallet |
| Saved payment method | Customer | Mobile app |
| Stripe customer ID | Automatic | Created on first payment |
Both Must Enable
Auto top-up only works when BOTH the subaccount AND the customer have it enabled. If either disables it, automatic charging stops.
Operator Configuration
Enabling Auto Top-Up
Navigate to Settings
Go to Dashboard → Settings.
Find Payments Section
Scroll to the Payments section.
Enable Auto Top-Up
Toggle Auto Top-Up Enabled to on.
Set Threshold
Enter the Trigger Level (when to charge). Default: $5.00
Set Amount
Enter the Top-Up Amount (how much to add). Default: $15.00
Save Settings
Click Save to apply changes.
Configuration Options
Trigger Level (Threshold)
The wallet balance at which auto top-up activates.
| Setting | Behavior |
|---|---|
| $5.00 (default) | Charges when balance ≤ $5.00 |
| $10.00 | Charges when balance ≤ $10.00 |
| $2.00 | Charges when balance ≤ $2.00 |
Recommendations:
- Set threshold slightly higher than your average ride cost
- Consider your unlock fee + typical ride duration
- Higher thresholds = more frequent small charges
Top-Up Amount
How much to add to the wallet each time.
| Setting | Behavior |
|---|---|
| $15.00 (default) | Adds $15.00 per charge |
| $10.00 | Adds $10.00 per charge |
| $25.00 | Adds $25.00 per charge |
Recommendations:
- Should cover 2-4 typical rides
- Balance between convenience and transaction fees
- Higher amounts = fewer transactions
Best Practices
- Set threshold above ride cost - Ensure customers can complete at least one ride
- Balance amount vs. frequency - Higher amounts mean fewer Stripe fees
- Communicate to customers - Make sure customers know auto top-up is available
- Monitor declined charges - Check for failed auto top-ups regularly
Customer Experience
Enabling Auto Top-Up
Customers enable auto top-up in the mobile app:
- Open Wallet screen
- Tap Auto Top-Up toggle
- Confirm enablement
- Ensure a default payment method is saved
What Customers See
- Toggle to enable/disable auto top-up
- Notification when auto top-up charges occur
- Transaction history shows "Auto top-up" entries
- Current wallet balance always visible
Saved Payment Required
Customers must have a saved payment method set as default for auto top-up to work. The system uses Stripe's off-session payment capability.
When Auto Top-Up Triggers
Auto top-up is checked at these moments:
| Event | Trigger Condition |
|---|---|
| Ride start | Balance ≤ threshold |
| Ride end | Balance insufficient for ride cost |
| Wallet check | Periodic balance verification |
Ride Start Flow
1. Customer taps "Unlock" on vehicle
2. System checks wallet balance
3. If balance ≤ threshold AND auto top-up enabled:
a. Lock acquired to prevent duplicate charges
b. Stripe PaymentIntent created
c. Default payment method charged
d. Wallet balance updated
e. Lock released
4. Ride starts normally
Ride End Flow
1. Ride ends, cost calculated: $8.50
2. Current wallet: $4.00
3. Wallet insufficient, auto top-up triggered
4. $15.00 added → New balance: $19.00
5. Ride cost deducted: $19.00 - $8.50 = $10.50
6. Customer sees final balance: $10.50
Technical Details
Database Fields
Subaccounts table:
| Column | Type | Description |
|---|---|---|
auto_topup_enabled | Boolean | Subaccount has auto top-up enabled |
auto_topup_threshold_cents | Integer | Trigger level in cents |
auto_topup_amount_cents | Integer | Amount to add in cents |
Customers table:
| Column | Type | Description |
|---|---|---|
auto_topup_enabled | Boolean | Customer has opted in |
stripe_customer_id | String | Stripe customer reference |
auto_topup_lock_expires_at | Timestamp | Prevents concurrent charges |
Concurrency Protection
The system uses database locks to prevent charging customers multiple times:
- Before charging, acquire lock via
acquire_auto_topup_lockRPC - Lock has 2-minute TTL (auto-expires if process fails)
- If lock already held, wait and check if balance increased
- After charging, release lock via
release_auto_topup_lockRPC - Idempotency key prevents Stripe duplicate charges
Error Handling
| Error | System Response |
|---|---|
| Card declined | Returns error, customer notified |
| No payment method | Returns "No payment method on file" |
| Authentication required | Returns error, requires customer action |
| Lock already held | Waits for existing charge to complete |
Troubleshooting
Auto Top-Up Not Working
- Check subaccount setting - Verify
auto_topup_enabledis true in Settings - Check customer setting - Verify customer has enabled in app
- Check payment method - Customer needs a saved default card
- Check Stripe customer - Customer needs
stripe_customer_id - Check balance - May already be above threshold
Duplicate Charges
The system prevents duplicates via:
- Database lock on customer record
- Stripe idempotency keys
- Balance re-check after lock acquisition
If duplicates occur, check:
- Lock release failures in logs
- Stripe webhook processing
- Database connection issues
Failed Charges
Common reasons for failed auto top-up:
| Reason | Solution |
|---|---|
| Card expired | Customer updates card in app |
| Insufficient funds | Customer uses different card |
| Card reported lost/stolen | Customer adds new card |
| Bank decline | Customer contacts bank |
| 3D Secure required | Customer manually adds funds |
3D Secure Limitation
Auto top-up uses off-session payments which cannot handle 3D Secure challenges. If a customer's card requires authentication, they'll need to manually add funds.
Test Mode
For internal testing, the system automatically uses Stripe test mode for @levyelectric.com email addresses. This allows testing auto top-up flows without real charges.
Customer email: test@levyelectric.com
→ Uses STRIPE_TEST_SECRET_KEY
→ Test cards work (4242 4242 4242 4242)
→ No real charges processed
API Reference
Check Auto Top-Up Capability
import { canProcessAutoTopup } from '@/lib/auto-topup'
const canTopup = await canProcessAutoTopup(customerId, vehicleId)
// Returns: boolean
Process Auto Top-Up
import { processAutoTopup } from '@/lib/auto-topup'
const result = await processAutoTopup(customerId, vehicleId, skipThresholdCheck)
// Returns: { success, amountCents, error?, newWalletBalance? }
Toggle Customer Preference (Mobile API)
POST /api/mobile/payment
{
"action": "toggle-auto-topup",
"enabled": true
}
Seamless Experience
With auto top-up configured, your customers enjoy uninterrupted rides without worrying about wallet balances. The system handles replenishment automatically, reducing friction and increasing ride completion rates.