Versioning
eFakturuj versions its public API in the URL path. The current
contract lives at /api/v1/… and is mounted from
backend/app/main.py:
app.include_router(api_router, prefix="/api/v1")
v1 is the only stable contract today. A future major version (when
we need to ship changes that break existing callers) will live at a
new prefix — /api/v2/… — running side-by-side with v1 for the
deprecation window described below.
Deprecation policy
When we deprecate a route, we will:
- Add
Deprecation: trueto responses from the deprecated route (per RFC 8594) - Add a
Sunset: <RFC 1123 date>header naming the planned removal date — with a minimum 6-month window between announcement and removal - Document the migration in the Changelog with the before / after request and response side-by-side
- Send an email to the contact on every API key still calling the deprecated route, 30 days before sunset
Honesty note. This is the policy we are committing to. The backend does not yet emit
DeprecationorSunsetheaders — there are no deprecated routes today, so there's been nothing to attach them to. The infrastructure ships with the first deprecation; until then, watch the changelog.
What counts as a breaking change
We treat the following as breaking — they only ship in a new major version:
- Removing a route
- Removing a field from a response payload
- Narrowing accepted enum values on a request field (e.g.
dropping
"acknowledged"fromstatus) - Changing a
2xxresponse into a4xxfor a request that was previously valid - Promoting an optional request field to required, or tightening format constraints on an existing field
- Renaming a JSON field
These are explicitly non-breaking and may ship in v1 minor
releases:
- Adding a new route
- Adding a new optional request field
- Adding a new field to a response payload (consumers should ignore unknown fields)
- Adding a new enum value to a response (your client should treat unknown enum values as opaque pass-through, not crash)
- Adding a new
4xxfor a new validation rule on a previously- unvalidated input
If you build your client to ignore unknown response fields and
unknown enum values, you are forward-compatible with every minor
release of v1.
Pinning the OpenAPI spec
The live spec for v1 is served at:
https://docs.efakturuj.sk/openapi.json
It tracks the production deployment. If you generate code from it (a typed Dart client, a Python SDK, etc.) and want a reproducible build:
- Pin during release.
curlthe spec into your repo at release time (docs/openapi-v1-2026-05.json), commit it, and run your generator against the committed file. CI re-runs use the pinned file, not the live URL. - Audit drift. Periodically diff the live spec against your
pinned copy (
curl -s https://docs.efakturuj.sk/openapi.json | diff -u docs/openapi-v1-2026-05.json -). Non-breaking additions show up here and let you decide whether to upgrade. - Track the changelog. Changelog names the
release each spec change ships in. We have not yet cut tagged
spec releases — for
v1the live URL is the canonical artefact.