Multi-Currency
Handle foreign-currency transactions, FX rate management, and period-end revaluation.
Overview
Axiomatic supports multi-currency accounting with automatic translation to each entity's functional currency. Foreign-currency journal lines carry both the original amount and the translated functional-currency amount with the applied exchange rate.
How It Works
- Each entity has a functional currency (e.g. USD) set in its profile
- When an event is posted in a foreign currency, the posting engine looks up the exchange rate for that date
- Journal lines store both the original amount/currency and the translated functional amount/currency
- Reports aggregate in the functional currency
FX Rate Resolution
When a rate is needed, the system tries three strategies in order:
- Direct lookup — find a rate for the exact currency pair on the event date
- Inverse lookup — if EUR→USD doesn't exist, use 1/USD→EUR
- Triangulation via USD — convert through USD as an intermediate (e.g. GBP→USD→JPY)
Stablecoins (USDC, USDT, DAI, BUSD, EUROC) are automatically pegged 1:1 to their base fiat currency — no rate entry needed.
Managing FX Rates
Adding Rates via API
Single rate:
curl -X POST /api/fx-rates \
-H "Content-Type: application/json" \
-d '{
"fromCurrency": "EUR",
"toCurrency": "USD",
"rate": "1.0850",
"rateDate": "2025-06-15",
"source": "manual"
}'Batch insert:
curl -X POST /api/fx-rates \
-H "Content-Type: application/json" \
-d '[
{ "fromCurrency": "GBP", "toCurrency": "USD", "rate": "1.2650", "rateDate": "2025-06-15" },
{ "fromCurrency": "JPY", "toCurrency": "USD", "rate": "0.00645", "rateDate": "2025-06-15" }
]'Duplicate entries (same pair and date) are silently ignored.
Looking Up Rates
GET /api/fx-rates?lookup=true&from=EUR&to=USD&date=2025-06-15Returns the closest rate on or before the requested date, with fallback to inverse and triangulation.
Posting Foreign-Currency Events
Post an event with a foreign-currency amount in the payload. The posting engine handles translation automatically:
POST /api/events
{
"entityId": "your-entity-id",
"type": "INVOICE_RECEIVED",
"timestamp": "2025-06-15T00:00:00Z",
"payload": {
"vendor": "Euro Supplier GmbH",
"amount": "10000.00",
"currency": "EUR",
"invoice_number": "INV-2025-042"
}
}The resulting journal lines will include:
| Field | Description |
|---|---|
amount | Original amount in transaction currency (e.g. 10,000.00) |
currency | Transaction currency (e.g. EUR) |
functionalAmount | Translated amount in functional currency (e.g. 10,850.00) |
functionalCurrency | Entity's functional currency (e.g. USD) |
fxRate | The exchange rate applied (e.g. 1.0850) |
Period-End FX Revaluation
At period end, monetary balances denominated in foreign currencies must be revalued at the closing exchange rate (per ASC 830 / IAS 21). This ensures your balance sheet reflects current exchange rates.
Preview Adjustments
Run a dry-run to see proposed adjustments before committing:
GET /api/fx-revaluation?entityId=...&bookId=...&asOfDate=2025-06-30The preview shows:
- Which accounts have foreign-currency balances
- Current functional-currency balance vs. revalued balance
- The unrealized gain or loss per account
Execute Revaluation
POST /api/fx-revaluation
{
"entityId": "your-entity-id",
"bookId": "your-book-id",
"asOfDate": "2025-06-30"
}This creates a journal entry that adjusts each revalued account with an offsetting entry to your unrealized FX gain/loss accounts.
Prerequisites
Before running revaluation, ensure your entity has two account mappings configured:
| Logical Role | Purpose |
|---|---|
fx.unrealized_gain | Credits for favorable rate movements |
fx.unrealized_loss | Debits for unfavorable rate movements |
These are typically mapped to accounts like "8100 Unrealized FX Gain" (Revenue) and "8200 Unrealized FX Loss" (Expense).
Currency Precision
The FX module uses currency-specific decimal precision for rounding:
| Currency | Decimal Places |
|---|---|
| USD, EUR, GBP | 2 |
| JPY | 0 |
| BTC | 8 |
| ETH | 18 |
| USDC, USDT | 6 |