---
title: "Preview the year-end FX revaluation"
method: POST
path: "/fiscal-years/{id}/fx-revaluation/preview"
tags: ["Fiscal Years"]
---

# Preview the year-end FX revaluation

`POST /fiscal-years/{id}/fx-revaluation/preview`

## Request

- Base URL: `https://api.lumabill.ch/v1`
- URL: `https://api.lumabill.ch/v1/fiscal-years/{id}/fx-revaluation/preview`
- Auth: HTTP bearer

Double-entry profiles only (403 DOUBLE_ENTRY_REQUIRED). Values every foreign-currency (FW) bank account and every open FW invoice, credit note, expense and revenue at the closing rate (Stichtagskurs) of the fiscal-year end and returns the CHF difference per item. Books nothing. Closing rates are prefilled (ESTV ICTax year-end list for a 31.12. close where it lists the currency, else the ESTV/BAZG daily rate of the closing date) and can be overridden in `rates`. Errors (400): FX_REVALUATION_TOO_EARLY (the year has not ended, with `endDate`), FX_REVALUATION_INVALID (policy / threshold), FX_INVALID_RATE (with `currency`), FX_PRIOR_YEAR_NOT_CLOSED (the previous fiscal year is still open, so this year holds no Saldovortrag and its FW saldi would be wrong: close the prior year first). The response carries a `previewToken` for the commit. Being a POST, it needs a read_write API key.

## Request body

- FxRevaluationRequest
  - `rates` object: Closing rate per currency, keyed by currency code. Optional on the preview (overrides the prefilled rate); required on the commit, one for every currency in scope (the commit never fetches a rate).
  - `policy` 'stichtag' | 'niederstwert': `stichtag` books unrealized gains and losses at the closing rate; `niederstwert` books no unrealized gains on open items (FW bank accounts are always valued at the closing rate). Default: the profile's `fxValuationPolicy`.
  - `threshold` number, double: Items whose CHF difference is below this amount are skipped
  - `previewToken` string: Commit only: the `previewToken` of the preview the commit books. When bookings in scope changed since that preview, the commit answers 409 FX_REVALUATION_PREVIEW_CHANGED and writes nothing; run the preview again and commit with its new token.

## Response `200`

The valuation with its rates, items, totals and warnings

- FxRevaluationPreview
  - `fiscalYear` FiscalYear
    - `id` string, uuid
    - `year` integer
    - `startDate` string, date
    - `endDate` string, date
    - `status` 'OPEN' | 'CLOSED'
    - `closedAt` string, date-time, nullable
    - `createdAt` string, date-time
    - `exportStatus` string, nullable
    - `exportRequestedAt` string, date-time, nullable
  - `runDate` string, date: The fiscal-year end
  - `policy` 'stichtag' | 'niederstwert'
  - `threshold` number, double
  - `rates` FxRevaluationRate[]
    - `currency` 'CHF' | 'EUR' | 'USD' | 'GBP' | 'JPY' | 'CAD' | 'AUD' | 'SEK' | 'NOK' | 'DKK' | 'HUF': ISO 4217 code of a currency the API converts (ESTV/BAZG rates). The same list applies to every currency field of the API.
    - `rate` number, double, nullable
    - `source` string: Where a rate came from: `BAZG` (ESTV/BAZG daily or monthly average sell rate), `BAZG_CROSS` (derived through a cross rate), `ICTAX` (ESTV year-end list, mid rate), `ACTUAL` (the CHF amount actually moved), `MANUAL` (entered by you).
    - `rateType` 'daily' | 'monthly' | 'closing', nullable
    - `rateDate` string, date, nullable
    - `retrievedAt` string, date-time, nullable
    - `manual` boolean
  - `items` FxRevaluationItem[]
    - `key` string
    - `kind` 'bank' | 'debitor' | 'kreditor'
    - `orientation` 'asset' | 'liability'
    - `chartAccountId` string, uuid, nullable
    - `accountCode` string, nullable
    - `accountName` string, nullable
    - `documentType` 'INVOICE' | 'EXPENSE' | 'REVENUE', nullable
    - `documentId` string, uuid, nullable
    - `documentKind` string, nullable
    - `label` string, nullable
    - `documentDate` string, date, nullable
    - `currency` 'CHF' | 'EUR' | 'USD' | 'GBP' | 'JPY' | 'CAD' | 'AUD' | 'SEK' | 'NOK' | 'DKK' | 'HUF': ISO 4217 code of a currency the API converts (ESTV/BAZG rates). The same list applies to every currency field of the API.
    - `fwSaldo` number, double
    - `chfBookBefore` number, double: CHF book value before this run
    - `rate` number, double, nullable
    - `chfTarget` number, double
    - `delta` number, double: chfTarget minus chfBookBefore
    - `gain` number, double: P&L effect (positive = gain)
    - `fxKind` 'revaluation' | 'realized', nullable
    - `skippedReason` 'below_threshold' | 'niederstwert' | 'settled' | 'rate_missing', nullable
    - `posted` boolean
    - `settledAfterYearEnd` boolean
  - `totals` FxRevaluationTotals
    - `gain` number, double
    - `loss` number, double
    - `net` number, double
    - `postedCount` integer
    - `skippedCount` integer
  - `warnings` object[]: Objects with a `code`: RATE_MISSING (currencies), RATE_FALLBACK (a 31.12. ICTax currency answered by the BAZG daily rate), RATE_DATE_DIFFERS, OVERDRAFT (accounts), SETTLED_AFTER_YEAR_END, DOCUMENT_RATE_MISSING (count, items), FX_ACCOUNT_MISSING.
    - `code` string
  - `currentRun` FxRevaluationRun
    - `id` string, uuid
    - `runDate` string, date
    - `policy` 'stichtag' | 'niederstwert'
    - `threshold` number, double
    - `journalEntryId` string, uuid, nullable
    - `createdAt` string, date-time
  - `unchanged` boolean: The current run already books exactly this result; a commit changes nothing
  - `canCommit` boolean
  - `previewToken` string: Identity of this preview (the ledger state it valued). Send it back on the commit; a commit whose token no longer matches the ledger answers 409 FX_REVALUATION_PREVIEW_CHANGED.

## Other responses

- `400`: Validation error
- `401`: Invalid or missing API key
- `403`: Subscription required or read-only key on a write endpoint
- `404`: Resource not found
- `429`: Rate limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/lumabill/apis/lumabill-api.md) · [All operations](https://skmtc.dev/lumabill/apis/lumabill-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lumabill/apis/lumabill-api/revisions/e48e7099b545?raw)
