Conventions
Date and amount formats, public_token identifiers and numeric ids, message language and headers recognised by the NovaFisko API.
This page gathers the rules common to all routes. Following them avoids most 422 errors.
Requests
- Send
Accept: application/jsonon every call. Theapi.novafisko.comhost always responds in JSON, but this header guarantees the same behaviour behind a proxy. - Bodies are JSON (
Content-Type: application/json), encoded in UTF-8. - File uploads (
document-imports) usemultipart/form-data. - Field names are in English and in
snake_case. URL segments are inkebab-case(third-parties,vat-declarations).
Dates and times
| Kind | Format | Example |
|---|---|---|
Accounting date (entry_date, due_date, starts_on, from, to) |
YYYY-MM-DD |
2026-03-31 |
Timestamp (created_at, posted_at, server_time) |
ISO 8601 with time zone, in UTC | 2026-10-05T08:30:11+00:00 |
| Billing month | YYYY-MM |
2026-10 |
An accounting date has no time zone: 31 March remains 31 March wherever you call from. Timestamps are stored and returned in UTC. Convert them to your user's time zone at display time.
In responses, an accounting date of a model may appear in the long form 2026-03-31T00:00:00.000000Z. Keep only the first ten characters. On input, always send YYYY-MM-DD.
Amounts
Amounts are expressed in euros, as decimal strings with a dot and two decimals: "1250.00", "0.21", "-48.40".
{
"debit": "1250.00",
"credit": "0.00",
"balance": "1250.00"
}
This choice avoids the rounding errors of floating-point numbers. In your code, use a decimal type (BigDecimal, decimal, Decimal, bcmath) or work in integer cents.
On input, the API accepts "1250.00" as well as 1250 or 1250.5. It converts everything to cents before calculating. We recommend sending strings.
A few management responses (licence, price list, simulator) return JSON numbers, for example "total": 149.0. These are commercial amounts, not accounting amounts. All accounting statements (trial balance, general ledger, entries, VAT) use strings.
An entry must balance to the cent: the sum of the debits equals the sum of the credits, otherwise the request is refused with 422.
Identifiers
NovaFisko uses two families of identifiers.
| Resource | Identifier in the URL | Shape | Example |
|---|---|---|---|
Firm (firm) |
public_token |
12 alphanumeric characters | Fd7hQ2mN8sXa |
Company (company) |
public_token |
12 alphanumeric characters | k3Jd9fPq2LmX |
| Everything that lives inside a company (entry, third party, account, journal, document, fiscal year...) | numeric id |
integer | 1842 |
The public_token is opaque, stable and not guessable. It is what you should store to refer to a firm or a company. Numeric id values only make sense inside their company: a companies/{company}/entries/{id} route responds 404 if the entry belongs to another company.
/v1/companies/k3Jd9fPq2LmX/entries/1842
└─ public_token └─ id
Some fields accept a readable form instead of the id. In an entry, for example, a line can refer to its account by account_id (integer) or by account (account number, "604000"). Likewise, an invoice line accepts vat_code_id or vat_code.
Imported data
Records that come from another source carry three fields: source (for example novadesko), external_id (the identifier in the source) and synced_at. Use external_id to find a record you pushed yourself.
Record version
Resources tracked by the history expose an integer version that increases with each modification. Send it back in X-Base-Version to enable the optimistic lock described in Idempotency.
Message language
Labels and error messages exist in French, Dutch, English and German. The language is chosen as follows:
- the
localequery parameter (history, recycle bin and synchronisation routes) orlang(exports, licence) when provided; - otherwise the profile language of the user who owns the token;
- otherwise the
Accept-Languageheader; - otherwise the platform's default language.
GET /v1/firms/Fd7hQ2mN8sXa/licence?lang=nl HTTP/1.1
Accept-Language: nl-BE,nl;q=0.9,fr;q=0.6
Never make your logic depend on the text of message, which varies with the language. Rely on the HTTP status and on the code field.
Request headers
| Header | Role |
|---|---|
Authorization |
Bearer <token> |
Accept |
application/json |
Accept-Language |
Desired language for messages |
X-Client-Mutation-Id |
Idempotency key of a write, 64 characters max. See Idempotency |
X-Base-Version |
Known version of the record being modified (optimistic lock) |
X-Operation-Id |
UUID that groups all the changes of a single action. Generated by the server if absent |
X-Device-Id |
Stable identifier of the installation or connector, 64 characters max |
X-Device-Name |
Readable name of the device, percent-encoded, 120 characters max |
X-Device-Platform |
Platform (web, macos, linux, integration...) |
X-Occurred-At |
ISO 8601 date of the action on the client side, bounded to plus or minus 24 hours around the server time |
X-Origin |
offline_sync when the request replays an action performed offline |
The X-Device-* headers are optional but useful: they appear in the History tab, which lets an accountant see that a modification comes from your connector.
curl -X POST https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/third-parties \
-H "Authorization: Bearer $NOVAFISKO_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Device-Id: erp-atelier-prod" \
-H "X-Device-Name: ERP%20Atelier" \
-H "X-Client-Mutation-Id: 6f1c2f0e-7a53-4f0b-9c58-0b8a4a7c2d11" \
-d '{"type": "supplier", "name": "Brasserie des Collines SA", "vat_number": "BE0999900134"}'
Response headers
| Header | Meaning |
|---|---|
X-Operation-Id |
Identifier of the operation when something was recorded in the history. It is used for reverting: POST history/operations/{operation}/revert |
X-Trashed: 1 |
The DELETE moved the record to the recycle bin instead of destroying it. It can still be restored |
X-Idempotent-Replay: 1 |
The response is the stored result of a request that was already executed |
X-Export-Fingerprint |
SHA-256 fingerprint of the exported data set |
Content-Disposition |
File name for exports |
Retry-After |
Delay in seconds before retrying after a 429 |
Deletions
A deletion almost never destroys anything immediately:
- a third party, an account, a journal, a rule or a fixed asset goes to the recycle bin (
X-Trashed: 1) and can be restored during the company's retention period, 90 days by default; - a posted entry cannot be deleted: it is reversed with
POST entries/{id}/reverse, which preserves the continuous numbering.