Skip to main content

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

ParameterTypeRequiredDescription
balance_idstringYesThe unique ID of the Balance resource

Response Fields

FieldTypeDescription
idstringUnique identifier for the balance
created_atstringISO 8601 timestamp of creation
updated_atstringISO 8601 timestamp of last update
available_amountintegerAmount available for immediate use or disbursement (in cents)
currencystring3-letter ISO 4217 currency code (e.g., "USD")
linked_tostringID of the linked Application
linked_typestringType of linked entity (e.g., "APPLICATION")
pending_amountintegerAmount pending due to processing times, holds, or constraints (in cents)
posted_amountintegerTotal sum including both available and pending funds (in cents)
tagsobjectCustom metadata key-value pairs
typestringType 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;
}

Interactive API Reference