eliDocs
E-invoicing answers

Which version of the rules is my invoice checked against?

Two version axes decide the answer, the spec your document declares and the ruleset your validator bundles, and only the second one is yours to control.

E-invoice rulebooks are versioned files, and they move. If you do not know which version judged your document, you do not really know what “valid” meant. Two independent axes decide it, and they are worth keeping apart.

The two axes

The two axes

The spec axisNot yours to set

Set byThe document itself

The standard your document declares, through its CustomizationID. An XRechnung invoice says it is an XRechnung invoice; a Peppol BIS Billing 3.0 invoice says so too. This is a property of the file, not a setting on the request, and it is what selects which country or network overlay applies at all.

The ruleset axisYours to control

Set byThe validator you send the document to

The specific version of the rule artifacts the validator bundles to check that spec. Two validators can agree completely on what your document claims to be and still disagree on the verdict, because one of them is running last year’s Schematron.

The second axis is the one you can actually control, and the one worth asking a vendor about.

Rulebooks move on the authority’s calendar, not yours

Rulebooks move on the authority’s calendar, not yours

Each authority publishes on its own schedule, and the schedules do not line up.

XRechnung looks the most orderly and is not: KoSIT sets each normative release’s validity date individually, and the bugfix bundles inside a line land whenever they are ready and are valid from the day they are published, with no transition window at all. The bundle in force today arrived that way. Peppol cuts releases on the network’s own timetable and makes them mandatory on a date the network sets, which can arrive before a vendor has finished adopting it. Factur-X and ZUGFeRD move together as one joint pack, on neither of those calendars.

So “we support XRechnung” is not a statement with a stable meaning. The meaningful version of that sentence names a release.

What a validator should tell you

What a validator should tell you

Every Beliq validation response reports what it applied, rather than leaving you to infer it:

schematronVersionfield

The EN 16931 core rules that ran, also exposed as the x-schematron-version header.

ciusVersionfield

The country or network overlay version, when one was detected.

rulesetArtifactsfield

Every rule artifact that ran, each with its version and its own hash.

Beliq-Ruleset-Resolvedheader

Names the ruleset actually applied to this request.

For formats validated against a schema rather than business rules, schematronVersion is deliberately absent and a format-specific bundle version appears instead. That absence is a signal, not an omission: it tells you no business-rule layer existed to run.

Choosing which ruleset runs

Choosing which ruleset runs

Beliq does not auto-update rule artifacts. Every version bump is reviewed and tested before rollout, and changes are classified before they ship:

Safe

Cannot make a previously-valid document invalid: a false-positive fix, a rule relaxation, a code-list addition. These roll straight into the current ruleset.

Breaking

Can make a previously-valid document invalid. These are announced on the day they take effect at the latest, and the outgoing ruleset stays selectable for at least 6 months from that day. Where the authority’s timetable allows an announcement ahead of the date, the upcoming bump is machine-readable until then under scheduledChanges on the public GET /v1/rulesets catalog, with the version it moves to, the date it takes effect and the date the outgoing ruleset stops being served at all. Polling that endpoint is how you learn about such a bump in advance rather than on the day.

scheduledChanges tracks the ruleset axis and nothing else. A document Beliq generates can also stop being valid because the generator changed under a ruleset that did not move: a field the builder used to supply on your behalf, withdrawn because supplying it was wrong. No row appears on GET /v1/rulesets for those, because no version moves; they are announced on the changelog. Note that the remedy is the opposite one: pinning the outgoing ruleset preserves the rules, not the output, so it cannot protect a document whose content changed.

Selection happens through a channel rather than a hard-coded version number. latest is the default and the system-wide fallback; an organisation can set its own default in the dashboard; a single request can override both with the Beliq-Ruleset header. Once a breaking bump takes effect, the outgoing ruleset becomes selectable as previous, so you decide when to adopt the new rules instead of being moved automatically. A format with nothing for the channel to reach says so honestly by setting rulesetFellBack on the response: either no breaking bump sits behind it, or the authority has since made the successor mandatory, at which point Beliq stops picking the superseded ruleset on your behalf and only an exact pin still reaches it. Four format families retain a ruleset today: XRechnung, Peppol BIS Billing, Factur-X and France CTC, of which Peppol’s is superseded. GET /v1/rulesets is the current list.

For the narrower case of reproducing one earlier verdict exactly, the same header takes exact per-format pins written as artifactKey:version. Pins are per request and are not permanent: retention is bounded, and a response served by a retained ruleset carries rulesetSunsetsOn, the date after which that pin stops resolving.

Related