Skip to main content

Transfer Between Budget Accounts

Overview

Use this endpoint to transfer funds between two budget accounts. This enables flexible budget management, allowing you to reallocate funds between departments, projects, or card programs as business needs change.

NOTE: This API is offered on a client-by-client approval basis. Speak to your account manager to check eligibility.

Resource Access

Production (api.ahrvo.network)

POST https://api.ahrvo.network/card/issuance/api/issuing/budget/v2/transfer

Staging (gateway.ahrvo.network)

POST https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/transfer

Request Headers

HeaderValueRequiredDescription
Acceptapplication/jsonYesContent type for the response
Content-Typeapplication/jsonYesContent type of the request body
AuthorizationBearer {access_token}YesBearer token for authentication
x-api-keyAPI KeyYesAPI key for authentication

Request Body

FieldTypeRequiredDescription
source_budget_idstringYesThe unique ID of the budget account from which funds are transferred (debited)
target_budget_idstringYesThe unique ID of the budget account to which funds are transferred (credited)
transfer_amountstringYesThe amount of funds to be transferred. Must be a positive number with up to 2 decimal places
source_currencystringYesCurrency in which the source budget will be debited. Must follow ISO 4217 standard (e.g., USD, EUR, GBP)
target_currencystringYesCurrency in which the target budget will be credited. Must follow ISO 4217 standard. Can differ from source for currency conversion

Request Example

{
"source_budget_id": "ci202008281528472924",
"target_budget_id": "ci202105241445228411",
"transfer_amount": "802.90",
"source_currency": "USD",
"target_currency": "USD"
}

Response

Success Response (200 OK)

{
"code": "SUCCESS",
"data": {
"transfer_order_id": "toi202311021736413952",
"in_amount": "802.90"
}
}

Response Fields

FieldTypeDescription
codestringStatus string indicating the result of the request. "SUCCESS" refers to a successful initiation
dataobjectResponse data object
data.transfer_order_idstringA unique ID for the fund transfer order generated by the system. Use this to query the transfer status
data.in_amountstringThe amount of funds transferred, denominated in the target_currency (after any currency conversion if applicable)

Error Responses

  • 400 Bad Request: Invalid parameters, insufficient funds in source budget, or invalid amount format
  • 401 Unauthorized: Invalid or missing authentication token
  • 403 Forbidden: Card issuance feature not enabled for this account
  • 404 Not Found: One or both budget accounts do not exist

Code Examples

cURL

curl -X POST \
https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/transfer \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{
"source_budget_id": "ci202008281528472924",
"target_budget_id": "ci202105241445228411",
"transfer_amount": "802.90",
"source_currency": "USD",
"target_currency": "USD"
}'

Python

import requests
import time

url = "https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/transfer"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"source_budget_id": "ci202008281528472924",
"target_budget_id": "ci202105241445228411",
"transfer_amount": "802.90",
"source_currency": "USD",
"target_currency": "USD"
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
transfer_order_id = result['data']['transfer_order_id']
in_amount = result['data']['in_amount']

print(f"✓ Transfer initiated successfully")
print(f" Transfer Order ID: {transfer_order_id}")
print(f" Amount (Target Currency): {in_amount}")
print(f"\nUse the transfer order ID to check status with Query Transfer Order endpoint")
else:
print(f"Failed to initiate transfer: {result}")

JavaScript (Node.js)

const axios = require('axios');

const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/transfer';
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const payload = {
source_budget_id: 'ci202008281528472924',
target_budget_id: 'ci202105241445228411',
transfer_amount: '802.90',
source_currency: 'USD',
target_currency: 'USD'
};

axios.post(url, payload, { headers })
.then(response => {
const result = response.data;

if (result.code === 'SUCCESS') {
console.log('✓ Transfer initiated successfully');
console.log(` Transfer Order ID: ${result.data.transfer_order_id}`);
console.log(` Amount (Target Currency): ${result.data.in_amount}`);
console.log('\nUse the transfer order ID to check status with Query Transfer Order endpoint');
}
})
.catch(error => {
console.error('Failed to initiate transfer:', error.response.data);
});

