Skip to main content

Top Up Dedicated Funds Card

Overview

Use this endpoint to add funds to a Dedicated Funds Card from your budget account. This endpoint transfers a specified amount from your budget balance to the card's independent balance, making the funds immediately available for spending on that card.

NOTE: This API is offered on a client-by-client approval basis. Speak to your account manager to check eligibility.

IMPORTANT: This endpoint only works for Dedicated Funds Cards. Shared Funds Cards do not require top-ups as they draw from budget accounts directly.

Resource Access

Production (api.ahrvo.network)

POST https://api.ahrvo.network/card/issuance/api/issuing/card/v2/funding/top-up

Staging (gateway.ahrvo.network)

POST https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/funding/top-up

Request Headers

HeaderValueRequiredDescription
Acceptapplication/jsonYesContent type for the response
Content-Typeapplication/jsonYesContent type of the request body
AuthorizationBearer {access_token}YesBearer token for authentication
x-api-keyAPI KeyYesAPI key for authentication

Request Body

FieldTypeRequiredDescription
unique_order_idstringYesTop-up order ID provided by you for idempotency. Character limit: 36
card_idstringYesA unique ID of the card to top up
amountstringYesMonetary amount expressed in USD (e.g., "10.45")

Request Example

{
"card_id": "card2020092710410645531",
"amount": "10.45",
"unique_order_id": "1cc24f5b-5dda-4c2f-8811-df2047469f9f"
}

Response

Success Response (200 OK)

{
"code": "SUCCESS",
"data": {
"record_id": "coi202511211358115253"
}
}

Response Fields

FieldTypeDescription
codestringStatus string indicating the result. "SUCCESS" refers to a successful top-up initiation
dataobjectResponse data object
data.record_idstringA unique ID of the top-up record generated by PingPong

Error Responses

  • 400 Bad Request: Invalid parameters, insufficient budget balance, or duplicate unique_order_id
  • 401 Unauthorized: Invalid or missing authentication token
  • 403 Forbidden: Card issuance feature not enabled for this account
  • 404 Not Found: Card does not exist

Code Examples

cURL

curl -X POST \
'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/funding/top-up' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{
"card_id": "card2020092710410645531",
"amount": "100.00",
"unique_order_id": "1cc24f5b-5dda-4c2f-8811-df2047469f9f"
}'

Python

import requests
import uuid

url = "https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/funding/top-up"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"card_id": "card2020092710410645531",
"amount": "100.00",
"unique_order_id": str(uuid.uuid4())
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
data = result['data']

print("Card Top-Up Successful!")
print(f" Record ID: {data['record_id']}")
print(f" Amount: ${payload['amount']}")
print(f" Card ID: {payload['card_id']}")
else:
print(f"Failed to top up card: {result}")

JavaScript (Node.js)

const axios = require('axios');
const { v4: uuidv4 } = require('uuid');

const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/funding/top-up';
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const payload = {
card_id: 'card2020092710410645531',
amount: '100.00',
unique_order_id: uuidv4()
};

axios.post(url, payload, { headers })
.then(response => {
const result = response.data;

if (result.code === 'SUCCESS') {
const data = result.data;

console.log('Card Top-Up Successful!');
console.log(` Record ID: ${data.record_id}`);
console.log(` Amount: $${payload.amount}`);
console.log(` Card ID: ${payload.card_id}`);
}
})
.catch(error => {
console.error('Failed to top up card:', error.response.data);
});

Usage Notes

  • Idempotency: Use unique unique_order_id values to prevent duplicate top-ups. The same unique_order_id cannot be used twice
  • Immediate Availability: Funds are typically available on the card within seconds
  • Budget Balance: Ensure your budget account has sufficient balance before initiating a top-up
  • USD Only: All amounts must be in USD with exactly 2 decimal places
  • Record Tracking: Save the returned record_id to track the top-up in funding orders
  • Dedicated Funds Only: This endpoint only works for Dedicated Funds Cards

Common Use Cases

Manual Card Top-Up

Top up a specific card with a fixed amount:

def top_up_card(card_id, amount):
"""
Top up a Dedicated Funds Card

Args:
card_id: Card ID to top up
amount: Amount in USD (e.g., 100.00)
"""
import uuid

