Create Balance Adjustment
Overview
Create a Balance Adjustment to increase (top-up) or decrease (deduction) your account balance for payouts. Balance adjustments allow you to manage your payout account balance by adding funds via ACH or wire transfer, or deducting funds as needed.
Resource Access
- User Permissions: ROLE_PARTNER or ROLE_PLATFORM credentials only
- Endpoint:
POST /balance_adjustments
Arguments
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | integer | Yes | Amount of adjustment in cents |
| currency | string | Yes | 3-letter ISO 4217 currency code (e.g., USD) |
| instrument_id | string | Yes | ID of the payment instrument |
| type | string | Yes | Type of adjustment (TOP_UP, DEDUCTION) |
| description | string | No | Description of the balance adjustment |
| processor | string | No | Processor to use for the adjustment |
| rail | string | No | Payment rail (ACH, WIRE) |
| tags | object | No | Key-value metadata pairs |
Adjustment Types
| Type | Description |
|---|---|
| TOP_UP | Add funds to account balance (credit) |
| DEDUCTION | Remove funds from account balance (debit) |
Payment Rails
| Rail | Description |
|---|---|
| ACH | Automated Clearing House (standard, 1-3 business days) |
| WIRE | Wire transfer (faster, same or next business day) |
Example Requests
Basic Top-Up via ACH
curl -X POST \
'https://api.ahrvo.network/payments/na/balance_adjustments' \
-u username:password \
-H 'Content-Type: application/json' \
-d '{
"amount": 10000,
"currency": "USD",
"description": "Weekly balance top-up",
"instrument_id": "PI4Ppf8rxWYapuEqQr3u6efi",
"processor": "DUMMY_V1",
"rail": "ACH",
"type": "TOP_UP",
"tags": {
"purpose": "weekly_topup"
}
}'
Top-Up via Wire Transfer
curl -X POST \
'https://api.ahrvo.network/payments/na/balance_adjustments' \
-u username:password \
-H 'Content-Type: application/json' \
-d '{
"amount": 50000,
"currency": "USD",
"description": "Urgent balance top-up",
"instrument_id": "PI4Ppf8rxWYapuEqQr3u6efi",
"processor": "DUMMY_V1",
"rail": "WIRE",
"type": "TOP_UP",
"tags": {
"urgency": "high",
"purpose": "emergency_funds"
}
}'
Balance Deduction
curl -X POST \
'https://api.ahrvo.network/payments/na/balance_adjustments' \
-u username:password \
-H 'Content-Type: application/json' \
-d '{
"amount": 5000,
"currency": "USD",
"description": "Fee correction deduction",
"instrument_id": "PI4Ppf8rxWYapuEqQr3u6efi",
"processor": "DUMMY_V1",
"rail": "ACH",
"type": "DEDUCTION",
"tags": {
"reason": "fee_correction"
}
}'
Example Response
{
"id": "balance_adjustment_cjWuGyhvBxEmgcUmxCzpvc",
"created_at": "2025-09-01T15:07:20.985846Z",
"updated_at": "2025-09-01T15:07:21.912828Z",
"amount": 10000,
"balance_entry_id": "balance_entry_corsu3cQg1TBLJJbmMyK3o",
"currency": "USD",
"description": "Weekly balance top-up",
"failure_code": null,
"failure_message": null,
"instrument_id": "PI4Ppf8rxWYapuEqQr3u6efi",
"rail": "ACH",
"state": "SUCCEEDED",
"tags": {
"purpose": "weekly_topup"
},
"top_up_config_id": null,
"trace_id": "7b44bd4e-31b0-4f34-afea-1d13526654b3",
"type": "TOP_UP",
"_links": {
"self": {
"href": "https://api.ahrvo.network/payments/na/balance_adjustments/balance_adjustment_cjWuGyhvBxEmgcUmxCzpvc"
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| id | string | Unique balance adjustment ID |
| created_at | string | Timestamp when created |
| updated_at | string | Timestamp when last updated |
| amount | integer | Adjustment amount in cents |
| balance_entry_id | string | ID of associated balance entry |
| currency | string | Currency code |
| description | string | Adjustment description |
| failure_code | string | Failure code (if failed) |
| failure_message | string | Failure message (if failed) |
| instrument_id | string | Payment instrument ID |
| rail | string | Payment rail used (ACH, WIRE) |
| state | string | State (SUCCEEDED, FAILED, PENDING) |
| tags | object | Metadata tags |
| top_up_config_id | string | Auto top-up configuration ID (if applicable) |
| trace_id | string | Trace ID for tracking |
| type | string | Adjustment type (TOP_UP, DEDUCTION) |
Adjustment States
| State | Description |
|---|---|
| SUCCEEDED | Adjustment completed successfully |
| FAILED | Adjustment failed |
| PENDING | Adjustment in progress |
Additional Information
-
Balance Entry Creation: Each adjustment creates a balance entry
balance_entry_idlinks to balance ledger- Balance entries track all balance changes
- Use for reconciliation and reporting
-
Top-Up vs Deduction: Direction matters
- TOP_UP: Adds funds to your balance (credit)
- DEDUCTION: Removes funds from your balance (debit)
- Amount is always positive (direction determined by type)
-
Payment Rails: Speed and cost differences
- ACH: Standard processing (1-3 business days), lower cost
- WIRE: Expedited processing (same/next day), higher fees
- Choose based on urgency and cost considerations
-
Payment Instrument: Bank account required
- Must be a verified bank account
- Used for ACH pulls/pushes
- Verify account before first use
-
Processing Time: Varies by rail
- ACH: 1-3 business days to settle
- WIRE: Same or next business day
- State changes from PENDING to SUCCEEDED when complete
-
Use Cases: When to adjust balance
- Top-Up: Ensure sufficient funds for payouts
- Top-Up: Prepare for high-volume payout periods
- Deduction: Correct overfunded accounts
- Deduction: Platform fee collection
Use Cases
Weekly Top-Up for Payouts
// Automatically top up balance for upcoming payouts
async function weeklyBalanceTopUp(instrumentId, amount) {
console.log('Creating weekly balance top-up...');
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: amount,
currency: 'USD',
description: `Weekly top-up for ${new Date().toISOString().split('T')[0]}`,
instrument_id: instrumentId,
rail: 'ACH',
type: 'TOP_UP',
tags: {
schedule: 'weekly',
automated: 'true',
week_of: new Date().toISOString().split('T')[0]
}
})
}
);
const adjustment = await response.json();
console.log('✓ Balance top-up created');
console.log(` Amount: $${adjustment.amount / 100}`);
console.log(` State: ${adjustment.state}`);
console.log(` Rail: ${adjustment.rail}`);
console.log(` Balance Entry: ${adjustment.balance_entry_id}`);
return adjustment;
}
Urgent Wire Top-Up
// Urgent top-up using wire transfer for same-day processing
async function urgentWireTopUp(instrumentId, amount, reason) {
console.log('Creating urgent wire top-up...');
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: amount,
currency: 'USD',
description: `Urgent wire top-up - ${reason}`,
instrument_id: instrumentId,
rail: 'WIRE',
type: 'TOP_UP',
tags: {
urgency: 'high',
reason: reason,
requested_by: 'finance_team'
}
})
}
);
const adjustment = await response.json();
console.log('✓ Urgent wire top-up initiated');
console.log(` Amount: $${adjustment.amount / 100}`);
console.log(` Expected: Same or next business day`);
console.log(` Reason: ${reason}`);
return adjustment;
}
// Usage
await urgentWireTopUp(
'PI4Ppf8rxWYapuEqQr3u6efi',
100000, // $1,000.00
'High volume payout period'
);
Smart Balance Top-Up
// Check balance and top up if below threshold
async function smartBalanceTopUp(instrumentId, threshold, topUpAmount) {
console.log('Checking balance...');
// Fetch current balance
const balanceResponse = await fetch(
'https://api.ahrvo.network/payments/na/balances',
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balances = await balanceResponse.json();
const currentBalance = balances.payouts_balance || 0;
console.log(`Current balance: $${currentBalance / 100}`);
console.log(`Threshold: $${threshold / 100}`);
if (currentBalance < threshold) {
console.log('Balance below threshold - initiating top-up...');
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: topUpAmount,
currency: 'USD',
description: 'Automatic balance top-up (threshold triggered)',
instrument_id: instrumentId,
rail: 'ACH',
type: 'TOP_UP',
tags: {
automated: 'true',
trigger: 'threshold',
previous_balance: currentBalance.toString()
}
})
}
);
const adjustment = await response.json();
console.log('✓ Top-up created');
console.log(` Top-up amount: $${topUpAmount / 100}`);
console.log(` New balance (pending): $${(currentBalance + topUpAmount) / 100}`);
return adjustment;
} else {
console.log('✓ Balance sufficient - no top-up needed');
return null;
}
}
// Usage
await smartBalanceTopUp(
'PI4Ppf8rxWYapuEqQr3u6efi',
50000, // $500.00 threshold
100000 // $1,000.00 top-up amount
);
Balance Deduction for Fee Collection
// Deduct platform fees from balance
async function collectPlatformFees(instrumentId, feeAmount, period) {
console.log(`Collecting platform fees for ${period}...`);
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: feeAmount,
currency: 'USD',
description: `Platform fees - ${period}`,
instrument_id: instrumentId,
rail: 'ACH',
type: 'DEDUCTION',
tags: {
fee_type: 'platform',
period: period,
collected_at: new Date().toISOString()
}
})
}
);
const adjustment = await response.json();
console.log('✓ Platform fees deducted');
console.log(` Amount: $${adjustment.amount / 100}`);
console.log(` Period: ${period}`);
console.log(` Balance Entry: ${adjustment.balance_entry_id}`);
return adjustment;
}
// Usage
await collectPlatformFees(
'PI4Ppf8rxWYapuEqQr3u6efi',
25000, // $250.00 in fees
'December 2024'
);
Batch Balance Adjustments
// Create multiple balance adjustments in batch
async function batchBalanceAdjustments(adjustments) {
console.log(`Processing ${adjustments.length} balance adjustments...\n`);
const results = {
successful: [],
failed: []
};
for (const adj of adjustments) {
try {
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify(adj)
}
);
const adjustment = await response.json();
results.successful.push({
id: adjustment.id,
type: adjustment.type,
amount: adjustment.amount
});
console.log(`✓ ${adjustment.type} - $${adjustment.amount / 100}`);
} catch (error) {
results.failed.push({
adjustment: adj,
error: error.message
});
console.log(`✗ Failed: ${error.message}`);
}
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
console.log(`\n=== Batch Complete ===`);
console.log(`Successful: ${results.successful.length}`);
console.log(`Failed: ${results.failed.length}`);
return results;
}
// Usage
await batchBalanceAdjustments([
{
amount: 50000,
currency: 'USD',
description: 'Merchant A payout funding',
instrument_id: 'PI4Ppf8rxWYapuEqQr3u6efi',
rail: 'ACH',
type: 'TOP_UP'
},
{
amount: 30000,
currency: 'USD',
description: 'Merchant B payout funding',
instrument_id: 'PI4Ppf8rxWYapuEqQr3u6efi',
rail: 'ACH',
type: 'TOP_UP'
}
]);
Monitor Adjustment Status
// Create adjustment and monitor until completion
async function createAndMonitorAdjustment(adjustmentData) {
console.log('Creating balance adjustment...');
const response = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify(adjustmentData)
}
);
let adjustment = await response.json();
console.log('✓ Adjustment created');
console.log(` ID: ${adjustment.id}`);
console.log(` Initial state: ${adjustment.state}`);
// Monitor status if pending
if (adjustment.state === 'PENDING') {
console.log('\nMonitoring status...');
let attempts = 0;
const maxAttempts = 20;
while (adjustment.state === 'PENDING' && attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 5000));
const statusResponse = await fetch(
`https://api.ahrvo.network/payments/na/balance_adjustments/${adjustment.id}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
adjustment = await statusResponse.json();
attempts++;
console.log(` Check ${attempts}: ${adjustment.state}`);
}
}
if (adjustment.state === 'SUCCEEDED') {
console.log('\n✓ Adjustment completed successfully');
} else if (adjustment.state === 'FAILED') {
console.log('\n✗ Adjustment failed');
console.log(` Failure: ${adjustment.failure_message}`);
}
return adjustment;
}
Best Practices
-
Verify Instrument: Ensure payment instrument is valid
// Check instrument before creating adjustment
const instrument = await fetchPaymentInstrument(instrumentId);
if (instrument.type === 'BANK_ACCOUNT' && instrument.verified) {
await createBalanceAdjustment(instrumentId, amount);
} -
Choose Right Rail: Based on urgency
- Use ACH for standard, cost-effective top-ups
- Use WIRE for urgent, time-sensitive needs
- Consider wire fees vs urgency trade-off
-
Monitor Balance: Proactive management
- Set up alerts for low balance
- Automate top-ups at thresholds
- Plan for high-volume periods
-
Document Adjustments: Clear descriptions
{
description: "Weekly payout funding - Week of Dec 10, 2024",
tags: {
purpose: "payout_funding",
week: "2024-12-10",
scheduled: "true"
}
} -
Track with Tags: Comprehensive metadata
- Purpose of adjustment
- Automated vs manual
- Business context
- Approval references
-
Handle Errors: Robust error handling
try {
const adjustment = await createBalanceAdjustment(data);
if (adjustment.state === 'FAILED') {
console.error('Adjustment failed:', adjustment.failure_message);
}
} catch (error) {
console.error('API error:', error);
}
Common Workflows
Pre-Payout Balance Check
// Ensure sufficient balance before creating payouts
async function ensureSufficientBalance(requiredAmount, instrumentId) {
console.log('=== Pre-Payout Balance Check ===\n');
// Step 1: Check current balance
console.log('Step 1: Checking current balance...');
const balanceResponse = await fetch(
'https://api.ahrvo.network/payments/na/balances',
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);
const balances = await balanceResponse.json();
const currentBalance = balances.payouts_balance || 0;
console.log(` Current: $${currentBalance / 100}`);
console.log(` Required: $${requiredAmount / 100}`);
// Step 2: Top up if needed
if (currentBalance < requiredAmount) {
const shortfall = requiredAmount - currentBalance;
const topUpAmount = shortfall + 10000; // Add $100 buffer
console.log(`\nStep 2: Insufficient balance - topping up $${topUpAmount / 100}...`);
const adjustment = await fetch(
'https://api.ahrvo.network/payments/na/balance_adjustments',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: topUpAmount,
currency: 'USD',
description: 'Pre-payout balance top-up',
instrument_id: instrumentId,
rail: 'ACH',
type: 'TOP_UP',
tags: {
reason: 'payout_preparation',
shortfall: shortfall.toString()
}
})
}
).then(r => r.json());
console.log('✓ Top-up initiated');
console.log(` Adjustment ID: ${adjustment.id}`);
return { sufficient: false, topUpCreated: true, adjustment };
} else {
console.log('\n✓ Sufficient balance available');
return { sufficient: true, topUpCreated: false };
}
}
Security Considerations
-
Access Control: Platform/Partner only
- Only ROLE_PARTNER or ROLE_PLATFORM can create adjustments
- Not available to merchant users
- Verify credentials before use
-
Audit Trail: Track all adjustments
- Log who created adjustment
- Log when and why
- Use tags for detailed tracking
- Review adjustment history regularly
-
Amount Validation: Prevent errors
- Validate amount is reasonable
- Check for typos (extra zeros)
- Confirm deductions don't overdraw
- Implement approval workflows for large amounts
-
Instrument Verification: Use verified accounts
- Only use verified bank accounts
- Verify account ownership
- Validate routing/account numbers
Error Responses
Unauthorized
{
"_embedded": {
"errors": [
{
"message": "Authentication credentials are invalid"
}
]
}
}
Forbidden
{
"_embedded": {
"errors": [
{
"message": "User does not have permission to perform this action"
}
]
}
}
Invalid Parameters
{
"status": 400,
"message": "Invalid request parameters",
"details": "Amount must be a positive integer"
}
Troubleshooting
Adjustment Fails - Insufficient Funds (Deduction)
- Check current balance before deduction
- Deduction amount exceeds available balance
- Reduce deduction amount
- Top up first if needed
Adjustment Stuck in PENDING
- ACH takes 1-3 business days
- Wire takes 1 business day
- Check during business hours
- Contact support if delayed >3 days
Invalid Instrument
- Payment instrument not found
- Instrument not verified
- Instrument not a bank account
- Verify instrument ID and type
Related Endpoints
- GET /balance_adjustments: List all balance adjustments
- GET /balances: Check current balance
- GET /payment_instruments/{id}: Verify payment instrument
- POST /balance_transfers: Transfer between balances