Check an incoming invoice before it is booked

Three checks before booking — and a clear statement about what was checked.

For an e-invoice, “checking” means three different things, and they get mixed up easily. First: is the file readable and in a known format? Second: do the figures add up — line items, tax amounts, totals? Third: does the invoice match your order? The API covers the first two questions; your system answers the third. This page says which call answers which question, so nobody reads a promise that is not there.

What comes in

The received file: XRechnung XML or a ZUGFeRD PDF

The invoice data read from it, as JSON

Your order or contract as the yardstick

The sender's country, because the rules hang off it

What this solves

01

Readable and detected

The parse endpoint says whether the received file can be read as an e-invoice. If that fails, the case is settled before anyone retypes a number.

02

Internally consistent

On the extracted fields, the validate endpoint answers the question: would this invoice data make a compliant invoice? The response carries valid plus errors and warnings with rule code and field.

03

What the validate endpoint does not judge

It judges invoice data, not the bytes of someone else's file — and formally compliant does not mean factually right. Whether the amount is correct is answered by your order, not by the standard.

04

The match against your order stays with you

Supplier number, order reference, agreed price, tax rate: only your system can make that comparison. The API supplies the fields for it — in the same structure it uses for generating.

One real example

An excerpt from the recipe “Validate an existing invoice” — the data the validate endpoint judges.

json
{
"invoice": {
"invoiceNumber": "RE-2025-003",
"countrySpecific": {
"countryCode": "DE",
"leitwegId": "991-12345-67"
},
"taxSummary": [
{
"taxRate": 19,
"netAmount": 1500,
"taxAmount": 285
}
],
"subtotal": 1500,
"total": 1785
}
}

POST /api/v1/invoice/DE/validate

Response: valid plus errors and warnings with rule code and field. For this example: 1,500.00 € net, 285.00 € tax, 1,785.00 € total — internally closed and carrying a Leitweg-ID, so no BR-DE-15.

The full recipe

The endpoints involved

  • Parser

    POST /api/v1/invoice/parse

    Live
  • Validator

    POST /api/v1/invoice/{countryCode}/validate

    Live

Compared to the alternative

The alternative is: bookkeeping or the tax adviser notices. By then the invoice is booked, the month is closed and the correction costs more than the check would have.

Read the comparison

How it runs

  1. 1

    Read the incoming file: POST /api/v1/invoice/parse returns the fields.

  2. 2

    POST /api/v1/invoice/DE/validate on the extracted data — rule code and field instead of “something is off”.

  3. 3

    Compare against the business facts: order reference, price and tax rate against your order, then book or reject.

What it costs at this volume

Around 1,000 invoices per month fit the Starter plan at 23 € per month.

All prices net, plus VAT · 20 % off when billed annually · Free tier without a credit card

All plans

Limits

  • The validate endpoint judges invoice data, not the received document itself. For a statement about someone else's file, parsing is the first and the meaningful step.
  • Formal conformance is not factual correctness: the rules of the standard say nothing about your amounts.
  • The endpoint requires a bearer key; with an exhausted quota even a pure check is rejected (429).

Frequently asked questions

Can I upload someone else's XRechnung and have it checked?

You read it with the parse endpoint first and then check the extracted data. The validate endpoint takes invoice data as JSON, not a file.

What does valid mean in the response?

That the submitted invoice data satisfies the rules that were checked; errors and warnings name rule code and field where they do not. It is not a statement about whether the amounts match your order.

Does a check count against my quota?

A check generates nothing and is not counted as generation. It still needs a valid key, and with an exhausted quota the API answers 429.

Check before booking — with a clear statement about what was checked.