Skip to main content

List Balances

Retrieve a list of Balance resources. A Balance represents the current financial state of an Application, tracking the state of funds processed through the system, including amounts that are available for immediate use or disbursement, pending due to processing times, holds, or other constraints, and posted, which reflects the total sum (including both available and pending funds).

Use Cases

1. List All Balances

Retrieve all balances for your platform:

curl "https://api.ahrvo.network/payments/na/balances?limit=100" \
-u username:password \
-H "Content-Type: application/json"

2. Get Balance Summary Across Applications

Calculate total funds across all applications:

async function getTotalBalancesSummary() {
const response = await fetch(
'https://api.ahrvo.network/payments/na/balances?limit=100',
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const data = await response.json();
const balances = data._embedded?.balances || [];

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: {},
formatted: {}
};

// Group by application
balances.forEach(balance => {
if (!summary.by_application[balance.linked_to]) {
summary.by_application[balance.linked_to] = {
application_id: balance.linked_to,
available: 0,
pending: 0,
posted: 0,
balances_count: 0
};
}

summary.by_application[balance.linked_to].available += balance.available_amount;
summary.by_application[balance.linked_to].pending += balance.pending_amount;
summary.by_application[balance.linked_to].posted += balance.posted_amount;
summary.by_application[balance.linked_to].balances_count++;
});

// Format totals
summary.formatted = {
total_available: `$${(summary.total_available / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`,
total_pending: `$${(summary.total_pending / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`,
total_posted: `$${(summary.total_posted / 100).toLocaleString('en-US', {minimumFractionDigits: 2})}`
};

return summary;
}

3. Find Low Balances

Identify balances that need attention:

async function findLowBalances(threshold = 100000) {
const response = await fetch(
'https://api.ahrvo.network/payments/na/balances?limit=100',
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

const data = await response.json();
const balances = data._embedded?.balances || [];

const lowBalances = balances.filter(b => b.available_amount < threshold);

if (lowBalances.length > 0) {
console.warn(`⚠️ Found ${lowBalances.length} low balances:`);

lowBalances.forEach(balance => {
console.warn({
balance_id: balance.id,
application: balance.linked_to,
available: `$${(balance.available_amount / 100).toFixed(2)}`,
threshold: `$${(threshold / 100).toFixed(2)}`,
shortfall: `$${((threshold - balance.available_amount) / 100).toFixed(2)}`
});
});
}

return lowBalances;
}

4. Monitor Platform Liquidity

Track overall platform fund availability:

async function monitorPlatformLiquidity() {
const response = await fetch(
'https://api.ahrvo.network/payments/na/balances?limit=100',
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

const data = await response.json();
const balances = data._embedded?.balances || [];

const liquidity = {
timestamp: new Date().toISOString(),
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),
liquidity_ratio: 0,
applications_count: new Set(balances.map(b => b.linked_to)).size,
health_status: ''
};

liquidity.liquidity_ratio = (liquidity.total_available / liquidity.total_posted * 100).toFixed(2);

// Determine health status
if (liquidity.liquidity_ratio > 70) {
liquidity.health_status = '✅ EXCELLENT';
} else if (liquidity.liquidity_ratio > 50) {
liquidity.health_status = '✅ GOOD';
} else if (liquidity.liquidity_ratio > 30) {
liquidity.health_status = '⚠️ MODERATE';
} else {
liquidity.health_status = '🔴 LOW';
}

console.log('Platform Liquidity Report:', {
...liquidity,
formatted: {
available: `$${(liquidity.total_available / 100).toLocaleString()}`,
pending: `$${(liquidity.total_pending / 100).toLocaleString()}`,
posted: `$${(liquidity.total_posted / 100).toLocaleString()}`
}
});

return liquidity;
}

5. Paginate Through All Balances

Retrieve all balances across multiple pages:

async function getAllBalances() {
const allBalances = [];
let nextCursor = null;

do {
const url = nextCursor
? `https://api.ahrvo.network/payments/na/balances?limit=100&after_cursor=${nextCursor}`
: 'https://api.ahrvo.network/payments/na/balances?limit=100';

const response = await fetch(url, {
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
});

const data = await response.json();
const balances = data._embedded?.balances || [];

allBalances.push(...balances);
nextCursor = data.page?.next_cursor;

console.log(`Fetched ${balances.length} balances, total: ${allBalances.length}`);

} while (nextCursor);

return allBalances;
}

6. Generate Balance Health Dashboard

Create a comprehensive health dashboard:

async function generateBalanceHealthDashboard() {
const balances = await getAllBalances();

const dashboard = {
generated_at: new Date().toISOString(),
overview: {
total_balances: balances.length,
total_applications: new Set(balances.map(b => b.linked_to)).size
},
financial_summary: {
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)
},
health_breakdown: {
healthy: balances.filter(b => b.available_amount > 100000).length,
low: balances.filter(b => b.available_amount > 50000 && b.available_amount <= 100000).length,
critical: balances.filter(b => b.available_amount <= 50000).length
},
top_balances: balances
.sort((a, b) => b.available_amount - a.available_amount)
.slice(0, 10)
.map(b => ({
id: b.id,
application: b.linked_to,
available: `$${(b.available_amount / 100).toLocaleString()}`
})),
bottom_balances: balances
.sort((a, b) => a.available_amount - b.available_amount)
.slice(0, 10)
.map(b => ({
id: b.id,
application: b.linked_to,
available: `$${(b.available_amount / 100).toLocaleString()}`
}))
};

return dashboard;
}

