Skip to main content

Query Top-Up Order

Overview

Use this endpoint to query the status of a specific top-up order. This allows you to verify whether funds were successfully added to a budget account, which is essential for reconciliation and error handling in your budget funding workflows.

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

Resource Access

Production (api.ahrvo.network)

GET https://api.ahrvo.network/card/issuance/api/issuing/budget/v2/top-up/order

Staging (gateway.ahrvo.network)

GET https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/top-up/order

Request Headers

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

Query Parameters

ParameterTypeRequiredDescription
unique_order_idstringYesThe unique order ID provided by you when initiating the top-up

Response

Success Response (200 OK)

{
"code": "SUCCESS",
"data": {
"status": "SUCCESS"
}
}

Response Fields

FieldTypeDescription
codestringStatus string indicating the result of the query. "SUCCESS" refers to a successful query
dataobjectResponse data object
data.statusstringThe processing status of the top-up order

Top-Up Status Values

StatusDescription
SUCCESSThe top-up was completed successfully and funds have been added to the budget
FAILEDThe top-up failed (payment declined, insufficient funds, invalid account, etc.)
PROCESSINGThe top-up is still being processed

Error Responses

  • 400 Bad Request: Invalid or missing unique_order_id
  • 401 Unauthorized: Invalid or missing authentication token
  • 403 Forbidden: Card issuance feature not enabled for this account
  • 404 Not Found: Top-up order does not exist

Code Examples

cURL

curl -X GET \
'https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/top-up/order?unique_order_id=1621924039' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY'

Python

import requests

url = "https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/top-up/order"
headers = {
"Accept": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
params = {
"unique_order_id": "1621924039"
}

response = requests.get(url, headers=headers, params=params)
result = response.json()

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

if top_up_status == 'SUCCESS':
print("✓ Top-up completed successfully")
elif top_up_status == 'FAILED':
print("✗ Top-up failed")
elif top_up_status == 'PROCESSING':
print("⏳ Top-up is still processing")
else:
print(f"Top-up status: {top_up_status}")
else:
print(f"Failed to query top-up order: {result}")

JavaScript (Node.js)

const axios = require('axios');

const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/top-up/order';
const headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const params = {
unique_order_id: '1621924039'
};

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

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

if (topUpStatus === 'SUCCESS') {
console.log('✓ Top-up completed successfully');
} else if (topUpStatus === 'FAILED') {
console.log('✗ Top-up failed');
} else if (topUpStatus === 'PROCESSING') {
console.log('⏳ Top-up is still processing');
} else {
console.log(`Top-up status: ${topUpStatus}`);
}
}
})
.catch(error => {
console.error('Failed to query top-up order:', error.response.data);
});

Usage Notes

  • Unique Order ID: Use the same unique_order_id you provided when initiating the top-up
  • Asynchronous Processing: Top-ups may be processed asynchronously, so query the status to confirm completion
  • Status Polling: Implement polling logic to check status periodically until SUCCESS or FAILED
  • Idempotent: You can query the same top-up order multiple times safely
  • Reconciliation: Use this endpoint for reconciliation and audit purposes

Common Use Cases

Verify Top-Up After Initiation

Check if a top-up completed successfully with retry logic:

def verify_top_up_completion(unique_order_id, max_attempts=10, wait_seconds=3):
"""
Verify a top-up has completed successfully with polling
"""
import time

for attempt in range(max_attempts):
try:
response = query_top_up_order(unique_order_id)

if response['code'] == 'SUCCESS':
status = response['data']['status']

if status == 'SUCCESS':
print(f"✓ Top-up {unique_order_id} completed successfully")
return True
elif status == 'FAILED':
print(f"✗ Top-up {unique_order_id} failed")
return False
elif status == 'PROCESSING':
print(f"⏳ Attempt {attempt + 1}/{max_attempts}: Top-up still processing...")

if attempt < max_attempts - 1:
time.sleep(wait_seconds)
continue

except Exception as e:
print(f"Error checking top-up status: {e}")
if attempt < max_attempts - 1:
time.sleep(wait_seconds)

print(f"⚠ Could not verify top-up status after {max_attempts} attempts")
return None

# Example usage
unique_order_id = "1621924039"
success = verify_top_up_completion(unique_order_id)

if success:
print("Proceeding with card issuance...")
else:
print("Cannot proceed - top-up failed or timed out")

Top-Up with Confirmation Workflow

Initiate a top-up and wait for confirmation:

