Axiomatic

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

  1. Each entity has a functional currency (e.g. USD) set in its profile
  2. When an event is posted in a foreign currency, the posting engine looks up the exchange rate for that date
  3. Journal lines store both the original amount/currency and the translated functional amount/currency
  4. Reports aggregate in the functional currency

FX Rate Resolution

When a rate is needed, the system tries three strategies in order:

  1. Direct lookup — find a rate for the exact currency pair on the event date
  2. Inverse lookup — if EUR→USD doesn't exist, use 1/USD→EUR
  3. 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-15

Returns 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:

FieldDescription
amountOriginal amount in transaction currency (e.g. 10,000.00)
currencyTransaction currency (e.g. EUR)
functionalAmountTranslated amount in functional currency (e.g. 10,850.00)
functionalCurrencyEntity's functional currency (e.g. USD)
fxRateThe 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-30

The 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 RolePurpose
fx.unrealized_gainCredits for favorable rate movements
fx.unrealized_lossDebits 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:

CurrencyDecimal Places
USD, EUR, GBP2
JPY0
BTC8
ETH18
USDC, USDT6

On this page