Usage Notes

  • Asynchronous Processing: Transfers are processed asynchronously. The successful response means the request was accepted, not that funds have been transferred
  • Status Verification: Use the Query Budget Transfer Order endpoint with transfer_order_id to check if the transfer succeeded
  • Sufficient Balance: Ensure the source budget has sufficient funds before initiating transfer
  • Amount Format: Provide amounts as strings with up to 2 decimal places (e.g., "802.90" not 802.90)
  • Currency Conversion: If source and target currencies differ, conversion will be applied automatically
  • Same Account: Cannot transfer between the same budget account (source and target must differ)

Common Use Cases

Basic Transfer with Status Verification

Transfer funds and verify completion:

def transfer_with_verification(source_id, target_id, amount, currency='USD'):
"""
Transfer funds between budgets and verify completion
"""
import time

# Initiate transfer
print(f"Initiating transfer of {currency} {amount}...")
response = initiate_budget_transfer(
source_budget_id=source_id,
target_budget_id=target_id,
transfer_amount=str(amount),
source_currency=currency,
target_currency=currency
)

if response['code'] == 'SUCCESS':
transfer_order_id = response['data']['transfer_order_id']
in_amount = response['data']['in_amount']

print(f"✓ Transfer initiated")
print(f" Transfer Order ID: {transfer_order_id}")
print(f" Target Amount: {currency} {in_amount}")

# Poll for completion
print("\nChecking transfer status...")
max_attempts = 10

for attempt in range(max_attempts):
time.sleep(3)

status_response = query_budget_transfer_order(transfer_order_id)

if status_response['code'] == 'SUCCESS':
fund_result = status_response['data']['fund_result']

if fund_result == 'SUCCESS':
print(f"✓ Transfer completed successfully")
return {
'success': True,
'transfer_order_id': transfer_order_id,
'amount': in_amount
}
elif fund_result == 'FAILED':
print(f"✗ Transfer failed")
return {
'success': False,
'transfer_order_id': transfer_order_id
}

print(f"⏳ Attempt {attempt + 1}/{max_attempts}: Still processing...")

print("⚠ Transfer status check timed out")
return {
'success': None,
'transfer_order_id': transfer_order_id,
'error': 'Timeout'
}
else:
print(f"✗ Failed to initiate transfer: {response}")
return {'success': False, 'error': response}

# Example usage
result = transfer_with_verification(
'ci202008281528472924',
'ci202105241445228411',
802.90
)

Budget Rebalancing

Automatically rebalance budgets to maintain target allocations:

async function rebalanceBudgets(budgets, targetAllocations) {
const transfers = [];

console.log('\n=== Budget Rebalancing ===');

// Calculate current total
let totalBalance = 0;
for (const budget of budgets) {
const balanceResponse = await queryBudgetBalance(budget.budget_id);
budget.current_balance = parseFloat(balanceResponse.data.balance);
totalBalance += budget.current_balance;

console.log(`${budget.name}: ${budget.currency} ${budget.current_balance}`);
}

console.log(`\nTotal Balance: USD ${totalBalance.toFixed(2)}`);

// Calculate target amounts
const rebalancing = [];
for (const budget of budgets) {
const targetPercentage = targetAllocations[budget.budget_id] || 0;
const targetAmount = totalBalance * (targetPercentage / 100);
const difference = targetAmount - budget.current_balance;

rebalancing.push({
...budget,
target_percentage: targetPercentage,
target_amount: targetAmount,
difference: difference
});

console.log(`${budget.name}: Target ${targetPercentage}% (${budget.currency} ${targetAmount.toFixed(2)}), Diff: ${difference.toFixed(2)}`);
}

// Sort by difference (negative first = needs funds)
rebalancing.sort((a, b) => a.difference - b.difference);

// Execute transfers
console.log('\n=== Executing Transfers ===');

for (const target of rebalancing) {
if (target.difference > 0) {
// This budget needs funds - find source with surplus
for (const source of rebalancing) {
if (source.difference < 0 && Math.abs(source.difference) >= target.difference) {
const transferAmount = Math.min(target.difference, Math.abs(source.difference));

console.log(`\nTransferring ${target.currency} ${transferAmount.toFixed(2)}`);
console.log(` From: ${source.name}`);
console.log(` To: ${target.name}`);

const transferResponse = await transferBetweenBudgets({
source_budget_id: source.budget_id,
target_budget_id: target.budget_id,
transfer_amount: transferAmount.toFixed(2),
source_currency: source.currency,
target_currency: target.currency
});

if (transferResponse.code === 'SUCCESS') {
console.log(` ✓ Transfer initiated: ${transferResponse.data.transfer_order_id}`);

transfers.push({
from: source.name,
to: target.name,
amount: transferAmount,
transfer_order_id: transferResponse.data.transfer_order_id
});

// Update differences
source.difference += transferAmount;
target.difference -= transferAmount;
} else {
console.log(` ✗ Transfer failed`);
}

break;
}
}
}
}

console.log(`\n=== Rebalancing Summary ===`);
console.log(`Total Transfers: ${transfers.length}`);

return transfers;
}

