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

# Book the year-end FX revaluation

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

## Request

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

Posts one system journal entry dated the fiscal-year end (`externalSource: system`, "Neubewertung Fremdwährungen per dd.mm.yyyy"): per item the CHF difference on the FW account, 1100 or 2000 against the FX result account (profile setting, default 6960), lines tagged `fxKind: revaluation`, no VAT code. Needs a rate for every currency in scope and never fetches one. Runs in one transaction that locks the fiscal year; a closed year answers 400 FISCAL_YEAR_CLOSED. Running it again replaces the previous run (its entry gets a Storno, the run is superseded); an identical result answers 200 with `unchanged: true` and writes nothing. Errors (400): FX_RATE_MISSING (with `currencies`), FX_INVALID_RATE, FX_REVALUATION_TOO_EARLY, FX_REVALUATION_INVALID, FX_ACCOUNT_MISSING, FX_PRIOR_YEAR_NOT_CLOSED (close the prior year first so its Saldovortrag is posted); 403 DOUBLE_ENTRY_REQUIRED; 409 FX_REVALUATION_PREVIEW_CHANGED when the body's `previewToken` no longer matches the ledger (a booking in scope changed since the preview: preview again and commit with the new token). The year close then no longer reports FX_REVALUATION_MISSING.

## 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 current run already books this result; nothing written

- object
  - `unchanged` true
  - `run` FxRevaluationRun
    - `id` string, uuid
    - `runDate` string, date
    - `policy` 'stichtag' | 'niederstwert'
    - `threshold` number, double
    - `journalEntryId` string, uuid, nullable
    - `createdAt` string, date-time

## Other responses

- `201`: Revaluation booked
- `400`: Validation error
- `401`: Invalid or missing API key
- `403`: Subscription required or read-only key on a write endpoint
- `404`: Resource not found
- `409`: FX_REVALUATION_PREVIEW_CHANGED: bookings in scope changed since the preview whose `previewToken` was sent; nothing written
- `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)
