Balance Management API
This document describes the Balance Management endpoints for querying customer and account balances in Link Core.
Endpoints
- Get Customer Balances -
GET /balances/customer/:customerId - Get Account Balances -
GET /balances/account/:accountId
Get Customer Balances
Retrieves all asset balances for a specific customer across all their accounts.
Endpoint: GET /balances/customer/:customerId
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Customer identifier |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
filter[assetCode] | string | No | Filter by specific asset code (e.g., "BTC") |
filter[assetId] | string (UUID) | No | Filter by specific asset ID |
filter[accountId] | string | No | Filter by specific account ID |
Response
Status: 200 OK
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
},
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Response Fields
| Field | Type | Description |
|---|---|---|
customerId | string | Customer identifier |
accountId | string | Account identifier |
assetId | string (UUID) | Digital asset identifier |
assetCode | string | Asset ticker symbol (e.g., "BTC", "ETH") |
assetName | string | Asset display name |
availableBalance | string | Available balance (spendable) |
frozenBalance | string | Frozen balance (pending transactions, holds) |
totalBalance | string | Total balance (available + frozen) |
Examples
Get All Balances for Customer
curl -X GET "https://api.ledgerlink.ai/v1/balances/customer/customer-123"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
},
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
},
{
"customerId": "customer-123",
"accountId": "account-789",
"assetId": "usdc-asset-id",
"assetCode": "USDC",
"assetName": "USD Coin",
"availableBalance": "5000.00",
"frozenBalance": "0.0",
"totalBalance": "5000.00"
}
]
Filter by Specific Asset Code
curl -X GET "https://api.ledgerlink.ai/v1/balances/customer/customer-123?filter[assetCode]=BTC"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
}
]
Filter by Asset ID
curl -X GET "https://api.ledgerlink.ai/v1/balances/customer/customer-123?filter[assetId]=eth-asset-id"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Filter by Specific Account
curl -X GET "https://api.ledgerlink.ai/v1/balances/customer/customer-123?filter[accountId]=account-456"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
},
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Error Responses
404 Not Found
{
"statusCode": 404,
"message": "Customer not found",
"error": "Not Found"
}
Causes:
- Customer ID does not exist
- No balances found for customer
400 Bad Request
{
"statusCode": 400,
"message": "Invalid filter parameters",
"error": "Bad Request"
}
Causes:
- Invalid UUID format for
assetId - Invalid filter syntax
Get Account Balances
Retrieves all asset balances for a specific account.
Endpoint: GET /balances/account/:accountId
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | Account identifier |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
filter[assetCode] | string | No | Filter by specific asset code (e.g., "BTC") |
filter[assetId] | string (UUID) | No | Filter by specific asset ID |
Response
Status: 200 OK
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
},
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Examples
Get All Balances for Account
curl -X GET "https://api.ledgerlink.ai/v1/balances/account/account-456"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "btc-asset-id",
"assetCode": "BTC",
"assetName": "Bitcoin",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
},
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Filter by Asset Code
curl -X GET "https://api.ledgerlink.ai/v1/balances/account/account-456?filter[assetCode]=ETH"
Response:
[
{
"customerId": "customer-123",
"accountId": "account-456",
"assetId": "eth-asset-id",
"assetCode": "ETH",
"assetName": "Ethereum",
"availableBalance": "10.25",
"frozenBalance": "2.5",
"totalBalance": "12.75"
}
]
Error Responses
404 Not Found
{
"statusCode": 404,
"message": "Account not found",
"error": "Not Found"
}
Causes:
- Account ID does not exist
- No balances found for account
Balance Concepts
Available Balance
The available balance represents the amount that can be immediately used for transactions:
Available Balance = Total Balance - Frozen Balance
Use Cases:
- Check if customer can withdraw requested amount
- Display spendable balance in UI
- Validate transaction requests
Frozen Balance
The frozen balance represents amounts that are temporarily locked:
Common Reasons for Frozen Balance:
- Pending withdrawals awaiting screening
- Pending deposits awaiting confirmation
- Transactions flagged for manual review (status:
FROZEN) - Risk management holds
- Regulatory compliance holds
Frozen Balance Lifecycle:
- Transaction created → Amount frozen
- Transaction approved → Amount unfrozen, processed
- Transaction rejected → Amount unfrozen, returned
Total Balance
The total balance is the sum of available and frozen amounts:
Total Balance = Available Balance + Frozen Balance
Use Cases:
- Display total holdings in portfolio
- Calculate net worth
- Reporting and analytics
Balance Filtering
By Asset Code
Filter balances by asset ticker symbol (case-insensitive):
GET /balances/customer/:customerId?filter[assetCode]=BTC
GET /balances/customer/:customerId?filter[assetCode]=eth
By Asset ID
Filter balances by specific asset UUID:
GET /balances/customer/:customerId?filter[assetId]=btc-asset-id
By Account ID (Customer Endpoint Only)
When querying customer balances, filter to a specific account:
GET /balances/customer/:customerId?filter[accountId]=account-456
Multiple Filters
Combine filters (implementation-dependent):
GET /balances/customer/:customerId?filter[assetCode]=BTC&filter[accountId]=account-456
Common Use Cases
Check Withdrawal Eligibility
Before initiating a withdrawal, verify sufficient available balance:
# Get balance
GET /balances/customer/customer-123?filter[assetCode]=BTC
# Response
[
{
"assetCode": "BTC",
"availableBalance": "1.5",
"frozenBalance": "0.0",
"totalBalance": "1.5"
}
]
# Can withdraw up to 1.5 BTC
Display Portfolio
Get all balances for portfolio display:
GET /balances/customer/customer-123
Display totalBalance for each asset in portfolio UI.
Monitor Frozen Amounts
Check frozen balances to track pending transactions:
GET /balances/customer/customer-123
# Look for assets with frozenBalance > 0
[
{
"assetCode": "ETH",
"availableBalance": "10.25",
"frozenBalance": "2.5", // ← 2.5 ETH locked
"totalBalance": "12.75"
}
]
Account-Specific Balances
For multi-account customers, query specific account:
# Get balances for specific account
GET /balances/account/account-456
# Or filter customer balances by account
GET /balances/customer/customer-123?filter[accountId]=account-456
Integration Notes
Balance Updates
Balances are updated automatically by Link Core:
Deposits:
- Transaction created → No balance change
- Screening approved → Amount frozen (if implemented)
- Transaction completed → Available balance increased
Withdrawals:
- Transaction created → Amount frozen (deducted from available)
- Screening approved → Blockchain transaction initiated
- Transaction completed → Frozen amount removed (already deducted)
Rejections:
- Transaction rejected → Frozen amount returned to available
Real-time Balances
Balance queries return real-time data:
- No caching by default
- Always reflects latest transaction state
- Suitable for transaction validation
Precision
All balance amounts are returned as decimal strings to preserve precision:
{
"availableBalance": "1.50000000",
"frozenBalance": "0.00000000",
"totalBalance": "1.50000000"
}
Important: Use decimal/BigDecimal libraries for arithmetic, never floating-point.
Empty Balances
If no balances exist for a customer/account:
[]
An empty array is returned (not an error).
Error Handling
Customer/Account Not Found
If the customer or account doesn't exist, a 404 error is returned:
{
"statusCode": 404,
"message": "Customer not found",
"error": "Not Found"
}
Recommendation: Create customer/account first before querying balances.
Invalid Filters
If filter parameters are invalid:
{
"statusCode": 400,
"message": "Invalid filter parameters",
"error": "Bad Request"
}
Common Issues:
- Malformed UUID in
filter[assetId] - Invalid filter syntax
Best Practices
1. Filter by Asset When Possible
For better performance, filter by specific asset:
# Good: Specific asset query
GET /balances/customer/customer-123?filter[assetCode]=BTC
# Slower: All assets
GET /balances/customer/customer-123
2. Use Available Balance for Validations
Always check availableBalance before initiating withdrawals:
const balance = await getCustomerBalances(customerId, { assetCode: 'BTC' });
if (parseFloat(balance.availableBalance) < withdrawalAmount) {
throw new Error('Insufficient available balance');
}
3. Display Both Available and Total
In UI, show both balances for transparency:
BTC Balance
Available: 1.5 BTC
Frozen: 0.0 BTC
Total: 1.5 BTC
4. Handle Zero Balances
Display assets with zero balance based on UI requirements:
// Option 1: Show all assets (including zero)
const allBalances = await getCustomerBalances(customerId);
// Option 2: Filter out zero balances
const nonZeroBalances = allBalances.filter(b =>
parseFloat(b.totalBalance) > 0
);
Need Help? Contact helpdesk@ledgerlink.ai for assistance.