Skip to main content

Fetch a Balance Transfer

Retrieve the details of a specific balance_transfer resource. This endpoint is essential for checking the status of a transfer, verifying completion, and retrieving transfer details for reconciliation.

Use Cases

1. Check Transfer Status

Verify if a balance transfer completed successfully:

curl https://api.ahrvo.network/payments/na/balance_transfers/BT_nRWVzeXvbou13Zg7UBNnYr \
-u username:password \
-H "Content-Type: application/json"

2. Poll Transfer Until Complete

Monitor a transfer until it reaches a final state:

async function waitForTransferCompletion(transferId, maxAttempts = 20) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

console.log(`Transfer ${transferId} status: ${transfer.state} (attempt ${attempt + 1})`);

if (transfer.state === 'SUCCEEDED') {
console.log('Transfer completed successfully');
return transfer;
}

if (transfer.state === 'FAILED') {
console.error('Transfer failed');
return transfer;
}

// Still pending, wait before next check
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
}

console.warn(`Transfer still pending after ${maxAttempts} attempts`);
return null;
}

3. Verify Transfer Details

Retrieve and verify specific transfer information:

async function verifyTransfer(transferId, expectedAmount, expectedDestination) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

// Verify amount
if (transfer.amount !== expectedAmount) {
throw new Error(
`Amount mismatch: expected ${expectedAmount}, got ${transfer.amount}`
);
}

// Verify destination
if (transfer.destination !== expectedDestination) {
throw new Error(
`Destination mismatch: expected ${expectedDestination}, got ${transfer.destination}`
);
}

// Verify state
if (transfer.state !== 'SUCCEEDED') {
throw new Error(`Transfer not successful: ${transfer.state}`);
}

console.log('Transfer verification passed:', transferId);
return transfer;
}

4. Get Transfer for Reconciliation

Fetch transfer details for accounting reconciliation:

async function getTransferForReconciliation(transferId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

// Extract reconciliation data
const reconciliationRecord = {
transfer_id: transfer.id,
date: transfer.created_at.split('T')[0],
amount: transfer.amount / 100, // Convert to dollars
source: transfer.source,
destination: transfer.destination,
state: transfer.state,
reference_id: transfer.reference_id,
description: transfer.description,
tags: transfer.tags
};

console.log('Reconciliation record:', reconciliationRecord);
return reconciliationRecord;
}

5. Check Failed Transfer

Investigate a failed transfer:

async function investigateFailedTransfer(transferId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

if (transfer.state !== 'FAILED') {
console.log(`Transfer ${transferId} is not failed (state: ${transfer.state})`);
return transfer;
}

// Analyze failure
console.error('Failed Transfer Analysis:', {
id: transfer.id,
amount: transfer.amount / 100,
source: transfer.source,
destination: transfer.destination,
created_at: transfer.created_at,
updated_at: transfer.updated_at,
description: transfer.description,
reference_id: transfer.reference_id,
processor_type: transfer.processor_type,
tags: transfer.tags
});

// Create incident report
await createIncidentReport('balance_transfer_failure', {
transfer_id: transferId,
amount: transfer.amount,
timestamp: transfer.created_at,
details: transfer
});

return transfer;
}

6. Retrieve Transfer with Retry Logic

Implement robust retrieval with automatic retries:

async function fetchTransferWithRetry(transferId, maxRetries = 3) {
let lastError;

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

if (!response.ok) {
if (response.status === 404) {
throw new Error(`Transfer ${transferId} not found`);
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

const transfer = await response.json();
return transfer;

} catch (error) {
lastError = error;
console.warn(`Attempt ${attempt + 1} failed:`, error.message);

if (attempt < maxRetries - 1) {
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}

throw new Error(`Failed to fetch transfer after ${maxRetries} attempts: ${lastError.message}`);
}

7. Get Transfer Age

Calculate how long ago a transfer was created:

async function getTransferAge(transferId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

const createdAt = new Date(transfer.created_at);
const now = new Date();
const ageMs = now - createdAt;

const ageMinutes = Math.floor(ageMs / 60000);
const ageHours = Math.floor(ageMinutes / 60);
const ageDays = Math.floor(ageHours / 24);

let ageString;
if (ageDays > 0) {
ageString = `${ageDays} day${ageDays > 1 ? 's' : ''} ago`;
} else if (ageHours > 0) {
ageString = `${ageHours} hour${ageHours > 1 ? 's' : ''} ago`;
} else {
ageString = `${ageMinutes} minute${ageMinutes > 1 ? 's' : ''} ago`;
}

return {
transfer_id: transferId,
created_at: transfer.created_at,
age_ms: ageMs,
age_minutes: ageMinutes,
age_hours: ageHours,
age_days: ageDays,
age_string: ageString,
state: transfer.state
};
}

8. Build Transfer Timeline

Create a timeline view of transfer events:

async function buildTransferTimeline(transferId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

const timeline = [
{
timestamp: transfer.created_at,
event: 'Transfer Created',
details: {
amount: transfer.amount,
source: transfer.source,
destination: transfer.destination,
description: transfer.description
}
}
];

// If updated_at is different from created_at, add update event
if (transfer.updated_at !== transfer.created_at) {
timeline.push({
timestamp: transfer.updated_at,
event: `Transfer ${transfer.state}`,
details: {
state: transfer.state,
reference_id: transfer.reference_id
}
});
}

// Sort by timestamp
timeline.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));

return {
transfer_id: transferId,
current_state: transfer.state,
timeline: timeline
};
}

