Get Account Balances

Overview

Retrieve your current account balances across all currencies. This endpoint shows:

  • Available balance (ready to withdraw)
  • Pending balance (payments being processed)
  • Total balance in USD equivalent

Use this endpoint to:

  • Display balance in your dashboard
  • Check available funds before initiating payouts
  • Monitor incoming payments
  • Track balances across multiple currencies

Authentication

Type: API Key (required)

Required Headers

Header Required Description
Authorization Yes Format: Bearer sk_test_... or Bearer sk_live_...

Request

Method & Path

GET /api/v1/accounts/balances

Example Request

curl https://api.usesyncpay.com/api/v1/accounts/balances \
  -H "Authorization: Bearer sk_live_abc123xyz..."

Response

200 – Success

Returns balances for all currencies in your account.

{
  "success": true,
  "account_id": "org_abc123",
  "balances": [
    {
      "currency": "USD",
      "available_balance": "1250.50",
      "pending_balance": "125.00"
    },
    {
      "currency": "NGN",
      "available_balance": "450000.00",
      "pending_balance": "75000.00"
    },
    {
      "currency": "GHS",
      "available_balance": "5600.00",
      "pending_balance": "0.00"
    },
    {
      "currency": "USDT_TRC20",
      "available_balance": "500.00",
      "pending_balance": "50.00"
    }
  ],
  "total_balance_usd": "2847.25"
}

Response Fields

Field Type Description
success boolean Always true for successful requests
account_id string Your organization ID
balances array Array of balance objects for each currency
balances[].currency string Currency code
balances[].available_balance string Funds available for withdrawal
balances[].pending_balance string Funds being processed (not yet available)
total_balance_usd string Total balance converted to USD

401 – Unauthorized

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}

404 – Not Found

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Organization not found"
  }
}

Cause: Your organization doesn't exist or has been deactivated.


Understanding Balance Types

Available Balance

What it is:

  • Funds that have been fully processed and settled
  • Ready for immediate withdrawal
  • Can be used for payouts

When funds become available:

  • Instantly for most fiat payments (bank transfer, mobile money)
  • After blockchain confirmations for crypto payments
  • After settlement period (if applicable to your account)

Pending Balance

What it is:

  • Funds from recently completed payments
  • Still being processed or confirmed
  • Not yet available for withdrawal

When funds are pending:

  • Payments awaiting final confirmation
  • Settlements being processed
  • Crypto payments with insufficient confirmations

How long it takes:

  • Most fiat payments: Instant to a few hours
  • Crypto payments: 3-60 minutes (depends on blockchain)
  • Bank transfers: Up to 24 hours in some regions

Automatic Balance Account Creation

When you first check your balances, SyncPay automatically creates balance accounts for:

  1. USD - Always created by default
  2. Your country currency - Based on your organization's country

Example:

  • Organization country: Nigeria (NG)
  • Automatic accounts created: USD and NGN

Additional currency accounts are created automatically when you receive your first payment in that currency.


Total Balance USD

The total_balance_usd field is the sum of all your balances converted to USD at current exchange rates:

total_balance_usd = sum(
  (available_balance + pending_balance) * exchange_rate_to_usd
)

Use for:

  • High-level financial overview
  • Multi-currency portfolio tracking
  • Simplified reporting

Note: This is an approximation using real-time exchange rates. Actual USD value may vary when withdrawing due to conversion fees and rate fluctuations.


Example Use Case

Scenario: Your financial dashboard needs to display real-time account balances across all currencies. Before allowing users to initiate withdrawals, the system must verify sufficient funds are available and prevent withdrawal attempts that would fail due to insufficient balance. The dashboard should show both available and pending balances to give users a complete financial picture.

Implementation:

async function getDashboardBalances() {
  const response = await fetch(
    'https://api.usesyncpay.com/api/v1/accounts/balances',
    {
      headers: {
        'Authorization': `Bearer ${process.env.SYNCPAY_API_KEY}`
      }
    }
  );
  
  const data = await response.json();
  
  return {
    totalUsd: parseFloat(data.total_balance_usd),
    currencies: data.balances.map(balance => ({
      currency: balance.currency,
      available: parseFloat(balance.available_balance),
      pending: parseFloat(balance.pending_balance),
      canWithdraw: parseFloat(balance.available_balance) >= getMinWithdrawal(balance.currency)
    }))
  };
}

function getMinWithdrawal(currency) {
  const minimums = {
    'USD': 10,
    'NGN': 5000,
    'GHS': 50,
    'USDT_TRC20': 10
  };
  return minimums[currency] || 10;
}

