FacturForge: Factur-X and CII Invoice Generator
Pricing
Pay per usage
FacturForge: Factur-X and CII Invoice Generator
Generate deterministic Factur-X UN/CEFACT CII invoice XML from structured JSON, optionally embedded in a PDF carrier, with bounded EN 16931 checks. No submission or filing.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
NICHOLAS SAVAGE
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
FacturForge — Factur-X / UN-CEFACT CII invoice generator
Give it structured invoice JSON. It gives you a byte-reproducible Factur-X (UN/CEFACT CII) XML document, optionally embedded in a PDF carrier, plus a machine-readable EN 16931 rule report that cites the rule behind every finding.
The same invoice and profile always produce the same XML bytes: element order
follows the XSD sequence, the VAT breakdown is sorted by (category, rate), and
amounts are computed in fixed-point at scale 2. Pin pdfTimestamp and the PDF
is byte-identical too, because the document /ID is derived from the XML digest
instead of being generated randomly.
What it does
| Mode | What you give it | What you get |
|---|---|---|
| generate (default) | an invoice object, a profile | CII XML as a downloadable record, its digest and byte count, and the rule report |
generate with emitPdf | the same, plus emitPdf: true | the above plus a PDF with the XML embedded |
validateOnly | an invoice object | the rule report only; no document is produced |
Set failOn to decide which findings make the run exit non-zero. The document
and the report are stored either way, so a "failed" run is still readable.
Input
Full contract in input_schema.json. Unknown fields are rejected, not
ignored — including anything that looks like a URL, because this Actor performs
no network requests of its own.
| Field | Type | Default | Notes |
|---|---|---|---|
invoice | object | – | required; the invoice payload, supplied inline |
profile | MINIMUM | BASIC_WL | BASIC | EN16931 | EXTENDED | EN16931 | MINIMUM and BASIC WL are not standalone EN 16931 invoices |
emitPdf | boolean | false | also write the PDF carrier; cannot be combined with validateOnly |
validateOnly | boolean | false | rule check only, no document |
businessProcessId | string | – | BT-23 business process type written into the document context |
pdfTimestamp | string (ISO 8601) | – | pins PDF timestamps for byte-reproducible output |
failOn | error | warning | never | error | which findings make the run exit 1 |
Output
One facturforge/actor-result/1 object per run, written identically to the
default dataset and to the OUTPUT key-value record, on success and on failure
alike. The shape is described in dataset_schema.json and output_schema.json;
a real local run's output is in ./sample-output.json,
produced by
npm ci && npm run buildmkdir -p storage/key_value_stores/default# the bundled EN 16931 fixture as the `invoice` fieldnode products/facturforge/dist/actor/main.js
so you can reproduce it apart from the timestamp and the duration.
The generated document is not inlined into that JSON. It is stored as its own key-value record, so you can download it as a file:
| Record | Written when |
|---|---|
invoice.xml | a document was generated |
invoice.pdf | emitPdf was set and the carrier was produced |
Exit codes:
| Code | Meaning |
|---|---|
0 | ran, result stored, failOn policy not tripped |
1 | findings at or above the failOn threshold (the document and report are still stored) |
2 | input missing, invalid, or containing an unknown field |
3 | runtime or storage failure |
Pricing
Pay per event, two events, charged once per run:
| Event | Price | Charged when |
|---|---|---|
invoice-document | $0.02 | once, after a generated document and its report have been written to both the dataset and OUTPUT |
invoice-validation | $0.01 | once, after a validateOnly report has been written to both the dataset and OUTPUT |
Nothing else is billable. In particular you are not charged for:
- a rejected or invalid input (exit
2), - a runtime failure (exit
3), - a run whose
failOngate tripped (exit1) — findings are news you asked for, and that run is a failed run, - a run whose result could not be stored,
- a start, a retry or a resurrect.
The charge is issued once per run, with an idempotency key, only after the result is durably stored, and the run's exit code never depends on whether the billing call succeeded. Your maximum cost per run is respected before any charge is sent.
Those two prices are what this repository's code, tests and ledger agree on. Whether they are what a published listing charges depends on the Apify Console configuration, which is not part of this repository.
Security
- No network egress. The run performs no outbound requests except to the Apify platform API that stores the result and issues the charge. There is no input field naming a URL, host or proxy, and unknown fields are rejected, so there is no user-influenced destination and no SSRF surface.
- No credentials. No input field is a secret, because the Actor has nothing
to authenticate to. The platform token it receives is used only for storage
and charging, and never appears in the dataset, the
OUTPUTrecord, an artefact or a log line. - Hostile XML is expected. The CII reader used by the internal round-trip check rejects DTDs and entity declarations outright (XXE and billion-laughs).
- Input size, JSON depth and line count are capped, and the run executes as an unprivileged user in the container.
Boundaries
- Not a submission platform. It transmits nothing. Not a PDP (plateforme de dématérialisation partenaire), not a PA/PPF connector, not a Peppol access point, not a Chorus Pro client, no e-reporting. Producing a file here creates no legal filing of any kind.
- Not a full validator. It implements a documented subset of EN 16931
business rules — presence rules BR-02..BR-16, arithmetic rules BR-CO-10/13/14
/15/16 and BR-CO-25, VAT-category rules BR-S-05/09, BR-Z-05/09, BR-E-10,
BR-AE-03 and BR-CO-26, plus Factur-X profile constraints. It does not run
UN/CEFACT D16B XSD validation, the complete CEN Schematron rule set, or any
national CIUS. The exact machine-readable scope travels in every result as
validationScope. - PDF/A-3 conformance is not asserted. The structural pieces are written —
the embedded file with
/AFRelationship /Alternative, the catalog/AFarray, and XMP carryingpdfaid:part=3plus the Factur-X extension schema — and the result reportspdfaConformanceAsserted: false. A synthesized visual page uses non-embedded standard-14 fonts, which are not PDF/A conformant. Verify any produced PDF with veraPDF. - Not tax advice. VAT treatment is taken from the input exactly as given.
- Not affiliated with or endorsed by FNFE-MPE, CEN, or any tax administration.
Licence
Apache-2.0.