9. Compare Transfer with Expected Values

Validate transfer matches expected parameters:

async function validateTransfer(transferId, expectedValues) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

const validationResults = {
transfer_id: transferId,
valid: true,
errors: []
};

// Check amount
if (expectedValues.amount && transfer.amount !== expectedValues.amount) {
validationResults.valid = false;
validationResults.errors.push({
field: 'amount',
expected: expectedValues.amount,
actual: transfer.amount
});
}

// Check source
if (expectedValues.source && transfer.source !== expectedValues.source) {
validationResults.valid = false;
validationResults.errors.push({
field: 'source',
expected: expectedValues.source,
actual: transfer.source
});
}

// Check destination
if (expectedValues.destination && transfer.destination !== expectedValues.destination) {
validationResults.valid = false;
validationResults.errors.push({
field: 'destination',
expected: expectedValues.destination,
actual: transfer.destination
});
}

// Check state
if (expectedValues.state && transfer.state !== expectedValues.state) {
validationResults.valid = false;
validationResults.errors.push({
field: 'state',
expected: expectedValues.state,
actual: transfer.state
});
}

if (!validationResults.valid) {
console.error('Transfer validation failed:', validationResults.errors);
}

return validationResults;
}

10. Export Transfer Details

Generate a detailed report of a specific transfer:

async function exportTransferDetails(transferId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);

const transfer = await response.json();

// Create detailed report
const report = {
'Transfer ID': transfer.id,
'Created At': new Date(transfer.created_at).toLocaleString(),
'Updated At': new Date(transfer.updated_at).toLocaleString(),
'Amount': `$${(transfer.amount / 100).toFixed(2)} ${transfer.currency}`,
'Source Account': transfer.source,
'Destination Account': transfer.destination,
'State': transfer.state,
'Description': transfer.description || 'N/A',
'Processor Type': transfer.processor_type,
'Reference ID': transfer.reference_id,
'External Reference ID': transfer.external_reference_id || 'N/A',
'Tags': JSON.stringify(transfer.tags || {}, null, 2)
};

// Format as readable text
const reportText = Object.entries(report)
.map(([key, value]) => `${key}: ${value}`)
.join('\n');

console.log('Transfer Report:\n', reportText);

return report;
}

Path Parameters

ParameterTypeRequiredDescription
balance_transfer_idstringYesThe unique ID of the balance transfer to retrieve

Response Fields

FieldTypeDescription
idstringUnique identifier for the balance transfer
created_atstringISO 8601 timestamp of when transfer was created
updated_atstringISO 8601 timestamp of last update
amountintegerAmount transferred in cents
currencystring3-letter ISO 4217 currency code (e.g., "USD")
descriptionstringHuman-readable description of the transfer
sourcestringSource account type (OPERATING_ACCOUNT or FOR_BENEFIT_OF_ACCOUNT)
destinationstringDestination account type (FOR_BENEFIT_OF_ACCOUNT or OPERATING_ACCOUNT)
statestringTransfer state: SUCCEEDED, FAILED, or PENDING
processor_typestringProcessor used for the transfer (e.g., "LITLE_V1")
reference_idstringInternal reference ID for tracking
external_reference_idstringExternal reference ID (if provided)
tagsobjectCustom metadata key-value pairs

Transfer States

SUCCEEDED

The transfer completed successfully and funds have been moved between accounts.

if (transfer.state === 'SUCCEEDED') {
console.log(`Transfer ${transfer.id} completed successfully`);
// Proceed with dependent operations
await updateAccountBalances();
await recordSuccessfulTransfer(transfer);
}

FAILED

The transfer failed and no funds were moved.

if (transfer.state === 'FAILED') {
console.error(`Transfer ${transfer.id} failed`);
// Investigate failure
await investigateFailedTransfer(transfer.id);
// Notify administrators
await notifyAdmins('Balance transfer failed', transfer);
// May need to retry or take corrective action
}

PENDING

The transfer is still being processed.

if (transfer.state === 'PENDING') {
console.log(`Transfer ${transfer.id} is pending`);
// Wait and check again
await new Promise(resolve => setTimeout(resolve, 5000));
await checkTransferStatus(transfer.id);
}

Best Practices

1. Check Transfer State

Always verify the transfer state before taking action:

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

const transfer = await response.json();

switch (transfer.state) {
case 'SUCCEEDED':
console.log('Transfer succeeded, updating records...');
await updateAccountingRecords(transfer);
break;

case 'FAILED':
console.error('Transfer failed, initiating recovery...');
await handleTransferFailure(transfer);
break;

case 'PENDING':
console.log('Transfer pending, will check again...');
await scheduleFutureCheck(transferId);
break;

default:
console.warn('Unknown transfer state:', transfer.state);
}
}