async function topUpWithConfirmation(budgetId, amount, uniqueOrderId) {
try {
// Step 1: Initiate top-up
console.log('Initiating top-up...');
const topUpResponse = await initiateBudgetTopUp({
budget_id: budgetId,
amount: amount,
unique_order_id: uniqueOrderId
});

console.log(`Top-up initiated: ${uniqueOrderId}`);

// Step 2: Poll for completion
console.log('Waiting for top-up to complete...');
const maxAttempts = 10;
const delayMs = 3000; // 3 seconds

for (let attempt = 1; attempt <= maxAttempts; attempt++) {
await new Promise(resolve => setTimeout(resolve, delayMs));

const statusResponse = await queryTopUpOrder(uniqueOrderId);

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

if (status === 'SUCCESS') {
console.log('✓ Top-up completed successfully');
return {
success: true,
unique_order_id: uniqueOrderId,
budget_id: budgetId,
amount: amount
};
} else if (status === 'FAILED') {
console.log('✗ Top-up failed');
return {
success: false,
unique_order_id: uniqueOrderId,
error: 'Top-up failed'
};
} else if (status === 'PROCESSING') {
console.log(`⏳ Attempt ${attempt}/${maxAttempts}: Still processing...`);
continue;
}
}
}

console.log('⚠ Top-up status could not be confirmed');
return {
success: null,
unique_order_id: uniqueOrderId,
error: 'Status verification timeout'
};
} catch (error) {
console.error('Top-up with confirmation failed:', error);
throw error;
}
}

// Example usage
const result = await topUpWithConfirmation(
'ci202507232016182661',
10000.00,
`topup_${Date.now()}`
);

Batch Top-Up Verification

Verify multiple top-ups at once:

def verify_batch_top_ups(unique_order_ids):
"""
Verify the status of multiple top-up orders
"""
results = {
'successful': [],
'failed': [],
'processing': [],
'unknown': []
}

for order_id in unique_order_ids:
try:
response = query_top_up_order(order_id)

if response['code'] == 'SUCCESS':
status = response['data']['status']

if status == 'SUCCESS':
results['successful'].append(order_id)
elif status == 'FAILED':
results['failed'].append(order_id)
elif status == 'PROCESSING':
results['processing'].append(order_id)
else:
results['unknown'].append(order_id)
except Exception as e:
print(f"Error checking top-up {order_id}: {e}")
results['unknown'].append(order_id)

# Print summary
print("\n=== Top-Up Verification Summary ===")
print(f"Total Orders: {len(unique_order_ids)}")
print(f"✓ Successful: {len(results['successful'])}")
print(f"✗ Failed: {len(results['failed'])}")
print(f"⏳ Processing: {len(results['processing'])}")
print(f"? Unknown: {len(results['unknown'])}")

return results

# Example usage
order_ids = [
"1621924039",
"1621924040",
"1621924041"
]
verification_results = verify_batch_top_ups(order_ids)

# Retry processing orders
if verification_results['processing']:
print("\nRetrying processing orders in 5 seconds...")
time.sleep(5)
retry_results = verify_batch_top_ups(verification_results['processing'])

Top-Up Reconciliation Report

Generate a reconciliation report for top-ups:

async function generateTopUpReconciliationReport(topUpOrders) {
const report = {
generated_at: new Date().toISOString(),
total_top_ups: topUpOrders.length,
successful_count: 0,
failed_count: 0,
processing_count: 0,
total_amount_successful: 0,
total_amount_failed: 0,
total_amount_processing: 0,
details: []
};

for (const order of topUpOrders) {
try {
const response = await queryTopUpOrder(order.unique_order_id);

if (response.code === 'SUCCESS') {
const status = response.data.status;
const detail = {
unique_order_id: order.unique_order_id,
budget_name: order.budget_name,
budget_id: order.budget_id,
amount: order.amount,
currency: order.currency,
status: status,
initiated_at: order.initiated_at
};

if (status === 'SUCCESS') {
report.successful_count++;
report.total_amount_successful += order.amount;
} else if (status === 'FAILED') {
report.failed_count++;
report.total_amount_failed += order.amount;
} else if (status === 'PROCESSING') {
report.processing_count++;
report.total_amount_processing += order.amount;
}

report.details.push(detail);
}
} catch (error) {
console.error(`Error checking top-up ${order.unique_order_id}:`, error);
}
}

// Print report
console.log('\n=== Top-Up Reconciliation Report ===');
console.log(`Generated: ${report.generated_at}`);
console.log(`Total Top-Ups: ${report.total_top_ups}`);
console.log(`✓ Successful: ${report.successful_count} (${report.total_amount_successful.toFixed(2)} USD)`);
console.log(`✗ Failed: ${report.failed_count} (${report.total_amount_failed.toFixed(2)} USD)`);
console.log(`⏳ Processing: ${report.processing_count} (${report.total_amount_processing.toFixed(2)} USD)`);
console.log('\nDetails:');

report.details.forEach(detail => {
const statusIcon = detail.status === 'SUCCESS' ? '✓' :
detail.status === 'FAILED' ? '✗' : '⏳';
console.log(`${statusIcon} ${detail.unique_order_id}: ${detail.budget_name} (${detail.currency} ${detail.amount})`);
});

return report;
}