Query Parameters

ParameterTypeRequiredDefaultDescription
limitintegerNo100Number of items to return per page
after_cursorstringNo-Return items created after this cursor value
before_cursorstringNo-Return items created before this cursor value

Response Structure

FieldTypeDescription
_embedded.balancesarrayArray of Balance objects
_links.self.hrefstringURL to current page
page.limitintegerNumber of items per page
page.next_cursorstringCursor for next page (if available)

Balance Fields

Each balance in the array contains:

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 (in cents)
currencystringCurrency code (e.g., "USD")
linked_tostringID of the linked Application
linked_typestringType of linked entity (e.g., "APPLICATION")
pending_amountintegerAmount pending (in cents)
posted_amountintegerTotal sum of available and pending (in cents)
tagsobjectCustom metadata
typestringBalance type (e.g., "DISBURSEMENT")

Best Practices

1. Use Pagination for Large Result Sets

Always paginate when dealing with many balances:

async function getBalancesPaginated(limit = 50) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balances?limit=${limit}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

return await response.json();
}

2. Cache Balance Lists

Cache balance lists to reduce API calls:

class BalanceListCache {
constructor(ttl = 120000) { // 2 minute default
this.cache = null;
this.cacheTime = null;
this.ttl = ttl;
}

async getBalances(forceRefresh = false) {
const now = Date.now();

if (!forceRefresh && this.cache && (now - this.cacheTime) < this.ttl) {
console.log('Using cached balance list');
return this.cache;
}

console.log('Fetching fresh balance list');
const balances = await getAllBalances();

this.cache = balances;
this.cacheTime = now;

return balances;
}

invalidate() {
this.cache = null;
this.cacheTime = null;
}
}

const balanceListCache = new BalanceListCache();

Track changes over time:

class BalanceTrendMonitor {
constructor() {
this.snapshots = [];
}

async takeSnapshot() {
const balances = await getAllBalances();

const snapshot = {
timestamp: new Date().toISOString(),
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),
count: balances.length
};

this.snapshots.push(snapshot);

// Keep only last 24 hours (assuming snapshots every hour)
if (this.snapshots.length > 24) {
this.snapshots.shift();
}

return snapshot;
}

getHourlyChange() {
if (this.snapshots.length < 2) return null;

const current = this.snapshots[this.snapshots.length - 1];
const previous = this.snapshots[this.snapshots.length - 2];

return {
available_change: current.total_available - previous.total_available,
pending_change: current.total_pending - previous.total_pending,
posted_change: current.total_posted - previous.total_posted,
formatted: {
available: `${current.total_available >= previous.total_available ? '+' : ''}$${((current.total_available - previous.total_available) / 100).toFixed(2)}`,
pending: `${current.total_pending >= previous.total_pending ? '+' : ''}$${((current.total_pending - previous.total_pending) / 100).toFixed(2)}`,
posted: `${current.total_posted >= previous.total_posted ? '+' : ''}$${((current.total_posted - previous.total_posted) / 100).toFixed(2)}`
}
};
}
}

4. Set Up Automated Alerts

Monitor balances and alert on issues:

async function monitorBalancesAndAlert() {
const balances = await getAllBalances();

// Check for low balances
const lowBalances = balances.filter(b => b.available_amount < 100000);

if (lowBalances.length > 0) {
await sendAlert('Low Balance Warning', {
count: lowBalances.length,
balances: lowBalances.map(b => ({
id: b.id,
application: b.linked_to,
available: `$${(b.available_amount / 100).toFixed(2)}`
}))
});
}

// Check overall platform liquidity
const totalAvailable = balances.reduce((sum, b) => sum + b.available_amount, 0);
const totalPosted = balances.reduce((sum, b) => sum + b.posted_amount, 0);
const liquidityRatio = (totalAvailable / totalPosted) * 100;

if (liquidityRatio < 50) {
await sendAlert('Low Platform Liquidity', {
liquidity_ratio: `${liquidityRatio.toFixed(2)}%`,
total_available: `$${(totalAvailable / 100).toLocaleString()}`,
total_posted: `$${(totalPosted / 100).toLocaleString()}`
});
}
}

// Run every 15 minutes
setInterval(monitorBalancesAndAlert, 15 * 60 * 1000);

5. Generate Regular Reports

Create automated balance reports:

async function generateDailyBalanceReport() {
const balances = await getAllBalances();

const report = {
date: new Date().toISOString().split('T')[0],
summary: {
total_balances: balances.length,
total_available: `$${(balances.reduce((sum, b) => sum + b.available_amount, 0) / 100).toLocaleString()}`,
total_pending: `$${(balances.reduce((sum, b) => sum + b.pending_amount, 0) / 100).toLocaleString()}`,
total_posted: `$${(balances.reduce((sum, b) => sum + b.posted_amount, 0) / 100).toLocaleString()}`
},
health_summary: {
healthy: balances.filter(b => b.available_amount > 100000).length,
low: balances.filter(b => b.available_amount > 50000 && b.available_amount <= 100000).length,
critical: balances.filter(b => b.available_amount <= 50000).length
},
by_application: {}
};

// Group by application
balances.forEach(balance => {
const appId = balance.linked_to;
if (!report.by_application[appId]) {
report.by_application[appId] = {
available: 0,
pending: 0,
posted: 0
};
}
report.by_application[appId].available += balance.available_amount;
report.by_application[appId].pending += balance.pending_amount;
report.by_application[appId].posted += balance.posted_amount;
});

// Send report
await sendDailyReport(report);

return report;
}

Common Workflows

Platform Health Check

async function performPlatformHealthCheck() {
const balances = await getAllBalances();

const health = {
status: 'HEALTHY',
issues: [],
metrics: {}
};

// Calculate totals
const totalAvailable = balances.reduce((sum, b) => sum + b.available_amount, 0);
const totalPosted = balances.reduce((sum, b) => sum + b.posted_amount, 0);

health.metrics = {
total_balances: balances.length,
liquidity_ratio: ((totalAvailable / totalPosted) * 100).toFixed(2) + '%',
total_available_formatted: `$${(totalAvailable / 100).toLocaleString()}`
};

// Check for issues
if (balances.some(b => b.available_amount === 0)) {
health.status = 'WARNING';
health.issues.push('Some balances have zero available funds');
}

if ((totalAvailable / totalPosted) < 0.3) {
health.status = 'CRITICAL';
health.issues.push('Platform liquidity below 30%');
}

const lowBalances = balances.filter(b => b.available_amount < 50000);
if (lowBalances.length > 0) {
health.issues.push(`${lowBalances.length} balances critically low`);
}

return health;
}

Balance Reconciliation

async function reconcileBalances() {
const balances = await getAllBalances();

const reconciliation = {
timestamp: new Date().toISOString(),
total_balances: balances.length,
by_status: {
healthy: [],
low: [],
critical: []
},
financial_totals: {
available: 0,
pending: 0,
posted: 0
}
};

balances.forEach(balance => {
reconciliation.financial_totals.available += balance.available_amount;
reconciliation.financial_totals.pending += balance.pending_amount;
reconciliation.financial_totals.posted += balance.posted_amount;

if (balance.available_amount > 100000) {
reconciliation.by_status.healthy.push(balance.id);
} else if (balance.available_amount > 50000) {
reconciliation.by_status.low.push(balance.id);
} else {
reconciliation.by_status.critical.push(balance.id);
}
});

// Verify posted = available + pending
balances.forEach(balance => {
if (balance.posted_amount !== balance.available_amount + balance.pending_amount) {
console.error('Balance mismatch detected:', {
balance_id: balance.id,
posted: balance.posted_amount,
calculated: balance.available_amount + balance.pending_amount
});
}
});

return reconciliation;
}

Interactive API Reference