2. Handle 404 Errors

Handle cases where transfer doesn't exist:

async function safeGetTransfer(transferId) {
try {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

if (response.status === 404) {
console.error(`Transfer ${transferId} not found`);
return null;
}

if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

return await response.json();

} catch (error) {
console.error('Error fetching transfer:', error);
throw error;
}
}

3. Use Transfer Details for Audit

Store complete transfer details for auditing:

async function auditTransfer(transferId) {
const transfer = await fetchTransferWithRetry(transferId);

const auditRecord = {
audit_timestamp: new Date().toISOString(),
transfer_id: transfer.id,
transfer_created_at: transfer.created_at,
transfer_updated_at: transfer.updated_at,
amount: transfer.amount,
currency: transfer.currency,
source: transfer.source,
destination: transfer.destination,
state: transfer.state,
description: transfer.description,
reference_id: transfer.reference_id,
processor_type: transfer.processor_type,
tags: transfer.tags
};

// Store in audit log
await storeAuditRecord('balance_transfer', auditRecord);

return auditRecord;
}

4. Monitor Transfer Timing

Track how long transfers take to complete:

async function monitorTransferTiming(transferId) {
const transfer = await fetchTransferWithRetry(transferId);

const createdAt = new Date(transfer.created_at);
const updatedAt = new Date(transfer.updated_at);
const processingTime = updatedAt - createdAt;

const metrics = {
transfer_id: transferId,
created_at: createdAt.toISOString(),
updated_at: updatedAt.toISOString(),
processing_time_ms: processingTime,
processing_time_seconds: (processingTime / 1000).toFixed(2),
state: transfer.state
};

// Track metrics
if (processingTime > 30000) { // More than 30 seconds
console.warn('Slow transfer detected:', metrics);
await alertSlowTransfer(metrics);
}

return metrics;
}

5. Cache Transfer Details

Cache frequently accessed transfers:

class TransferDetailsCache {
constructor(ttl = 60000) { // 1 minute default TTL
this.cache = new Map();
this.ttl = ttl;
}

async get(transferId) {
const cached = this.cache.get(transferId);

if (cached && (Date.now() - cached.timestamp) < this.ttl) {
console.log(`Using cached transfer ${transferId}`);
return cached.transfer;
}

console.log(`Fetching fresh transfer ${transferId}`);
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${transferId}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

const transfer = await response.json();

// Only cache completed transfers (won't change)
if (transfer.state === 'SUCCEEDED' || transfer.state === 'FAILED') {
this.cache.set(transferId, {
transfer,
timestamp: Date.now()
});
}

return transfer;
}

invalidate(transferId) {
this.cache.delete(transferId);
}

clear() {
this.cache.clear();
}
}

const transferCache = new TransferDetailsCache();

6. Store Transfer Reference

Keep transfer IDs for future reference:

async function createAndStoreTransfer(transferData) {
// Create transfer
const createResponse = await fetch(
'https://api.ahrvo.network/payments/na/balance_transfers',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify(transferData)
}
);

const transfer = await createResponse.json();

// Store reference for later retrieval
await storeTransferReference({
transfer_id: transfer.id,
created_at: transfer.created_at,
amount: transfer.amount,
purpose: transferData.description,
tags: transferData.tags
});

return transfer;
}

async function retrieveStoredTransfer(transferId) {
// Get stored reference
const reference = await getTransferReference(transferId);

if (!reference) {
throw new Error(`No stored reference found for transfer ${transferId}`);
}

// Fetch current state
const transfer = await fetchTransferWithRetry(transferId);

return {
reference,
current: transfer
};
}

Common Workflows

Post-Creation Status Check

async function createAndVerifyTransfer(transferData) {
// 1. Create transfer
const createResponse = await fetch(
'https://api.ahrvo.network/payments/na/balance_transfers',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
},
body: JSON.stringify(transferData)
}
);

const transfer = await createResponse.json();
console.log('Transfer created:', transfer.id);

// 2. Wait for completion
const completedTransfer = await waitForTransferCompletion(transfer.id);

// 3. Verify final state
if (completedTransfer.state === 'SUCCEEDED') {
console.log('Transfer verified successful');
return completedTransfer;
} else {
throw new Error(`Transfer failed: ${completedTransfer.id}`);
}
}

Periodic Status Monitoring

async function monitorPendingTransfers(transferIds) {
const results = await Promise.all(
transferIds.map(async (id) => {
const response = await fetch(
`https://api.ahrvo.network/payments/na/balance_transfers/${id}`,
{
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
}
);

return await response.json();
})
);

const pending = results.filter(t => t.state === 'PENDING');
const succeeded = results.filter(t => t.state === 'SUCCEEDED');
const failed = results.filter(t => t.state === 'FAILED');

console.log('Transfer Status Summary:', {
pending: pending.length,
succeeded: succeeded.length,
failed: failed.length
});

return { pending, succeeded, failed };
}

Interactive API Reference