// Example usage
const budgets = [
{ budget_id: 'ci202008281528472924', name: 'Marketing', currency: 'USD' },
{ budget_id: 'ci202105241445228411', name: 'Operations', currency: 'USD' },
{ budget_id: 'ci202105241445228412', name: 'Sales', currency: 'USD' }
];

const targetAllocations = {
'ci202008281528472924': 40, // Marketing: 40%
'ci202105241445228411': 35, // Operations: 35%
'ci202105241445228412': 25 // Sales: 25%
};

const transfers = await rebalanceBudgets(budgets, targetAllocations);

Department Budget Allocation

Distribute funds from a master budget to department budgets:

def allocate_to_departments(master_budget_id, department_allocations):
"""
Distribute funds from master budget to department budgets

Args:
master_budget_id: Source budget ID
department_allocations: List of dicts with budget_id, name, amount, currency
"""
import time

print("\n=== Department Budget Allocation ===")

# Check master budget balance
master_balance_response = query_budget_balance(master_budget_id)
master_balance = float(master_balance_response['data']['balance'])
master_currency = master_balance_response['data']['currency']

total_allocation = sum(dept['amount'] for dept in department_allocations)

print(f"Master Budget Balance: {master_currency} {master_balance}")
print(f"Total Allocation Requested: {master_currency} {total_allocation}")

if master_balance < total_allocation:
print(f"\n✗ Insufficient funds in master budget")
print(f" Available: {master_currency} {master_balance}")
print(f" Required: {master_currency} {total_allocation}")
return {'success': False, 'error': 'Insufficient funds'}

results = {
'successful': [],
'failed': []
}

# Execute transfers
print(f"\nAllocating to {len(department_allocations)} departments...")

for dept in department_allocations:
dept_name = dept['name']
dept_budget_id = dept['budget_id']
amount = dept['amount']
currency = dept.get('currency', master_currency)

print(f"\n{dept_name}: {currency} {amount}")

try:
response = initiate_budget_transfer(
source_budget_id=master_budget_id,
target_budget_id=dept_budget_id,
transfer_amount=str(amount),
source_currency=master_currency,
target_currency=currency
)

if response['code'] == 'SUCCESS':
transfer_order_id = response['data']['transfer_order_id']
print(f" ✓ Transfer initiated: {transfer_order_id}")

results['successful'].append({
'department': dept_name,
'budget_id': dept_budget_id,
'amount': amount,
'currency': currency,
'transfer_order_id': transfer_order_id
})
else:
print(f" ✗ Transfer failed: {response}")
results['failed'].append({
'department': dept_name,
'error': response
})

time.sleep(1) # Rate limiting

except Exception as e:
print(f" ✗ Error: {e}")
results['failed'].append({
'department': dept_name,
'error': str(e)
})

# Summary
print(f"\n=== Allocation Summary ===")
print(f"Successful: {len(results['successful'])}")
print(f"Failed: {len(results['failed'])}")

# Verify transfers
if results['successful']:
print("\nVerifying transfer statuses...")
time.sleep(5)

for item in results['successful']:
status_response = query_budget_transfer_order(item['transfer_order_id'])
status = status_response['data']['fund_result']
status_icon = '✓' if status == 'SUCCESS' else '✗'
print(f" {status_icon} {item['department']}: {status}")

return results

# Example usage
allocations = [
{
'budget_id': 'ci202105241445228411',
'name': 'Engineering',
'amount': 50000.00,
'currency': 'USD'
},
{
'budget_id': 'ci202105241445228412',
'name': 'Marketing',
'amount': 30000.00,
'currency': 'USD'
},
{
'budget_id': 'ci202105241445228413',
'name': 'Sales',
'amount': 20000.00,
'currency': 'USD'
}
]

