einvoicekit
Validate any EN 16931 e-invoice (Factur-X, ZUGFeRD, XRechnung, UBL or CII) against the full official rule set, from one command or one function call. No Java, no Saxon, no rule files to download.
pipx run einvoicekit invoice.pdf
invoice.pdf INVALID (cii, urn:cen.eu:en16931:2017)
BR-CO-15 /Q{urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100}CrossIndustryInvoice[1]
[BR-CO-15]-Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).
Exit code 0 means every file is valid, 1 means at least one is not, 2 means at least one could not be validated. That is the whole integration for a CI pipeline.
What this package is, honestly
It is a thin client. Each call sends the invoice over HTTPS to einvoicekit's validator, which processes it in memory to produce the verdict and drops it; nothing is stored. What you get in exchange is the real thing: the official rule sets, EN 16931, XRechnung 3.0.2, Factur-X 1.09 and Peppol BIS 3.0, run by the reference validator, not a hand-written subset of them.
Two promises follow from that:
- A verdict is a verdict.
valid=Falselists every broken rule with its official id, the official message and the XPath of the element at fault. - No silent green. If the service cannot be reached, you get an
exception, never
valid=True. The package has no fallback and no retry; a retry policy is yours to write.
Install
pip install einvoicekit
Python 3.10 or later. No dependencies.
Renamed in 0.2.0: the command was facturx and the error class
FacturxError. The package name and the import name are unchanged.
Use it from code
from einvoicekit import validate, EinvoicekitError
with open("invoice.pdf", "rb") as f:
result = validate(f.read())
result.valid # True or False
result.errors # [Finding(rule, message, path), ...]
result.warnings # same shape, never change the verdict
result.syntax # 'cii' or 'ubl'
result.profile # the profile URN the document declares, or None
result.raw # the API's JSON as a dict, untouched
validate(data, ...) takes the bytes of an XML invoice, or of a Factur-X /
ZUGFeRD PDF, which is unwrapped first so its embedded XML is what gets
validated. The result carries the API's JSON, field for field.
Keyword arguments:
| argument | meaning |
|---|---|
api_key |
an einvoicekit key; defaults to EINVOICEKIT_API_KEY; with neither, the free pool is used |
target |
"france" adds the BR-FR rules French platforms apply, opt-in per call |
base_url |
the API to call, default https://api.einvoicekit.com |
timeout |
seconds to wait for the answer, default 30 |
Use it from the command line
einvoicekit invoice.pdf
einvoicekit a.xml b.pdf --target france
einvoicekit invoice.pdf --json
einvoicekit invoice.pdf --warnings
EINVOICEKIT_API_KEY=eik_live_... einvoicekit invoice.pdf
--json prints the API's verdict as JSON on stdout, an array when several
files are given, and nothing else there; refusals go to stderr. --help
lists every option.
Limits, plainly
- Without a key: 10 validations a day per IP address, shared with the free tools on einvoicekit.com. The eleventh call is refused with the time the pool resets (midnight UTC) and a link to the free key.
- With a free key: 100 validations a month, plus 20 generated invoices in an allowance of their own. No card. Get one by signing in with GitHub.
- Pro: 29 € a month for 1,000 pooled credits, a validation spending one. Details.
Only a delivered verdict counts. A document the API cannot assess, a refused call and an error on the service's side cost nothing.
Errors
Everything that is not a verdict raises EinvoicekitError with a stable code:
| code | HTTP | meaning |
|---|---|---|
bad_request |
400 | the request itself was wrong (bad target, empty body) |
unauthorized |
401 | a key was sent and it is unknown, malformed or disabled |
too_large |
413 | over 5 MB |
unreadable_document |
422 | the API read the file and cannot assess it: a plain PDF, an unsupported profile |
pool_exhausted |
429 | the free daily pool is spent; resets_at and upgrade say when and where |
rate_limited |
429 | too many calls in a short window; slow down |
quota_exceeded |
429 | the key's monthly allowance is spent; upgrade says where to get more |
service_unavailable |
5xx | the service answered but could not validate |
network |
0 | no response at all |
A wrong key is never a fallback into the free pool: send no key at all to use it.
Scope
Validation checks the invoice XML: the schema and every business rule of the profile the document declares. It does not check the PDF container's own PDF/A conformance; that check runs on the generation side of the API.
Full API documentation, the French rules and the generation endpoint: einvoicekit.com/docs.
Licence
MIT.
Release files for einvoicekit 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| einvoicekit-0.2.0.tar.gz | 13.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| einvoicekit-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.7 kB
Release files / einvoicekit-0.2.0.tar.gz
| Download URL | einvoicekit-0.2.0.tar.gz |
|---|---|
| Size | 13.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bf46e5a13ba8e23d36ca91eca0b1ac12719406dabb85070b9da52e08d61ea41d
|
|
BLAKE2b-256 checksum How to use checksums |
755a47d879ec0304fe506cede04af40e311527546d645db11e0bd54ec17af845
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / einvoicekit-0.2.0-py3-none-any.whl
| Download URL | einvoicekit-0.2.0-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca0a2127f81c589c6fefa702afaa450bdc0caac9cf863472175f0b2a54e2844e
|
|
BLAKE2b-256 checksum How to use checksums |
6f2a6d16bba968b3c97cd6de9a1c53d37953dc49a26e50c99d198b8314ef5a16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency log