CLI
The Beliq CLI validates, generates, parses and converts e-invoices from a terminal or CI. Each verdict shows the check depth the API states for it.
Available
The beliq CLI wraps the same API as the SDKs for the terminal and CI. It is a thin layer over the Node SDK, so validation, generation, parsing, and conversion behave identically to every other path.
- Package:
beliq-clion npm (binarybeliq) - Source: github.com/beliq-eu/beliq-cli
Install
npm install -g beliq-cli
# or run without installing
npx beliq-cli validate invoice.xml
Authentication
The CLI reads your key from --api-key or the BELIQ_API_KEY environment variable (the flag wins over the env):
export BELIQ_API_KEY="blq_..."
beliq me # zero-quota credential check
Options
| Option | Environment | What it does |
|---|---|---|
--base-url <url> |
BELIQ_BASE_URL |
API base URL, default https://api.beliq.eu. Self-hosted deployments only |
--auth <mode> |
BELIQ_AUTH |
How the key is sent: header (default, X-API-Key) or bearer. Any other value is a usage error |
--json |
Machine-readable JSON on stdout | |
--content-type <type> |
The input’s media type for validate, parse and convert. Without it, input starting with %PDF- is sent as application/pdf, anything else as application/xml |
|
--france-ctc |
validate also applies the French CTC rules (BR-FR-CTC) |
beliq --help lists every command with the values each flag accepts.
Commands
| Command | What it does |
|---|---|
beliq validate <files...> |
Validate one or many XML or PDF invoices. Each verdict shows the check depth the API states for it (Reading a verdict) |
beliq generate <data.json> --standard <standard> |
Generate a document from an EN 16931 invoice. --standard is xrechnung, zugferd, facturx, peppol-bis, fatturapa, facturae, eslog or ksef |
beliq parse <file> |
Extract a canonical JSON invoice from XML or a hybrid PDF |
beliq convert <file> --target-format <format> |
Convert within the EN 16931 family. --target-format is cii, ubl, zugferd, facturx, xrechnung or peppol-bis. From an XML source the result is XML for every target, facturx and zugferd included. From a hybrid PDF source, a facturx or zugferd target returns a PDF (it needs --output): as sent, with only its annotation flags set as PDF/A asks, when its embedded XML already is the target, and otherwise re-wrapped around the converted XML; every other target returns XML |
beliq me |
Confirm a key works, with no quota cost |
Batch validation
validate accepts many file arguments, shell globs, and a directory (walked recursively over .xml and .pdf). It prints a per-file row (PASS, FAIL or ERROR, the error and warning counts, and the check depth) and an aggregate summary. A directory is a batch even when it holds one file, so its --json shape does not depend on how many invoices it contains:
beliq validate invoices/ # every .xml / .pdf under invoices/
beliq validate out/*.xml --fail-on error # the shell expands the glob
The CLI does not expand a glob itself, so leave it unquoted. A file argument of - reads the document from stdin.
Reading a verdict
For one document, validate prints a verdict line: the verdict word, the detected format and profile, the check depth, and the Schematron version where one ran. Below it come the error and warning counts and a table of every finding.
VALIDandINVALIDare the API’svalid.validmeans the document passed the rule packs and schemas Beliq runs for its format, in the versions the result names. It does not mean every recipient, validation tool or tax authority accepts it.- The check depth is the label the API sends in
verificationBadgeLabel, printed as it came. How verification works says what each depth means. Where the API sends no label, the CLI printscheck depth not statedand names no depth. - For a PDF, a line says which embedded XML the verdict is about. The PDF itself is not checked.
- When the result carries
franceCtcBlockingRuleIds, the CLI prints the API’s message for them with the rule ids, and the file fails with exit code1under every--fail-on, also where the verdict isVALID. The API reports those ids besidevalidand does not fold them into it.
generate names the same depth in its summary, or not validated with --no-verify. convert prints no verdict and no depth: a successful convert means the API validated the converted XML before returning it. For a facturx or zugferd target at profile en16931 the converted document carries the plain EN 16931 identifier, so it is checked as EN 16931 CII and against no Factur-X profile schema.
Exit codes
The exit code is the contract for scripts and CI:
| Code | Meaning |
|---|---|
0 |
Success. For validate: every document passed --fail-on, and no result carries France CTC blocking rule ids |
1 |
A document failed --fail-on, or its result carries France CTC blocking rule ids (franceCtcBlockingRuleIds). The France case fails the file under either --fail-on value, also where valid is true |
2 |
Usage error |
3 |
API error (auth, quota, rate limit, a rejected document), the API could not be reached, or an unexpected error. Never a verdict on the document |
4 |
I/O error (file not found or unreadable) |
In batch mode the code covers the whole run: 3 if any file could not be checked, else 1 if any document failed, else 0. A missing key (401), a refused key or a forbidden request (403), or a rate limit (429) stops a batch: the CLI prints the API error instead of the report and exits 3.
--json prints the raw result (a batch report { total, passed, failed, errored, results } in batch mode) as the only thing on stdout, so piped output stays clean. Without it, validate, parse and me print their human-readable report on stdout; generate and convert print the document on stdout and a one-line summary on stderr.
In a batch report, the row of a checked file carries the file, a status of pass or fail, and every field of the API result. status is the CLI’s call under --fail-on and the France rule, so a row can be fail with valid: true: a warning under --fail-on warning, or France CTC blocking rule ids. A file that could not be checked has status: "error" and a message.
Errors
An API error prints its code and message on stderr. When the API names the rules a document failed, the CLI prints them after the message in the same table validate uses. generate names them when it refuses to return an invoice that fails its own validation (422 INVALID_INVOICE), and convert when it refuses a converted document that fails validation (422 CONVERSION_OUTPUT_INVALID, the details). With --json, stdout also carries the error as { "error": { "status", "code", "message", "details" } }.
See also
- Node SDK: the client the CLI wraps.
- GitHub Action: run the same validation in a pull request.
- Quickstart: the underlying API in five minutes.