results = allocate_to_departments('ci202008281528472924', allocations)

Emergency Budget Transfer

Quickly transfer funds to cover urgent expenses:

async function emergencyTransfer(sourceBudgetId, targetBudgetId, amount, reason) {
console.log('\n🚨 EMERGENCY TRANSFER INITIATED 🚨');
console.log(`Reason: ${reason}`);
console.log(`Amount: USD ${amount}`);

try {
// Check source budget balance
const sourceBalance = await queryBudgetBalance(sourceBudgetId);
const availableBalance = parseFloat(sourceBalance.data.balance);

console.log(`\nSource Budget Balance: USD ${availableBalance}`);

if (availableBalance < amount) {
console.log('✗ Insufficient funds for emergency transfer');
return {
success: false,
error: 'Insufficient funds',
available: availableBalance,
required: amount
};
}

// Initiate transfer
console.log('\nInitiating emergency transfer...');

const transferResponse = await transferBetweenBudgets({
source_budget_id: sourceBudgetId,
target_budget_id: targetBudgetId,
transfer_amount: amount.toFixed(2),
source_currency: 'USD',
target_currency: 'USD'
});

if (transferResponse.code === 'SUCCESS') {
const transferOrderId = transferResponse.data.transfer_order_id;
console.log(`✓ Transfer initiated: ${transferOrderId}`);

// Rapid status checking
console.log('\nMonitoring transfer status...');
let attempts = 0;
const maxAttempts = 20; // More attempts for emergency

while (attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 2000)); // Check every 2 seconds
attempts++;

const statusResponse = await queryBudgetTransferOrder(transferOrderId);
const status = statusResponse.data.fund_result;

if (status === 'SUCCESS') {
console.log('\n✓ EMERGENCY TRANSFER COMPLETED');

// Verify target balance updated
const targetBalance = await queryBudgetBalance(targetBudgetId);
console.log(`Target Budget New Balance: USD ${targetBalance.data.balance}`);

// Send alert
await sendAlert({
type: 'emergency_transfer_success',
source_budget: sourceBudgetId,
target_budget: targetBudgetId,
amount: amount,
reason: reason,
transfer_order_id: transferOrderId
});

return {
success: true,
transfer_order_id: transferOrderId,
amount: amount,
completed_in_seconds: attempts * 2
};
} else if (status === 'FAILED') {
console.log('\n✗ EMERGENCY TRANSFER FAILED');

await sendAlert({
type: 'emergency_transfer_failed',
source_budget: sourceBudgetId,
target_budget: targetBudgetId,
amount: amount,
reason: reason,
transfer_order_id: transferOrderId
});

return {
success: false,
error: 'Transfer failed',
transfer_order_id: transferOrderId
};
}

console.log(`⏳ Attempt ${attempts}/${maxAttempts}: Status ${status}`);
}

console.log('\n⚠ Transfer status check timed out');
return {
success: null,
error: 'Timeout',
transfer_order_id: transferOrderId
};
} else {
console.log('✗ Failed to initiate emergency transfer');
return {
success: false,
error: transferResponse
};
}
} catch (error) {
console.error('Emergency transfer error:', error);
throw error;
}
}

// Example usage
const result = await emergencyTransfer(
'ci202008281528472924', // Reserve budget
'ci202105241445228411', // Operations budget
5000.00,
'Critical server infrastructure payment'
);

Scheduled Inter-Budget Transfers

Automate recurring transfers between budgets:

def scheduled_inter_budget_transfers(transfer_schedules):
"""
Execute scheduled transfers between budgets

Args:
transfer_schedules: List of scheduled transfer configs
"""
from datetime import datetime
import time

print(f"\n=== Scheduled Transfers - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ===")

results = {
'executed': [],
'skipped': [],
'failed': []
}

for schedule in transfer_schedules:
schedule_name = schedule['name']
source_id = schedule['source_budget_id']
target_id = schedule['target_budget_id']
amount = schedule['amount']
currency = schedule['currency']
condition = schedule.get('condition', 'always') # always, if_source_above_threshold, etc.