print(f"\nTopping up card {card_id} with ${amount:.2f}...\n")

# Generate unique order ID for idempotency
unique_order_id = str(uuid.uuid4())

payload = {
"card_id": card_id,
"amount": f"{amount:.2f}",
"unique_order_id": unique_order_id
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
data = result['data']

print("✓ Top-Up Successful!")
print(f" Record ID: {data['record_id']}")
print(f" Amount: ${amount:.2f}")
print(f" Order ID: {unique_order_id}")

# Query updated balance
balance_response = query_card_balance(card_id)
if balance_response['code'] == 'SUCCESS':
new_balance = balance_response['data']['available_balance']
print(f" New Balance: ${new_balance}")

return {
'success': True,
'record_id': data['record_id'],
'amount': amount,
'order_id': unique_order_id
}
else:
print(f"✗ Top-Up Failed: {result}")
return {
'success': False,
'error': result
}

# Example usage
result = top_up_card('card2020092710410645531', 500.00)

if result['success']:
print(f"\nCard topped up successfully. Record ID: {result['record_id']}")
else:
print(f"\nFailed to top up card")

Automated Low Balance Top-Up

Automatically top up cards when balance falls below threshold:

async function autoTopUpOnLowBalance(cardId, thresholdAmount, topUpAmount) {
console.log(`\n=== Automated Top-Up Check ===`);
console.log(`Card: ${cardId}`);
console.log(`Threshold: $${thresholdAmount.toFixed(2)}`);
console.log(`Top-Up Amount: $${topUpAmount.toFixed(2)}\n`);

try {
// Check current balance
const balanceResponse = await queryCardBalance(cardId);

if (balanceResponse.code === 'SUCCESS') {
const currentBalance = parseFloat(balanceResponse.data.available_balance);
const cardNumber = balanceResponse.data.card_number;

console.log(`Current Balance: $${currentBalance.toFixed(2)}`);

if (currentBalance < thresholdAmount) {
console.log(`⚠️ Balance below threshold ($${thresholdAmount.toFixed(2)})`);
console.log(`Initiating automatic top-up...\n`);

// Generate unique order ID
const { v4: uuidv4 } = require('uuid');
const uniqueOrderId = uuidv4();

// Execute top-up
const topUpPayload = {
card_id: cardId,
amount: topUpAmount.toFixed(2),
unique_order_id: uniqueOrderId
};

const topUpResponse = await topUpCard(topUpPayload);

if (topUpResponse.code === 'SUCCESS') {
const newBalance = currentBalance + topUpAmount;

console.log('✓ Automatic Top-Up Successful!');
console.log(` Card: ${cardNumber}`);
console.log(` Previous Balance: $${currentBalance.toFixed(2)}`);
console.log(` Top-Up Amount: $${topUpAmount.toFixed(2)}`);
console.log(` New Balance: $${newBalance.toFixed(2)}`);
console.log(` Record ID: ${topUpResponse.data.record_id}`);

// Send notification
await sendTopUpNotification(cardNumber, topUpAmount, newBalance);

return {
topped_up: true,
record_id: topUpResponse.data.record_id,
previous_balance: currentBalance,
new_balance: newBalance
};
} else {
console.log('✗ Top-Up Failed:', topUpResponse);
return {
topped_up: false,
error: topUpResponse
};
}
} else {
console.log('✓ Balance above threshold - no top-up needed');
return {
topped_up: false,
reason: 'balance_sufficient',
current_balance: currentBalance
};
}
} else {
console.log('✗ Failed to check balance:', balanceResponse);
return {
topped_up: false,
error: balanceResponse
};
}
} catch (error) {
console.error('Error in auto top-up:', error.message);
return {
topped_up: false,
error: error.message
};
}
}

async function sendTopUpNotification(cardNumber, amount, newBalance) {
console.log(` 📧 Notification sent: Card ${cardNumber} topped up with $${amount.toFixed(2)}`);
// Implement your notification logic (email, SMS, Slack, etc.)
}

// Example usage
const result = await autoTopUpOnLowBalance(
'card2020092710410645531',
100.00, // Threshold: $100
500.00 // Top-up amount: $500
);

Batch Top-Up Multiple Cards

Top up multiple cards in a single operation:

def batch_top_up_cards(top_up_list):
"""
Top up multiple cards

Args:
top_up_list: List of dicts with 'card_id' and 'amount'
"""
import uuid
from datetime import datetime

print("\n" + "=" * 70)
print("BATCH CARD TOP-UP".center(70))
print("=" * 70)
print(f"Started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Total Cards: {len(top_up_list)}\n")

results = {
'successful': [],
'failed': [],
'total_amount': 0
}

for idx, item in enumerate(top_up_list, 1):
card_id = item['card_id']
amount = float(item['amount'])

print(f"[{idx}/{len(top_up_list)}] Processing {card_id}...")
print(f" Amount: ${amount:.2f}")

try:
payload = {
"card_id": card_id,
"amount": f"{amount:.2f}",
"unique_order_id": str(uuid.uuid4())
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
data = result['data']

print(f" ✓ Success - Record ID: {data['record_id']}")

results['successful'].append({
'card_id': card_id,
'amount': amount,
'record_id': data['record_id']
})

results['total_amount'] += amount
else:
print(f" ✗ Failed: {result.get('message', 'Unknown error')}")

results['failed'].append({
'card_id': card_id,
'amount': amount,
'error': result
})

except Exception as e:
print(f" ✗ Exception: {e}")

results['failed'].append({
'card_id': card_id,
'amount': amount,
'error': str(e)
})

print()

# Summary
print("=" * 70)
print("BATCH TOP-UP SUMMARY".center(70))
print("=" * 70)
print(f"Total Cards: {len(top_up_list)}")
print(f"Successful: {len(results['successful'])} ✓")
print(f"Failed: {len(results['failed'])} ✗")
print(f"Total Amount Topped Up: ${results['total_amount']:,.2f}")

if results['failed']:
print(f"\n⚠️ Failed Top-Ups:")
for item in results['failed']:
print(f" • {item['card_id']}: ${item['amount']:.2f}")
print(f" Error: {item['error']}")

print("\n" + "=" * 70 + "\n")

return results

# Example usage
top_up_list = [
{'card_id': 'card2020092710410645531', 'amount': '500.00'},
{'card_id': 'card2020092710410645532', 'amount': '250.00'},
{'card_id': 'card2020092710410645533', 'amount': '1000.00'},
{'card_id': 'card2020092710410645534', 'amount': '750.00'}
]

results = batch_top_up_cards(top_up_list)

print(f"Batch complete: {len(results['successful'])}/{len(top_up_list)} successful")

Scheduled Recurring Top-Up

Set up recurring top-ups on a schedule:

const cron = require('node-cron');
const { v4: uuidv4 } = require('uuid');

class ScheduledTopUpManager {
constructor() {
this.schedules = new Map();
}

/**
* Schedule recurring top-ups for a card
*
* @param {string} cardId - Card ID to top up
* @param {number} amount - Amount to top up each time
* @param {string} cronExpression - Cron expression (e.g., '0 9 * * 1' for every Monday at 9 AM)
* @param {string} description - Description of the schedule
*/
scheduleRecurringTopUp(cardId, amount, cronExpression, description) {
console.log(`\n📅 Scheduling Recurring Top-Up`);
console.log(` Card: ${cardId}`);
console.log(` Amount: $${amount.toFixed(2)}`);
console.log(` Schedule: ${description}`);
console.log(` Cron: ${cronExpression}\n`);

const task = cron.schedule(cronExpression, async () => {
console.log(`\n⏰ Scheduled Top-Up Triggered: ${description}`);
console.log(` Time: ${new Date().toISOString()}`);

try {
const payload = {
card_id: cardId,
amount: amount.toFixed(2),
unique_order_id: uuidv4()
};

const response = await topUpCard(payload);

if (response.code === 'SUCCESS') {
console.log(` ✓ Top-Up Successful`);
console.log(` Record ID: ${response.data.record_id}`);
console.log(` Amount: $${amount.toFixed(2)}`);

// Log to database/file
await logTopUpEvent({
card_id: cardId,
amount: amount,
record_id: response.data.record_id,
scheduled: true,
timestamp: new Date()
});

// Send success notification
await sendNotification(
`Scheduled top-up completed for card ${cardId}: $${amount.toFixed(2)}`
);
} else {
console.log(` ✗ Top-Up Failed:`, response);

// Send failure alert
await sendAlert(
`Scheduled top-up failed for card ${cardId}`,
response
);
}
} catch (error) {
console.error(` ✗ Error:`, error.message);
await sendAlert(
`Scheduled top-up error for card ${cardId}`,
error
);
}
});

// Store the schedule
const scheduleId = uuidv4();
this.schedules.set(scheduleId, {
task: task,
cardId: cardId,
amount: amount,
cronExpression: cronExpression,
description: description,
createdAt: new Date()
});

console.log(`✓ Schedule created with ID: ${scheduleId}`);

return scheduleId;
}

/**
* Cancel a scheduled top-up
*/
cancelSchedule(scheduleId) {
const schedule = this.schedules.get(scheduleId);

if (schedule) {
schedule.task.stop();
this.schedules.delete(scheduleId);

console.log(`\n🗑️ Schedule Cancelled: ${schedule.description}`);
console.log(` Card: ${schedule.cardId}`);

return true;
} else {
console.log(`\n⚠️ Schedule not found: ${scheduleId}`);
return false;
}
}

/**
* List all active schedules
*/
listSchedules() {
console.log(`\n📋 Active Scheduled Top-Ups: ${this.schedules.size}\n`);

this.schedules.forEach((schedule, scheduleId) => {
console.log(`Schedule ID: ${scheduleId}`);
console.log(` Card: ${schedule.cardId}`);
console.log(` Amount: $${schedule.amount.toFixed(2)}`);
console.log(` Description: ${schedule.description}`);
console.log(` Cron: ${schedule.cronExpression}`);
console.log(` Created: ${schedule.createdAt.toISOString()}\n`);
});
}
}

// Example usage
const topUpManager = new ScheduledTopUpManager();

// Schedule weekly top-up every Monday at 9 AM
const weeklyScheduleId = topUpManager.scheduleRecurringTopUp(
'card2020092710410645531',
500.00,
'0 9 * * 1',
'Weekly Monday top-up'
);

// Schedule bi-weekly top-up (1st and 15th of month at 8 AM)
const biweeklyScheduleId = topUpManager.scheduleRecurringTopUp(
'card2020092710410645532',
1000.00,
'0 8 1,15 * *',
'Bi-weekly top-up (1st and 15th)'
);

// Schedule monthly top-up (first day of month at 7 AM)
const monthlyScheduleId = topUpManager.scheduleRecurringTopUp(
'card2020092710410645533',
2000.00,
'0 7 1 * *',
'Monthly top-up (1st of month)'
);

// List all schedules
topUpManager.listSchedules();

// Cancel a schedule later
// topUpManager.cancelSchedule(weeklyScheduleId);

Top-Up with Balance Verification

Top up and verify the new balance:

def top_up_and_verify(card_id, amount, max_retries=3):
"""
Top up card and verify the balance was updated correctly

Args:
card_id: Card ID to top up
amount: Amount to top up
max_retries: Number of verification retries
"""
import time
import uuid

print(f"\n=== Top-Up with Verification ===")
print(f"Card: {card_id}")
print(f"Amount: ${amount:.2f}\n")

# Get initial balance
print("Step 1: Checking initial balance...")
initial_response = query_card_balance(card_id)

if initial_response['code'] != 'SUCCESS':
print(f"✗ Failed to get initial balance: {initial_response}")
return {'success': False, 'error': 'Failed to get initial balance'}

initial_balance = float(initial_response['data']['available_balance'])
expected_balance = initial_balance + amount

print(f" Initial Balance: ${initial_balance:.2f}")
print(f" Expected Balance after top-up: ${expected_balance:.2f}\n")

# Execute top-up
print("Step 2: Executing top-up...")

payload = {
"card_id": card_id,
"amount": f"{amount:.2f}",
"unique_order_id": str(uuid.uuid4())
}

top_up_response = requests.post(url, headers=headers, json=payload)
result = top_up_response.json()

if result['code'] != 'SUCCESS':
print(f"✗ Top-up failed: {result}")
return {'success': False, 'error': result}

record_id = result['data']['record_id']
print(f" ✓ Top-up initiated - Record ID: {record_id}\n")

# Verify balance update
print("Step 3: Verifying balance update...")

for attempt in range(1, max_retries + 1):
print(f" Verification attempt {attempt}/{max_retries}...")

# Wait a moment for balance to update
time.sleep(2)

verify_response = query_card_balance(card_id)

if verify_response['code'] == 'SUCCESS':
current_balance = float(verify_response['data']['available_balance'])

print(f" Current Balance: ${current_balance:.2f}")

if abs(current_balance - expected_balance) < 0.01: # Allow 1 cent tolerance
print(f"\n✓ Verification Successful!")
print(f" Initial Balance: ${initial_balance:.2f}")
print(f" Top-Up Amount: ${amount:.2f}")
print(f" Final Balance: ${current_balance:.2f}")
print(f" Record ID: {record_id}")

return {
'success': True,
'record_id': record_id,
'initial_balance': initial_balance,
'top_up_amount': amount,
'final_balance': current_balance,
'verified': True
}
else:
difference = current_balance - expected_balance
print(f" ⚠️ Balance mismatch: ${difference:.2f} difference")

if attempt < max_retries:
print(f" Retrying...")
else:
print(f"\n⚠️ Balance verification failed after {max_retries} attempts")
print(f" Expected: ${expected_balance:.2f}")
print(f" Actual: ${current_balance:.2f}")
print(f" Difference: ${difference:.2f}")

return {
'success': True,
'record_id': record_id,
'initial_balance': initial_balance,
'top_up_amount': amount,
'final_balance': current_balance,
'verified': False,
'warning': 'Balance mismatch'
}
else:
print(f" ✗ Failed to verify balance")

if attempt == max_retries:
return {
'success': True,
'record_id': record_id,
'verified': False,
'error': 'Could not verify balance'
}

return {'success': False, 'error': 'Verification failed'}

# Example usage
result = top_up_and_verify('card2020092710410645531', 250.00)

if result['success'] and result.get('verified'):
print("\n✅ Top-up completed and verified successfully!")
elif result['success']:
print("\n⚠️ Top-up completed but verification inconclusive")
else:
print("\n❌ Top-up failed")

Dynamic Top-Up Based on Spending Pattern

Analyze spending and top up proactively:

async function intelligentTopUp(cardId) {
console.log('\n=== Intelligent Top-Up System ===\n');

try {
// Step 1: Get current balance
const balanceResponse = await queryCardBalance(cardId);
const currentBalance = parseFloat(balanceResponse.data.available_balance);

console.log(`Current Balance: $${currentBalance.toFixed(2)}`);

// Step 2: Analyze recent spending
const fundingOrders = await queryCardFundingOrders(cardId);
const spendingAnalysis = analyzeSpendingPattern(fundingOrders);

console.log('\nSpending Analysis:');
console.log(` Average Daily Spend: $${spendingAnalysis.avgDailySpend.toFixed(2)}`);
console.log(` Days Remaining at Current Rate: ${spendingAnalysis.daysRemaining.toFixed(1)}`);
console.log(` Recommended Top-Up: $${spendingAnalysis.recommendedTopUp.toFixed(2)}`);

// Step 3: Decide if top-up is needed
const daysThreshold = 3; // Top up if less than 3 days remaining

if (spendingAnalysis.daysRemaining < daysThreshold) {
console.log(`\n⚠️ Low balance warning: Only ${spendingAnalysis.daysRemaining.toFixed(1)} days remaining`);
console.log('Initiating intelligent top-up...\n');

const { v4: uuidv4 } = require('uuid');
const topUpAmount = spendingAnalysis.recommendedTopUp;

const payload = {
card_id: cardId,
amount: topUpAmount.toFixed(2),
unique_order_id: uuidv4()
};

const topUpResponse = await topUpCard(payload);

if (topUpResponse.code === 'SUCCESS') {
const newBalance = currentBalance + topUpAmount;
const newDaysRemaining = newBalance / spendingAnalysis.avgDailySpend;

console.log('✓ Intelligent Top-Up Successful!');
console.log(` Amount: $${topUpAmount.toFixed(2)}`);
console.log(` New Balance: $${newBalance.toFixed(2)}`);
console.log(` New Days Remaining: ${newDaysRemaining.toFixed(1)} days`);
console.log(` Record ID: ${topUpResponse.data.record_id}`);

return {
topped_up: true,
amount: topUpAmount,
new_balance: newBalance,
record_id: topUpResponse.data.record_id
};
}
} else {
console.log(`\n✓ Balance sufficient (${spendingAnalysis.daysRemaining.toFixed(1)} days remaining)`);
console.log('No top-up needed at this time.');

return {
topped_up: false,
reason: 'balance_sufficient'
};
}
} catch (error) {
console.error('Error in intelligent top-up:', error.message);
return {
topped_up: false,
error: error.message
};
}
}

function analyzeSpendingPattern(fundingOrders) {
// Calculate average daily spending from recent funding history
const withdrawals = fundingOrders.filter(o => o.operate_type === 'card_out');

if (withdrawals.length === 0) {
return {
avgDailySpend: 50.00, // Default if no history
daysRemaining: 999,
recommendedTopUp: 500.00
};
}

const totalSpent = withdrawals.reduce((sum, o) => sum + parseFloat(o.amount), 0);
const avgDailySpend = totalSpent / 30; // Assuming 30-day history

const currentBalance = parseFloat(balanceResponse.data.available_balance);
const daysRemaining = currentBalance / avgDailySpend;

// Recommend enough to last 14 days
const recommendedTopUp = Math.max(
(avgDailySpend * 14) - currentBalance,
100.00 // Minimum top-up
);

return {
avgDailySpend,
daysRemaining,
recommendedTopUp
};
}

// Example usage
const result = await intelligentTopUp('card2020092710410645531');

Best Practices

  • Idempotency: Always use unique unique_order_id values (UUID recommended)
  • Balance Verification: Query balance after top-up to confirm successful update
  • Budget Check: Verify budget account has sufficient balance before initiating top-up
  • Amount Precision: Always use exactly 2 decimal places for USD amounts
  • Record Tracking: Store record_id values for reconciliation and audit purposes
  • Error Handling: Implement retry logic with exponential backoff for network errors
  • Monitoring: Set up alerts for failed top-ups
  • Automation: Consider automated top-ups for frequently used cards

Understanding Card Funding

Top-Up Flow

  1. Initiate: Call this endpoint with card ID and amount
  2. Debit Budget: Amount is deducted from your budget account
  3. Credit Card: Amount is added to the card's balance
  4. Immediate: Funds are typically available within seconds
  5. Track: Use the returned record_id to track the funding order

Funding Operations

OperationDescriptionAmount Direction
Top-Up (card_in)Add funds to cardBudget → Card
Withdrawal (card_out)Remove funds from cardCard → Budget
  • Withdraw Funds - Remove funds from a Dedicated Funds Card
  • Query Dedicated Funds Card Balance - Check current card balance
  • Query Card Funding Orders - View top-up and withdrawal history
  • Query Budget Balance - Check budget account balance before top-up
  • Top-Up Budget Account - Add funds to budget account

Troubleshooting

Insufficient Budget Balance (400)

  • Cause: Budget account doesn't have enough funds
  • Solution:
    • Query budget balance first
    • Top up budget account if needed
    • Retry the card top-up

Duplicate Order ID (400)

  • Cause: The unique_order_id was used in a previous request
  • Solution:
    • Generate a new UUID for each top-up attempt
    • Don't retry with the same unique_order_id

Card Not Found (404)

  • Cause: Invalid card_id or card doesn't exist
  • Solution:
    • Verify the card ID is correct
    • Use Query All Cards to list available cards
    • Check if card was deleted or cancelled

Wrong Card Type (400)

  • Cause: Attempting to top up a Shared Funds Card
  • Solution:
    • This endpoint only works for Dedicated Funds Cards
    • Shared Funds Cards draw from budget accounts directly

Top-Up Not Reflected

  • Cause: Balance query timing or processing delay
  • Solution:
    • Wait 2-5 seconds and query balance again
    • Use the record_id to verify the funding order status
    • Check Query Card Funding Orders for the transaction

Security Considerations

  • Access Control: Restrict top-up operations to authorized users only
  • Amount Validation: Implement maximum top-up limits in your application
  • Budget Monitoring: Monitor budget account balance to prevent overdrafts
  • Audit Logging: Log all top-up operations for security auditing
  • Idempotency Protection: Store used unique_order_id values to prevent duplicates
  • Rate Limiting: Implement reasonable limits on top-up frequency

Interactive API Explorer