Fetch a Balance
Retrieve the details of a specific Balance resource. Balances represent the current financial state of an application, tracking funds that are available for immediate use, pending due to processing times, and posted (total sum).
Balance Types
DISBURSEMENT Balance
Tracks funds available for payouts to merchants. This includes:
- available_amount: Funds ready for immediate disbursement
- pending_amount: Funds on hold or being processed
- posted_amount: Total funds (available + pending)
Use Cases
1. Check Current Balance
Retrieve the current balance to verify available funds:
curl https://api.ahrvo.network/payments/na/balances/balance_dyz5APsJebDef9oTW9J2Hc \
-u username:password \
-H "Content-Type: application/json"
2. Verify Sufficient Funds Before Payout
Check if there are enough funds before initiating a payout:
async function verifySufficientFunds(balanceId, requiredAmount) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const balance = await response.json();
if (balance.available_amount < requiredAmount) {
console.error('Insufficient funds:', {
available: balance.available_amount / 100,
required: requiredAmount / 100,
shortfall: (requiredAmount - balance.available_amount) / 100
});
return false;
}
console.log('Sufficient funds available');
return true;
}
// Example: Check if we have $100 available
const canPayout = await verifySufficientFunds('balance_dyz5APsJebDef9oTW9J2Hc', 10000);
3. Monitor Balance Health
Track balance metrics and alert when low:
async function monitorBalanceHealth(balanceId, minimumThreshold = 100000) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
const healthReport = {
balance_id: balance.id,
available: balance.available_amount,
pending: balance.pending_amount,
posted: balance.posted_amount,
currency: balance.currency,
status: balance.available_amount >= minimumThreshold ? 'HEALTHY' : 'LOW',
percentage_available: (balance.available_amount / balance.posted_amount * 100).toFixed(2)
};
if (healthReport.status === 'LOW') {
console.warn('⚠️ LOW BALANCE ALERT:', {
available: `$${(balance.available_amount / 100).toFixed(2)}`,
minimum: `$${(minimumThreshold / 100).toFixed(2)}`,
shortfall: `$${((minimumThreshold - balance.available_amount) / 100).toFixed(2)}`
});
await sendLowBalanceAlert(healthReport);
}
return healthReport;
}
4. Calculate Available vs Pending Ratio
Understand fund allocation:
async function analyzeBalanceDistribution(balanceId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
const analysis = {
total_posted: balance.posted_amount,
total_available: balance.available_amount,
total_pending: balance.pending_amount,
available_percentage: ((balance.available_amount / balance.posted_amount) * 100).toFixed(2),
pending_percentage: ((balance.pending_amount / balance.posted_amount) * 100).toFixed(2),
liquidity_ratio: (balance.available_amount / balance.pending_amount).toFixed(2),
formatted: {
posted: `$${(balance.posted_amount / 100).toFixed(2)}`,
available: `$${(balance.available_amount / 100).toFixed(2)}`,
pending: `$${(balance.pending_amount / 100).toFixed(2)}`
}
};
console.log('Balance Distribution:', analysis);
return analysis;
}
5. Pre-Flight Check for Large Transactions
Verify balance before processing large transfers:
async function preFlightBalanceCheck(balanceId, transactionAmount, transactionType) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
const check = {
transaction_amount: transactionAmount,
transaction_type: transactionType,
current_available: balance.available_amount,
current_pending: balance.pending_amount,
can_proceed: balance.available_amount >= transactionAmount,
post_transaction_available: balance.available_amount - transactionAmount,
safety_buffer: 50000, // $500 minimum buffer
safe_to_proceed: (balance.available_amount - transactionAmount) >= 50000
};
if (!check.can_proceed) {
console.error('TRANSACTION BLOCKED: Insufficient funds', check);
throw new Error(`Insufficient funds: need $${transactionAmount/100}, have $${balance.available_amount/100}`);
}
if (!check.safe_to_proceed) {
console.warn('WARNING: Transaction will leave balance below safety buffer', check);
}
return check;
}
6. Real-Time Balance Dashboard
Create a live balance monitoring dashboard:
async function getBalanceDashboard(balanceId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
const dashboard = {
timestamp: new Date().toISOString(),
balance: {
id: balance.id,
type: balance.type,
currency: balance.currency,
linked_to: balance.linked_to,
linked_type: balance.linked_type
},
amounts: {
available: {
cents: balance.available_amount,
formatted: `$${(balance.available_amount / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`
},
pending: {
cents: balance.pending_amount,
formatted: `$${(balance.pending_amount / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`
},
posted: {
cents: balance.posted_amount,
formatted: `$${(balance.posted_amount / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`
}
},
metrics: {
liquidity_percentage: ((balance.available_amount / balance.posted_amount) * 100).toFixed(2) + '%',
pending_percentage: ((balance.pending_amount / balance.posted_amount) * 100).toFixed(2) + '%',
health_status: balance.available_amount > 100000 ? '✅ HEALTHY' : balance.available_amount > 50000 ? '⚠️ LOW' : '🔴 CRITICAL'
},
tags: balance.tags,
last_updated: balance.updated_at
};
return dashboard;
}
7. Balance Change Detection
Compare current balance with previous snapshot:
async function detectBalanceChanges(balanceId, previousSnapshot) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const currentBalance = await response.json();
const changes = {
timestamp: new Date().toISOString(),
available_change: currentBalance.available_amount - previousSnapshot.available_amount,
pending_change: currentBalance.pending_amount - previousSnapshot.pending_amount,
posted_change: currentBalance.posted_amount - previousSnapshot.posted_amount,
changes_detected: false
};
changes.changes_detected =
changes.available_change !== 0 ||
changes.pending_change !== 0 ||
changes.posted_change !== 0;
if (changes.changes_detected) {
console.log('Balance changes detected:', {
available: `${changes.available_change >= 0 ? '+' : ''}$${(changes.available_change / 100).toFixed(2)}`,
pending: `${changes.pending_change >= 0 ? '+' : ''}$${(changes.pending_change / 100).toFixed(2)}`,
posted: `${changes.posted_change >= 0 ? '+' : ''}$${(changes.posted_change / 100).toFixed(2)}`
});
}
return {
current: currentBalance,
changes: changes
};
}
8. Multi-Application Balance Check
Check balances across multiple applications:
async function checkMultipleBalances(balanceIds) {
const balances = await Promise.all(
balanceIds.map(async (id) => {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${id}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
return await response.json();
})
);
const summary = {
total_balances: balances.length,
total_available: balances.reduce((sum, b) => sum + b.available_amount, 0),
total_pending: balances.reduce((sum, b) => sum + b.pending_amount, 0),
total_posted: balances.reduce((sum, b) => sum + b.posted_amount, 0),
by_application: balances.map(b => ({
application: b.linked_to,
available: `$${(b.available_amount / 100).toFixed(2)}`,
pending: `$${(b.pending_amount / 100).toFixed(2)}`,
total: `$${(b.posted_amount / 100).toFixed(2)}`
})),
formatted: {
total_available: `$${(balances.reduce((sum, b) => sum + b.available_amount, 0) / 100).toFixed(2)}`,
total_pending: `$${(balances.reduce((sum, b) => sum + b.pending_amount, 0) / 100).toFixed(2)}`,
total_posted: `$${(balances.reduce((sum, b) => sum + b.posted_amount, 0) / 100).toFixed(2)}`
}
};
return summary;
}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
balance_id | string | Yes | The unique ID of the Balance resource |
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the balance |
created_at | string | ISO 8601 timestamp of creation |
updated_at | string | ISO 8601 timestamp of last update |
available_amount | integer | Amount available for immediate use or disbursement (in cents) |
currency | string | 3-letter ISO 4217 currency code (e.g., "USD") |
linked_to | string | ID of the linked Application |
linked_type | string | Type of linked entity (e.g., "APPLICATION") |
pending_amount | integer | Amount pending due to processing times, holds, or constraints (in cents) |
posted_amount | integer | Total sum including both available and pending funds (in cents) |
tags | object | Custom metadata key-value pairs |
type | string | Type of balance (e.g., "DISBURSEMENT") |
Understanding Balance Amounts
Available Amount
Funds ready for immediate disbursement or use. These funds can be:
- Transferred to merchants
- Used for payouts
- Withdrawn immediately
Pending Amount
Funds that are temporarily unavailable due to:
- Processing times (ACH settlements take 1-3 days)
- Holds from risk reviews
- Disputed transactions
- Reserved funds
Posted Amount
The total balance combining both available and pending:
posted_amount = available_amount + pending_amount
Best Practices
1. Cache Balance Data Appropriately
Balance data changes frequently, but doesn't need to be fetched constantly:
class BalanceCache {
constructor(ttl = 60000) { // 1 minute default
this.cache = new Map();
this.ttl = ttl;
}
async get(balanceId, forceRefresh = false) {
const cached = this.cache.get(balanceId);
const now = Date.now();
if (!forceRefresh && cached && (now - cached.timestamp) < this.ttl) {
console.log('Using cached balance');
return cached.balance;
}
console.log('Fetching fresh balance');
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
this.cache.set(balanceId, {
balance,
timestamp: now
});
return balance;
}
invalidate(balanceId) {
this.cache.delete(balanceId);
}
}
const balanceCache = new BalanceCache();
2. Always Use Available Amount for Decisions
Never use pending or posted amounts to determine if you can make a payout:
// ✅ CORRECT
if (balance.available_amount >= payoutAmount) {
await processPayout(payoutAmount);
}
// ❌ WRONG - Don't use posted amount
if (balance.posted_amount >= payoutAmount) {
await processPayout(payoutAmount); // May fail!
}
3. Set Up Low Balance Alerts
Proactively monitor balances and alert before they run out:
async function setupLowBalanceMonitoring(balanceId, threshold = 100000) {
setInterval(async () => {
const balance = await balanceCache.get(balanceId);
if (balance.available_amount < threshold) {
await sendAlert('Low Balance Warning', {
balance_id: balanceId,
current: `$${(balance.available_amount / 100).toFixed(2)}`,
threshold: `$${(threshold / 100).toFixed(2)}`,
action_needed: 'Top up account soon'
});
}
}, 5 * 60 * 1000); // Check every 5 minutes
}
4. Track Balance Over Time
Monitor balance trends to predict when top-ups are needed:
class BalanceTracker {
constructor() {
this.history = [];
}
async recordBalance(balanceId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balance = await response.json();
this.history.push({
timestamp: new Date().toISOString(),
available: balance.available_amount,
pending: balance.pending_amount,
posted: balance.posted_amount
});
// Keep only last 100 records
if (this.history.length > 100) {
this.history.shift();
}
}
getTrend() {
if (this.history.length < 2) return null;
const recent = this.history.slice(-10);
const avgChange = recent.reduce((sum, record, idx) => {
if (idx === 0) return 0;
return sum + (record.available - recent[idx - 1].available);
}, 0) / (recent.length - 1);
return {
trend: avgChange >= 0 ? 'INCREASING' : 'DECREASING',
avg_daily_change: avgChange,
formatted: `${avgChange >= 0 ? '+' : ''}$${(avgChange / 100).toFixed(2)}/day`
};
}
}
5. Handle Balance Errors Gracefully
Always handle cases where balance fetch might fail:
async function safeGetBalance(balanceId) {
try {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances/${balanceId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
if (response.status === 404) {
console.error('Balance not found:', balanceId);
return null;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching balance:', error);
throw error;
}
}
6. Implement Safety Buffers
Never allow balance to go to exactly zero:
const SAFETY_BUFFER = 50000; // $500 minimum
async function canAffordTransaction(balanceId, amount) {
const balance = await safeGetBalance(balanceId);
const postTransactionBalance = balance.available_amount - amount;
if (postTransactionBalance < SAFETY_BUFFER) {
return {
can_afford: false,
reason: 'Would leave balance below safety buffer',
current_available: balance.available_amount,
post_transaction: postTransactionBalance,
safety_buffer: SAFETY_BUFFER
};
}
return {
can_afford: true,
current_available: balance.available_amount,
post_transaction: postTransactionBalance
};
}
Common Workflows
Daily Balance Report
async function generateDailyBalanceReport(balanceId) {
const balance = await safeGetBalance(balanceId);
const report = {
date: new Date().toISOString().split('T')[0],
balance_id: balanceId,
application: balance.linked_to,
snapshot: {
available: `$${(balance.available_amount / 100).toFixed(2)}`,
pending: `$${(balance.pending_amount / 100).toFixed(2)}`,
total: `$${(balance.posted_amount / 100).toFixed(2)}`
},
status: balance.available_amount > 100000 ? 'HEALTHY' :
balance.available_amount > 50000 ? 'LOW' : 'CRITICAL',
recommendation: balance.available_amount < 100000 ?
'Consider topping up account' : 'Balance is healthy'
};
console.log('Daily Balance Report:', report);
// Send report via email
await sendReport(report);
return report;
}
// Schedule daily at 9 AM
// scheduleCronJob('0 9 * * *', () => generateDailyBalanceReport('balance_dyz5APsJebDef9oTW9J2Hc'));
Balance-Aware Payout Processing
async function processPayoutWithBalanceCheck(balanceId, payoutAmount, merchantId) {
// 1. Check current balance
const balance = await safeGetBalance(balanceId);
// 2. Verify sufficient funds
if (balance.available_amount < payoutAmount) {
throw new Error('Insufficient funds for payout');
}
// 3. Verify safety buffer
const postPayoutBalance = balance.available_amount - payoutAmount;
if (postPayoutBalance < 50000) {
console.warn('⚠️ Payout will leave balance below safety buffer');
await alertLowBalance(balance, postPayoutBalance);
}
// 4. Process payout
const payout = await createPayout({
merchant: merchantId,
amount: payoutAmount,
currency: balance.currency
});
// 5. Log transaction
await logBalanceTransaction({
balance_id: balanceId,
type: 'PAYOUT',
amount: payoutAmount,
merchant: merchantId,
payout_id: payout.id,
pre_balance: balance.available_amount,
post_balance: postPayoutBalance
});
return payout;
}