print(f"\n{schedule_name}")
print(f" From: {source_id}")
print(f" To: {target_id}")
print(f" Amount: {currency} {amount}")
print(f" Condition: {condition}")

try:
# Check condition
should_execute = True

if condition == 'if_source_above_threshold':
threshold = schedule.get('threshold', 0)
source_balance_response = query_budget_balance(source_id)
source_balance = float(source_balance_response['data']['balance'])

print(f" Source Balance: {currency} {source_balance} (Threshold: {threshold})")

if source_balance <= threshold:
print(f" ⊘ Skipped: Balance below threshold")
results['skipped'].append({
'name': schedule_name,
'reason': 'Balance below threshold'
})
should_execute = False

elif condition == 'if_target_below_threshold':
threshold = schedule.get('threshold', 0)
target_balance_response = query_budget_balance(target_id)
target_balance = float(target_balance_response['data']['balance'])

print(f" Target Balance: {currency} {target_balance} (Threshold: {threshold})")

if target_balance >= threshold:
print(f" ⊘ Skipped: Target already above threshold")
results['skipped'].append({
'name': schedule_name,
'reason': 'Target above threshold'
})
should_execute = False

if should_execute:
# Execute transfer
response = initiate_budget_transfer(
source_budget_id=source_id,
target_budget_id=target_id,
transfer_amount=str(amount),
source_currency=currency,
target_currency=currency
)

if response['code'] == 'SUCCESS':
transfer_order_id = response['data']['transfer_order_id']
print(f" ✓ Executed: {transfer_order_id}")

results['executed'].append({
'name': schedule_name,
'transfer_order_id': transfer_order_id,
'amount': amount,
'currency': currency
})
else:
print(f" ✗ Failed: {response}")
results['failed'].append({
'name': schedule_name,
'error': response
})

time.sleep(1)

except Exception as e:
print(f" ✗ Error: {e}")
results['failed'].append({
'name': schedule_name,
'error': str(e)
})

# Summary
print(f"\n=== Execution Summary ===")
print(f"Executed: {len(results['executed'])}")
print(f"Skipped: {len(results['skipped'])}")
print(f"Failed: {len(results['failed'])}")

return results

# Example usage - Daily scheduled transfers
schedules = [
{
'name': 'Daily Marketing Allocation',
'source_budget_id': 'ci202008281528472924', # Master budget
'target_budget_id': 'ci202105241445228411', # Marketing budget
'amount': 1000.00,
'currency': 'USD',
'condition': 'if_source_above_threshold',
'threshold': 10000.00
},
{
'name': 'Low Balance Top-Up - Operations',
'source_budget_id': 'ci202008281528472924', # Master budget
'target_budget_id': 'ci202105241445228412', # Operations budget
'amount': 5000.00,
'currency': 'USD',
'condition': 'if_target_below_threshold',
'threshold': 2000.00
}
]

results = scheduled_inter_budget_transfers(schedules)

Cross-Currency Budget Transfer

Transfer funds with currency conversion:

async function crossCurrencyTransfer(sourceBudgetId, targetBudgetId, amount, sourceCurrency, targetCurrency) {
console.log('\n=== Cross-Currency Transfer ===');
console.log(`Amount: ${sourceCurrency} ${amount}`);
console.log(`From Currency: ${sourceCurrency}`);
console.log(`To Currency: ${targetCurrency}`);

try {
// Initiate transfer
const transferResponse = await transferBetweenBudgets({
source_budget_id: sourceBudgetId,
target_budget_id: targetBudgetId,
transfer_amount: amount.toFixed(2),
source_currency: sourceCurrency,
target_currency: targetCurrency
});

if (transferResponse.code === 'SUCCESS') {
const transferOrderId = transferResponse.data.transfer_order_id;
const inAmount = parseFloat(transferResponse.data.in_amount);

console.log(`\n✓ Transfer initiated: ${transferOrderId}`);
console.log(`Source Amount: ${sourceCurrency} ${amount}`);
console.log(`Target Amount: ${targetCurrency} ${inAmount}`);

// Calculate exchange rate
const exchangeRate = inAmount / amount;
console.log(`Effective Exchange Rate: ${exchangeRate.toFixed(4)}`);

// Wait for completion
console.log('\nWaiting for transfer to complete...');

let attempts = 0;
const maxAttempts = 10;

while (attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 3000));
attempts++;

const statusResponse = await queryBudgetTransferOrder(transferOrderId);
const status = statusResponse.data.fund_result;

if (status === 'SUCCESS') {
console.log('\n✓ Cross-currency transfer completed successfully');

return {
success: true,
transfer_order_id: transferOrderId,
source_amount: amount,
source_currency: sourceCurrency,
target_amount: inAmount,
target_currency: targetCurrency,
exchange_rate: exchangeRate
};
} else if (status === 'FAILED') {
console.log('\n✗ Cross-currency transfer failed');
return {
success: false,
transfer_order_id: transferOrderId,
error: 'Transfer failed'
};
}

console.log(`⏳ Attempt ${attempts}/${maxAttempts}: Still processing...`);
}

console.log('\n⚠ Transfer status check timed out');
return {
success: null,
transfer_order_id: transferOrderId,
error: 'Timeout'
};
} else {
console.log('✗ Failed to initiate transfer');
return {
success: false,
error: transferResponse
};
}
} catch (error) {
console.error('Cross-currency transfer error:', error);
throw error;
}
}

