Exchange rates & FX policy
When the catalog price is in one currency and the invoice in another, Kontorion converts using a stored exchange-rate snapshot. The choice of which rate to use - the rate at issue, at period start, or per segment - is controlled by the org's FX policy. Every finalized invoice line pins the rate it was converted with, so replay reproduces the original totals to the cent regardless of later policy changes.
Why this matters. Multi-currency billing introduces three kinds of risk: rate volatility between order and capture, divergent finance preferences across markets, and replay correctness when rates change after finalization. Kontorion pins three FX-rate candidates per invoice (issue, period-start, per-segment) and lets you set the active policy at the org level, so the books are always reproducible and "what-if" rendering against alternate policies is one query away.
Snapshots and overrides
The FX surface has two kinds of records:
- Snapshots are the daily rate set, sourced from an upstream feed (typically ECB). They are read-only at the API layer - new snapshots arrive through the scheduled sync job.
- Overrides are workspace-scoped manual rates that override the snapshot for a specific currency pair and validity window. Use these when finance needs to pin a contractual rate or correct a feed glitch.
Both shapes carry from_currency, to_currency (ISO 4217), a decimal rate, and an effective window. Internally each becomes a candidate when the invoice pipeline resolves an effective rate at finalize time.
FX policy
The org's FX policy lives in organization settings under the key fx_policy. Default is invoice_issue. Four values:
| Policy | Rate used | Best for |
|---|---|---|
invoice_issue (default) | Rate active when the invoice is finalized | Simplest; minimal volatility surface. |
period_start | Rate active at the billing period start | Pins all lines on the invoice to one rate captured up front. |
per_segment | Rate active at each line's segment start | Mid-period FX moves get line-level granularity. |
daily_snapshot | Daily-rotated snapshot | Operationally similar to invoice_issue but with off-hours stability. |
Switching policies applies to future invoices only. Existing invoices stay pinned to the rate that finalised them.
To support replay across policy changes, every finalized invoice records three candidate exchange-rate ids:
Invoice.issue_exchange_rate_id- theinvoice_issuecandidate.Invoice.period_start_exchange_rate_id- theperiod_startcandidate.InvoiceLine.segment_exchange_rate_id- theper_segmentcandidate (per line).
Field (on Invoice) | Candidate |
|---|---|
issue_exchange_rate_id | The invoice_issue candidate (rate at finalize) |
period_start_exchange_rate_id | The period_start candidate (rate at billing-period open) |
Reading rates
Get the latest snapshot for a currency pair:
Code
Both from and to are required (3-letter ISO codes). The response is the snapshot row that was active at request time.
List all currency-pair snapshots for a date:
Code
date is optional and accepts YYYY-MM-DD. When omitted, today (UTC) is used.
Check the sync job's freshness:
Code
Returns latest_snapshot_date and distinct_dates_last_year so you can alert on stale feeds.
Workspace overrides
Add a manual override for a currency pair:
Code
List, patch, or delete overrides via GET /v1/fx/overrides, PATCH /v1/fx/overrides/{id}, DELETE /v1/fx/overrides/{id}. Overrides are scoped to the calling workspace; they do not affect other workspaces in the same org.
Conversion fee
The policy lives on the organization's tax profile:
Code
Endpoints
Next steps
- Currencies - minor units, supported codes, rounding.
- Invoices - where pinned rates surface.
- Tax Compliance - FX policy lives on
OrgTaxProfile.