// Example usage
const topUps = [
{
unique_order_id: '1621924039',
budget_name: 'Marketing Budget',
budget_id: 'ci202507232016182661',
amount: 10000,
currency: 'USD',
initiated_at: '2026-02-07T10:30:00Z'
},
// ... more top-ups
];

const report = await generateTopUpReconciliationReport(topUps);

Automated Top-Up with Retry

Handle failed top-ups with automated retry:

def top_up_with_retry(budget_id, amount, max_retries=3):
"""
Initiate top-up with automatic retry on failure
"""
import time
import uuid

for attempt in range(max_retries):
# Generate unique order ID for this attempt
unique_order_id = f"topup_{int(time.time())}_{uuid.uuid4().hex[:8]}"

try:
# Initiate top-up
top_up_response = initiate_budget_top_up(
budget_id=budget_id,
amount=amount,
unique_order_id=unique_order_id
)

print(f"Top-up initiated (Attempt {attempt + 1}): {unique_order_id}")

# Poll for completion
for check_attempt in range(10):
time.sleep(3)

status_response = query_top_up_order(unique_order_id)

if status_response['code'] == 'SUCCESS':
status = status_response['data']['status']

if status == 'SUCCESS':
print(f"✓ Top-up successful on attempt {attempt + 1}")
return {
'success': True,
'unique_order_id': unique_order_id,
'attempts': attempt + 1
}
elif status == 'FAILED':
print(f"✗ Top-up failed on attempt {attempt + 1}")

if attempt < max_retries - 1:
print(f"Retrying... ({max_retries - attempt - 1} attempts remaining)")
time.sleep(5)
break # Exit polling loop to retry
elif status == 'PROCESSING':
print(f"⏳ Check {check_attempt + 1}/10: Still processing...")
continue

except Exception as e:
print(f"Error on attempt {attempt + 1}: {e}")
if attempt < max_retries - 1:
time.sleep(5)

return {
'success': False,
'attempts': max_retries,
'error': 'Max retries exceeded'
}

# Example usage
result = top_up_with_retry('ci202507232016182661', 10000.00)

Top-Up Monitoring Dashboard

Monitor ongoing top-ups in real-time:

class TopUpMonitor {
constructor() {
this.pendingTopUps = new Map();
}

async addTopUp(uniqueOrderId, metadata = {}) {
this.pendingTopUps.set(uniqueOrderId, {
...metadata,
added_at: new Date(),
last_checked: null,
status: 'PENDING'
});

console.log(`Added top-up to monitor: ${uniqueOrderId}`);
}

async checkAllTopUps() {
console.log(`\nChecking ${this.pendingTopUps.size} pending top-ups...`);

const completedTopUps = [];

for (const [orderId, info] of this.pendingTopUps.entries()) {
try {
const response = await queryTopUpOrder(orderId);

if (response.code === 'SUCCESS') {
const status = response.data.status;
info.last_checked = new Date();
info.status = status;

if (status === 'SUCCESS') {
console.log(`${orderId}: Completed successfully`);
completedTopUps.push(orderId);
} else if (status === 'FAILED') {
console.log(`${orderId}: Failed`);
completedTopUps.push(orderId);
} else if (status === 'PROCESSING') {
console.log(`${orderId}: Still processing`);
}
}
} catch (error) {
console.error(` Error checking ${orderId}:`, error.message);
}
}

// Remove completed top-ups
completedTopUps.forEach(id => {
console.log(`Removing completed top-up: ${id}`);
this.pendingTopUps.delete(id);
});

return {
checked: this.pendingTopUps.size + completedTopUps.length,
completed: completedTopUps.length,
pending: this.pendingTopUps.size
};
}

getPendingCount() {
return this.pendingTopUps.size;
}

getPendingTopUps() {
return Array.from(this.pendingTopUps.entries()).map(([id, info]) => ({
unique_order_id: id,
...info
}));
}
}

// Example usage
const monitor = new TopUpMonitor();

// Add top-ups to monitor
await monitor.addTopUp('1621924039', {
budget_name: 'Marketing Budget',
amount: 10000,
currency: 'USD'
});

// Check periodically
setInterval(async () => {
if (monitor.getPendingCount() > 0) {
const results = await monitor.checkAllTopUps();
console.log(`\nMonitoring Summary: ${results.pending} pending, ${results.completed} completed`);
}
}, 5000); // Check every 5 seconds

Budget Funding with Balance Verification

Top up and verify the new balance:

def fund_budget_with_verification(budget_id, amount):
"""
Top up a budget and verify the balance increased correctly
"""
import time

