BR-KSA-EN16931-01 Rejects the invoice

Business process (BT-23) is not reporting:1.0

One element at the head of every Saudi e-invoice carries the fixed text reporting:1.0. It is not a description of what you are doing and not a version of your software — it is a constant the specification requires letter for letter, and any other value is a rejection.

The message text as the Authority sends it in English, unedited

Business process (BT-23) must be "reporting:1.0".

What does this mean?

The element is cbc:ProfileID, written at the head of the document before the invoice number. In the European specification, EN 16931, the field is BT-23, the business process type, and a value is chosen there from a list of profiles. The Saudi specification collapses that choice to a single literal: reporting:1.0.

And that is where the mistake behind this code comes from: reading the name of the field and answering it truthfully. A system that writes clearance on an invoice that goes through clearance, or writes the name of its own process, or copies a Peppol value out of a European example, describes itself perfectly accurately and is rejected. The field is not asking a question; it is requiring a constant.

The literal includes its shape: lower case, one colon, and 1.0 with the dot. Reporting:1.0, reporting:1 and reporting-1.0 are different strings, and so is the same text with a stray space or a newline inside the element.

It does not vary by document type: the same value goes on a tax invoice, a simplified one, and their credit and debit notes, and it stays reporting:1.0 even on a document that goes through clearance rather than reporting. In the rules we extracted there is not one other rule that speaks about BT-23 at all — no condition, no exception, no family attached.

Its position at the head is not a cosmetic detail if you are writing your own signer. In the library ZATCA Tools uses, the ext:UBLExtensions block — the one that carries the stamp and the signature — is spliced in by a text replacement that looks for the cbc:ProfileID tag and places the block immediately before it. The element is load-bearing for validation and for signing at once.

Why does it happen?

Ordered from the most common to the least — your cause is most likely the first or the second.

  • XML built on a European example, carrying the Peppol billing profile value instead of the Saudi text.
  • The field answered as a description: clearance, or reporting with no version, or B2C.
  • A version bumped by a developer who assumed it tracked the specification: reporting:2.0.
  • A value derived from an environment variable or a config key that separates sandbox from production.
  • A space or a newline inside the element, introduced by pretty-printing the file after building it.
  • The element dropped entirely. We cannot tell you whether its absence comes back as this code or as a schema failure — we read the text of each rule and its severity, not the test that fires it — and the right action is the same either way: write it.

How to fix it

3 steps, then send the invoice again.

  1. 1
    Write the constant exactly

    cbc:ProfileID with the value reporting:1.0, as a literal, with no surrounding whitespace and no newline inside it, on every document: tax invoice, simplified invoice, credit note and debit note.

  2. 2
    And derive it from nothing

    Not from an environment name, not from a config key, not from whether you clear or report, not from a row in a table. Every derived field is a field that can be wrong, and this one need never be: put it in code as a constant.

  3. 3
    Then check its neighbours in the header

    The head of the document carries other constants that go wrong the same way: the transaction code KSA-2 in BR-KSA-06, the document type BT-3 in BR-KSA-05, and the tax accounting currency in BR-KSA-68. A file built from a European example usually has all of them wrong, so reviewing them in one pass saves you a run of consecutive rejections.

Once corrected, send the invoice again. A rejected invoice was never recorded with the Authority, so it needs no credit note — send the corrected invoice itself.

Does ZATCA Tools prevent it?

Yes, and there is no route to anything else. The value reporting:1.0 is a private field on the library's invoice class, initialised to that string, with a getter and no setter — so neither ZATCA Tools nor any other consumer of that library could change it even deliberately. We pass no profile value in our payload at all. We verified this in the library file itself: the element is written from that fixed field on every document, ahead of the invoice number.

Related codes

Frequently asked questions

My invoices go through clearance rather than reporting. Is there a different value? +
No. The rule names one literal with no condition attached, and no other rule in the extract speaks about BT-23. Which path a document takes — clearance or reporting — is decided by the document type in KSA-2 and by the Authority endpoint you call, not by this field.
Is this a version I have to keep up with? +
Treat it as a constant, not a variable. It is a literal in the validation rules we extracted, and it has nothing to do with the version of your software, your integration, or the library you build the XML with. If a later specification changes it, zatca.gov.sa is where that news comes from.
Where exactly does it go? +
At the head of the document: after the extensions block that carries the signature, and before the invoice number, its UUID and its date. Element order in the UBL header is not free, so putting it in the wrong place produces a file that fails the schema before it ever reaches this rule.
You fixed this one — now avoid the next

ZATCA Tools builds the signature, the PIH, the counter and the encoding for you, and validates your data before it is sent. Start free, with no credit card.

Start for free

← All ZATCA error codes