Multi-Currency Support
Crane Ledger provides comprehensive multi-currency support for organizations operating internationally. Handle transactions in any currency while maintaining accurate financial records and reporting in your base currency.
Base Currency Setup
Organization Base Currency
Every organization has a primary currency for financial reporting:
{
"id": "ORG_1234567890abcdef",
"name": "Global Corporation",
"base_currency": {
"code": "USD",
"name": "US Dollar",
"symbol": "$",
"decimal_places": 2
}
}
Setup during organization creation:
POST /accounts/master
{
"organization_name": "Global Corp",
"base_currency_code": "USD",
"tax_number": "US123456789"
}
Change base currency (requires careful consideration):
PUT /organizations/{org_id}
{
"base_currency_code": "EUR"
}
Currency Considerations
- Historical transactions remain in original currencies
- Exchange rates must be available for conversion
- Reports recalculate using new base currency
- Sub-organizations can have different base currencies
Supported Currencies
Currency Catalog
Crane Ledger supports all major world currencies:
// Get all supported currencies
GET /currencies
// Response includes metadata
[
{
"id": "CUR_USD",
"code": "USD",
"name": "US Dollar",
"symbol": "$",
"decimal_places": 2,
"symbol_first": true,
"is_active": true
},
{
"id": "CUR_EUR",
"code": "EUR",
"name": "Euro",
"symbol": "€",
"decimal_places": 2,
"is_active": true
},
{
"id": "CUR_JPY",
"code": "JPY",
"name": "Japanese Yen",
"symbol": "¥",
"decimal_places": 0,
"is_active": true
}
]
Currency-Specific Rules
Different currencies have unique formatting rules:
| Currency | Code | Decimals | Symbol | Position |
|---|---|---|---|---|
| US Dollar | USD | 2 | $ | Before |
| Euro | EUR | 2 | € | After |
| Japanese Yen | JPY | 0 | ¥ | Before |
| British Pound | GBP | 2 | £ | Before |
| Swiss Franc | CHF | 2 | Fr | Before |
| Bitcoin | BTC | 8 | ₿ | Before |
Exchange Rate Management
Exchange Rate Sources
Exchange rates can come from multiple sources:
// Manual entry
POST /organizations/{org_id}/exchange-rates
{
"from_currency_id": "CUR_USD",
"to_currency_id": "CUR_EUR",
"rate": 0.85,
"effective_date": "2024-01-15",
"source": "manual"
}
// External API integration
POST /organizations/{org_id}/exchange-rates/import
{
"source": "ecb", // European Central Bank
"effective_date": "2024-01-15"
}
Rate History
Maintain historical rates for accurate reporting:
{
"id": "EXR_1234567890abcdef",
"organization_id": "ORG_1234567890abcdef",
"from_currency_id": "CUR_USD",
"to_currency_id": "CUR_EUR",
"rate": 0.85,
"effective_date": "2024-01-15",
"source": "ecb",
"created_by": "system",
"created_at": "2024-01-15T08:00:00Z"
}
Rate Lookup
Get current or historical rates:
# Current rate
GET /organizations/{org_id}/exchange-rates/USD/EUR
# Rate for specific date
GET /organizations/{org_id}/exchange-rates/USD/EUR?date=2024-01-15
# All rates for currency pair
GET /organizations/{org_id}/exchange-rates/USD/EUR/history
Currency Conversion in Transactions
Multi-Currency Transaction Structure
Transactions can involve multiple currencies:
{
"description": "EUR invoice payment",
"transaction_date": "2024-01-15",
"currency_id": "CUR_EUR", // Transaction currency
"amount": 100.00, // Amount in EUR
"entries": [
{
"account_id": "ACT_1001", // USD Cash account
"entry_type": "debit",
"amount": 110.00, // USD equivalent
"currency_id": "CUR_USD", // Entry currency
"currency_rate": 1.10 // USD/EUR rate
},
{
"account_id": "ACT_1101", // EUR Accounts Receivable
"entry_type": "credit",
"amount": 100.00, // EUR amount
"currency_id": "CUR_EUR", // Entry currency
"currency_rate": 1.10 // USD/EUR rate
}
]
}
Conversion Rules
- Entry amounts are always in the entry's currency
- Base amounts are calculated using exchange rates
- Balance validation ensures total debits = total credits in base currency
- Exchange rates are snapshots at transaction time
Automatic Conversion
// System calculates base amounts automatically
function calculateBaseAmount(entryAmount, exchangeRate) {
return entryAmount / exchangeRate; // For USD/EUR at 1.10
}
// EUR 100 at rate 1.10 = USD 90.91
calculateBaseAmount(100, 1.10); // Returns 90.91
Currency Gain/Loss Accounting
Exchange Rate Fluctuations
Currency values change over time, creating gains/losses:
// Invoice created: EUR 100 at rate 1.10 = USD 90.91
// Payment received: EUR 100 at rate 1.05 = USD 95.24
// Result: Currency gain of USD 4.33
// Automatic adjustment entry
{
"description": "Currency exchange gain",
"entries": [
{
"account_id": "ACT_1101", // Accounts Receivable
"entry_type": "debit",
"amount": 4.33, // Gain amount
"currency_id": "CUR_USD"
},
{
"account_id": "ACT_4201", // Currency Gain account
"entry_type": "credit",
"amount": 4.33,
"currency_id": "CUR_USD"
}
]
}
Gain/Loss Accounts
Set up dedicated accounts for currency adjustments:
// Currency Gain (Revenue account)
{
"code": "4201",
"name": "Currency Exchange Gain",
"type": "revenue"
}
// Currency Loss (Expense account)
{
"code": "5105",
"name": "Currency Exchange Loss",
"type": "expense"
}
Multi-Currency Accounts
Account Currency Assignment
Accounts can hold balances in different currencies:
// Multi-currency bank account
{
"id": "ACT_1001",
"code": "1001",
"name": "Foreign Currency Account",
"type": "asset",
"currency_id": "CUR_USD", // Account currency
"allow_multi_currency": true // Allow other currencies
}
// Account balances in multiple currencies
{
"account_id": "ACT_1001",
"balances": {
"USD": 5000.00,
"EUR": 2500.00,
"GBP": 1800.00
},
"total_base": 9500.00 // Total in base currency
}
Currency-Specific Sub-Accounts
Create separate accounts for each currency:
1001 Cash - USD
1002 Cash - EUR
1003 Cash - GBP
1004 Cash - JPY
Financial Reporting in Multi-Currency
Base Currency Reporting
All reports are generated in the organization's base currency:
// Balance Sheet in USD (base currency)
{
"assets": {
"cash_usd": 5000.00,
"cash_eur": 2272.73, // EUR 2500 at rate 1.10
"cash_gbp": 2340.00, // GBP 1800 at rate 1.30
"total": 9612.73
}
}
Currency Breakdown Reports
View balances by currency:
GET /organizations/{org_id}/reports/balance-sheet?by_currency=true
// Response shows balances in each currency
{
"USD": {
"assets": 5000.00,
"liabilities": 2000.00,
"equity": 3000.00
},
"EUR": {
"assets": 2500.00,
"liabilities": 1000.00,
"equity": 1500.00
}
}
Exchange Rate Impact Analysis
Analyze how currency fluctuations affect financials:
GET /organizations/{org_id}/reports/currency-impact?period=2024-01
// Shows gains/losses by currency pair
{
"USD_EUR": {
"transactions": 15,
"total_gain_loss": 1250.00,
"rate_change": -0.05
},
"USD_GBP": {
"transactions": 8,
"total_gain_loss": -350.00,
"rate_change": 0.02
}
}
Transaction Examples
Foreign Invoice
// Create invoice in EUR
const invoice = await createInvoice({
contact_id: "CON_EUR_CUSTOMER",
currency_id: "CUR_EUR",
invoice_date: "2024-01-15",
items: [
{
name: "Consulting Services",
quantity: 10,
price: 100.00, // EUR
currency_id: "CUR_EUR"
}
]
});
// Invoice total: EUR 1,000
// Converted to USD at rate 1.10: USD 909.09
Multi-Currency Payment
// Customer pays in different currency
const payment = await recordInvoicePayment({
invoice_id: invoice.id,
amount: 1100.00, // USD payment
currency_id: "CUR_USD", // Payment currency
payment_date: "2024-01-20"
});
// System handles conversion:
// EUR 1,000 invoice at rate 1.10 = USD 909.09
// USD 1,100 payment received
// Result: Overpayment of USD 190.91
Bank Transfer Between Currencies
// Transfer EUR to USD account
const transfer = await createTransfer({
from_account_id: "ACT_EUR_BANK",
to_account_id: "ACT_USD_BANK",
amount: 1000.00,
currency_id: "CUR_EUR",
transfer_date: "2024-01-15"
});
// System creates entries:
// Debit EUR Bank: EUR 1,000
// Credit USD Bank: USD 1,100 (at rate 1.10)
// Currency gain/loss: USD 100
Best Practices
Rate Management
- Update rates daily - Use reliable sources for current rates
- Document sources - Track where rates come from
- Set rate policies - Decide when to update (daily, weekly, monthly)
- Audit rate changes - Review significant fluctuations
Transaction Recording
- Use transaction currency - Record in the currency of the actual transaction
- Lock exchange rates - Use rates at time of transaction
- Document conversions - Include rate information in descriptions
- Separate currency accounts - Consider dedicated accounts per currency
Reporting
- Monitor currency exposure - Track balances in foreign currencies
- Analyze gain/loss patterns - Identify significant currency impacts
- Use base currency for consolidation - Standardize reporting currency
- Consider hedge accounting - For significant currency risks
Account Setup
- Create currency-specific accounts - Separate accounts for each currency
- Use consistent naming - Include currency codes in account names
- Set up gain/loss accounts - Dedicated accounts for exchange differences
- Enable multi-currency flags - Allow mixed currency entries
Common Challenges
Rate Fluctuation Impact
Challenge: Currency values change between invoice and payment
Solutions:
- Lock rates at invoice time - Use consistent rates
- Accept over/under payments - Handle small differences
- Require payment in invoice currency - Minimize conversions
- Use forward contracts - Hedge major currency risks
Reporting Complexity
Challenge: Multiple currencies complicate financial analysis
Solutions:
- Standardize on base currency - All reports in USD/EUR/etc.
- Provide currency breakdowns - Show original currencies
- Use exchange rate tables - Document rates used
- Implement currency controls - Separate currency responsibilities
Compliance Issues
Challenge: Different countries have different currency rules
Solutions:
- Set organization base currencies - Per local requirements
- Use appropriate tax currencies - Match local tax authorities
- Maintain currency trails - Complete audit trails
- Implement currency restrictions - Limit available currencies
Integration Issues
Challenge: External systems may not support multi-currency
Solutions:
- Convert at boundaries - Handle conversions at API level
- Use base currency interfaces - Simplify external integrations
- Provide currency metadata - Include conversion information
- Support multiple formats - Accept various currency inputs
Integration Examples
Currency Rate Import
// Import rates from external API
async function importRates() {
const rates = await fetch('https://api.exchangerate-api.com/v4/latest/USD')
.then(r => r.json());
for (const [currency, rate] of Object.entries(rates.rates)) {
await createExchangeRate({
from_currency_id: "CUR_USD",
to_currency_id: `CUR_${currency}`,
rate: rate,
source: "exchangerate-api",
effective_date: new Date().toISOString().split('T')[0]
});
}
}
Transaction with Currency Conversion
// Handle payment in different currency
async function processMultiCurrencyPayment(invoiceId, payment) {
const invoice = await getInvoice(invoiceId);
const currentRate = await getExchangeRate(
payment.currency_id,
invoice.currency_id,
payment.date
);
// Convert payment to invoice currency
const convertedAmount = payment.amount * currentRate;
// Record payment with conversion details
return await recordPayment({
invoice_id: invoiceId,
amount: convertedAmount,
original_amount: payment.amount,
original_currency: payment.currency_id,
exchange_rate: currentRate,
exchange_rate_date: payment.date
});
}
Currency Gain/Loss Calculation
// Calculate currency adjustments
async function calculateCurrencyAdjustments(transaction) {
const adjustments = [];
for (const entry of transaction.entries) {
if (entry.currency_id !== transaction.currency_id) {
const currentRate = await getCurrentExchangeRate(
entry.currency_id,
transaction.currency_id
);
const originalValue = entry.amount / entry.currency_rate;
const currentValue = originalValue * currentRate;
const adjustment = currentValue - entry.amount;
if (Math.abs(adjustment) > 0.01) { // Threshold for small differences
adjustments.push({
account_id: entry.account_id,
amount: adjustment,
type: adjustment > 0 ? 'gain' : 'loss'
});
}
}
}
return adjustments;
}
Performance Considerations
Rate Caching
- Cache exchange rates - Reduce API calls to external services
- Set cache expiration - Balance freshness with performance
- Fallback rates - Use last known rates if external services fail
Query Optimization
- Pre-calculate base amounts - Store converted values
- Index currency fields - Optimize currency-based queries
- Use materialized views - For complex multi-currency reports
Batch Processing
- Bulk rate updates - Update multiple rates at once
- Batch conversions - Process multiple transactions together
- Async processing - Handle large currency recalculations
Multi-currency support enables global business operations while maintaining accurate financial records. Proper exchange rate management and transaction handling ensure compliance and accurate reporting across currencies.
Need help?
Create a free account to access our support portal. Once signed in, use the Support tab in your dashboard to submit a support ticket — our team typically responds within 24 hours.
- ✨ For LLMs/AI assistants: Read our structured API reference