# Step 1: Get current balance
print("Getting current balance...")
balance_response = query_budget_balance(budget_id)
original_balance = balance_response['data']['balance']
print(f"Current balance: {original_balance}")

# Step 2: Initiate top-up
unique_order_id = f"topup_{int(time.time())}"
print(f"\nInitiating top-up of {amount}...")

top_up_response = initiate_budget_top_up(
budget_id=budget_id,
amount=amount,
unique_order_id=unique_order_id
)

# Step 3: Wait for top-up to complete
print("Waiting for top-up to complete...")
max_attempts = 10

for attempt in range(max_attempts):
time.sleep(3)

status_response = query_top_up_order(unique_order_id)

if status_response['code'] == 'SUCCESS':
status = status_response['data']['status']

if status == 'SUCCESS':
print("✓ Top-up completed successfully")
break
elif status == 'FAILED':
print("✗ Top-up failed")
return {
'success': False,
'error': 'Top-up failed'
}
elif status == 'PROCESSING':
print(f"⏳ Attempt {attempt + 1}/{max_attempts}: Still processing...")

# Step 4: Verify new balance
print("\nVerifying new balance...")
time.sleep(2) # Wait for balance to update

new_balance_response = query_budget_balance(budget_id)
new_balance = new_balance_response['data']['balance']
expected_balance = original_balance + amount

print(f"Original balance: {original_balance}")
print(f"Top-up amount: {amount}")
print(f"Expected balance: {expected_balance}")
print(f"Actual balance: {new_balance}")

if new_balance == expected_balance:
print("✓ Balance verification successful")
return {
'success': True,
'original_balance': original_balance,
'new_balance': new_balance,
'amount_added': amount
}
else:
print(f"⚠ Balance mismatch: expected {expected_balance}, got {new_balance}")
return {
'success': False,
'error': 'Balance verification failed',
'original_balance': original_balance,
'new_balance': new_balance,
'amount_added': amount
}

# Example usage
result = fund_budget_with_verification('ci202507232016182661', 10000.00)

Best Practices

  • Always Verify: Check top-up status after initiating to ensure funds were added
  • Use Unique IDs: Generate unique order IDs to avoid duplicates (e.g., timestamp + UUID)
  • Implement Polling: Poll status periodically until SUCCESS or FAILED (not PROCESSING)
  • Set Timeouts: Define maximum retry attempts to avoid infinite loops
  • Balance Verification: Verify budget balance after successful top-up
  • Error Handling: Handle all status values (SUCCESS, FAILED, PROCESSING)
  • Audit Trail: Log all top-up attempts and results for compliance

Top-Up Workflow

Standard Top-Up Process

  1. Check Current Balance: Query existing budget balance
  2. Initiate Top-Up: Call top-up endpoint with unique_order_id
  3. Store Order ID: Save the unique_order_id for status tracking
  4. Poll Status: Use this endpoint to check status periodically
  5. Verify Completion: Wait for SUCCESS or FAILED status
  6. Verify Balance: Confirm budget balance increased by expected amount
  7. Update Records: Update your internal systems with the result
  • Top-Up Budget Account - Initiate a top-up to add funds to a budget
  • Query Budget Balance - Check balance before and after top-ups
  • Create Budget Account - Create budget accounts to receive top-ups
  • Query Budget Details - Get detailed information about budget accounts

Troubleshooting

Top-Up Order Not Found (404)

  • Cause: Invalid unique_order_id or top-up doesn't exist
  • Solution:
    • Verify the unique_order_id is correct and matches what you provided at initiation
    • Ensure the top-up was actually initiated

Top-Up Status Remains PROCESSING

  • Cause: Top-up is taking longer than expected or stuck
  • Solution:
    • Continue polling - some top-ups may take several minutes
    • Check with support if status doesn't update after 5-10 minutes
    • Verify your payment source is valid

Top-Up Failed Status

  • Cause: Payment declined, insufficient funds, invalid account, etc.
  • Solution:
    • Check your funding source has sufficient balance
    • Verify payment method is valid and not expired
    • Review budget account is active and not frozen
    • Contact support for specific failure reason

Balance Not Updated After SUCCESS

  • Cause: Delay in balance propagation
  • Solution:
    • Wait a few seconds and query balance again
    • Verify you're checking the correct budget_id
    • Contact support if balance still doesn't reflect top-up

Security Considerations

  • Order ID Security: Treat unique order IDs as sensitive information
  • Idempotency: Use the same unique_order_id to safely retry queries
  • Rate Limiting: Implement reasonable polling intervals (3-5 seconds recommended)
  • Audit Logging: Log all top-up status queries for audit purposes
  • Data Retention: Maintain top-up records for compliance requirements

Interactive API Explorer