// Display in UI
async function renderBalanceDashboard() {
  const balances = await getDashboardBalances();
  
  console.log(`Total: $${balances.totalUsd.toFixed(2)} USD`);
  console.log('\nBy Currency:');
  
  for (const balance of balances.currencies) {
    console.log(`${balance.currency}:`);
    console.log(`  Available: ${balance.available}`);
    console.log(`  Pending: ${balance.pending}`);
    console.log(`  Can withdraw: ${balance.canWithdraw ? 'Yes' : 'No'}`);
  }
}

Balance Updates

Real-Time Updates

Balances are updated in real-time when:

  • A payment is completed (increases pending balance)
  • A payment settles (moves from pending to available)
  • A withdrawal is processed (decreases available balance)
  • A refund is issued (decreases available balance)

Polling for Updates

If building a real-time dashboard, poll this endpoint:

async function pollBalances(intervalMs = 30000) {
  async function fetchAndDisplay() {
    const balances = await getBalances();
    updateUI(balances);
  }
  
  // Initial fetch
  await fetchAndDisplay();
  
  // Poll every 30 seconds
  setInterval(fetchAndDisplay, intervalMs);
}

// Start polling
pollBalances(30000); // Every 30 seconds

Recommendation: Poll every 30-60 seconds for dashboards. Don't poll more frequently than every 10 seconds to avoid rate limits.


Zero Balances

If you have no balance in a currency, it may:

  • Still appear with "0.00" balances
  • Or not appear in the balances array at all

Handle both cases:

function getCurrencyBalance(balancesResponse, currency) {
  const balance = balancesResponse.balances.find(b => b.currency === currency);
  
  if (!balance) {
    return {
      available: 0,
      pending: 0
    };
  }
  
  return {
    available: parseFloat(balance.available_balance),
    pending: parseFloat(balance.pending_balance)
  };
}

Important Notes

Currency Precision

Balance amounts are returned as strings with appropriate decimal precision for each currency:

  • Fiat currencies: 2 decimals (e.g., "1250.50")
  • Cryptocurrencies: Up to 8 decimals (e.g., "0.12345678")

Always use strings to preserve precision when storing or displaying balances.


Test Mode vs Live Mode

Balance accounts are separate between test and live modes:

  • sk_test_... returns test mode balances
  • sk_live_... returns live mode balances
  • Test mode balances have no real monetary value

Minimum Withdrawal Amounts

Not all available balance can be withdrawn. Each currency has minimum withdrawal amounts:

Currency Minimum Withdrawal
USD $10.00
NGN ₦5,000
GHS GH₵50
KES KSh500
USDT_TRC20 $10.00
USDT_ERC20 $50.00 (due to gas fees)

Check before initiating withdrawal:

async function canWithdraw(currency, amount) {
  const balances = await getBalances();
  const currencyBalance = balances.balances.find(b => b.currency === currency);
  
  if (!currencyBalance) return false;
  
  const available = parseFloat(currencyBalance.available_balance);
  const minimum = getMinWithdrawal(currency);
  
  return available >= amount && amount >= minimum;
}

Balance Reconciliation

If your calculated balance doesn't match the API response:

  1. Check pending settlements - Payments may still be processing
  2. Review withdrawals - Recent withdrawals reduce available balance
  3. Check refunds - Refunds decrease balance
  4. Verify environment - Ensure you're checking the correct mode (test vs live)
  5. Contact support - If discrepancy persists

Caching Strategies

For dashboards with multiple components requesting balances:

class BalanceCache {
  constructor(ttlMs = 30000) {
    this.cache = null;
    this.ttl = ttlMs;
    this.lastFetch = 0;
  }
  
  async getBalances() {
    const now = Date.now();
    
    // Return cached if still fresh
    if (this.cache && (now - this.lastFetch) < this.ttl) {
      return this.cache;
    }
    
    // Fetch fresh data
    const response = await fetch(
      'https://api.usesyncpay.com/api/v1/accounts/balances',
      { headers: { 'Authorization': `Bearer ${API_KEY}` } }
    );
    
    this.cache = await response.json();
    this.lastFetch = now;
    
    return this.cache;
  }
  
  invalidate() {
    this.cache = null;
    this.lastFetch = 0;
  }
}

// Usage
const balanceCache = new BalanceCache(30000); // 30 second TTL

// Multiple calls within 30s will use cache
const balances1 = await balanceCache.getBalances(); // API call
const balances2 = await balanceCache.getBalances(); // From cache
const balances3 = await balanceCache.getBalances(); // From cache

// After withdrawal, invalidate cache
await createWithdrawal(...);
balanceCache.invalidate();
const freshBalances = await balanceCache.getBalances(); // New API call


Next Steps

After checking your balances:

  1. Initiate withdrawals using Create Withdrawal
  2. Set up payout destinations for each currency you want to withdraw
  3. Monitor balance trends to understand your revenue flow
  4. Set up alerts when available balance reaches certain thresholds