// Example usage
const result = await crossCurrencyTransfer(
'ci202008281528472924', // USD budget
'ci202105241445228411', // EUR budget
1000.00,
'USD',
'EUR'
);

Best Practices

  • Check Balances First: Always verify source budget has sufficient funds before initiating transfer
  • Verify Status: Use Query Budget Transfer Order endpoint to confirm transfer completed successfully
  • Atomic Operations: Transfers are atomic - either fully succeed or fully fail, no partial transfers
  • Amount Validation: Validate amounts are positive and properly formatted before submission
  • Currency Matching: Be aware of currency conversion when source and target currencies differ
  • Error Handling: Handle insufficient funds, invalid budgets, and network errors gracefully
  • Audit Trail: Log all transfers for financial reconciliation and compliance
  • Rate Limiting: Add delays between batch transfers to avoid rate limits

Transfer Workflow

Standard Process

  1. Validate Budgets: Confirm both source and target budget accounts exist
  2. Check Source Balance: Verify source budget has sufficient funds
  3. Initiate Transfer: Call this endpoint with transfer details
  4. Store Transfer ID: Save transfer_order_id for tracking
  5. Poll Status: Use Query Budget Transfer Order endpoint to check status
  6. Wait for Completion: Continue polling until SUCCESS or FAILED
  7. Verify Balances: Confirm both budgets reflect the transfer
  8. Update Records: Update your financial systems with completed transfer
  • Query Budget Transfer Order - Check the status of a transfer using transfer_order_id
  • Query Budget Balance - View budget balances before and after transfers
  • Create Budget Account - Create budget accounts for transfers
  • Top Up Budget Account - Add funds to budgets from external sources

Troubleshooting

Insufficient Funds (400)

  • Cause: Source budget doesn't have enough balance
  • Solution:
    • Check source budget balance with Query Budget Balance
    • Top up source budget first if needed
    • Reduce transfer amount

Budget Not Found (404)

  • Cause: One or both budget IDs don't exist
  • Solution:
    • Verify both budget IDs are correct
    • Ensure budgets were created successfully
    • Check if budgets were deleted

Same Source and Target (400)

  • Cause: Attempting to transfer to the same budget
  • Solution:
    • Verify source and target IDs are different
    • Check for copy-paste errors

Transfer Stuck in Processing

  • Cause: Transfer processing is delayed
  • Solution:
    • Continue polling for up to 5-10 minutes
    • Check if source budget is frozen or locked
    • Contact support if status doesn't update

Currency Conversion Issues

  • Cause: Invalid currency codes or conversion not supported
  • Solution:
    • Use valid ISO 4217 currency codes
    • Verify currency conversion is supported
    • Contact support for currency availability

Security Considerations

  • Authorization: Ensure proper authorization before allowing budget transfers
  • Balance Validation: Always validate sufficient funds before transfer
  • Transfer Limits: Consider implementing transfer limits for security
  • Audit Logging: Maintain comprehensive logs of all transfer operations
  • Fraud Detection: Monitor for unusual transfer patterns
  • Access Control: Restrict transfer permissions to authorized personnel only

Interactive API Explorer