BR-KSA-CL-04 Warning — the invoice is accepted

Exemption reason code (BT-121) not on the list for its category

When the VAT breakdown for a zero-rated, exempt or out-of-scope category carries an exemption reason code, only a code from that category's VATEX list is accepted, spelled exactly. VATEX-SA-34 without its suffix, vatex-sa-35 in lower case, a zero-rating code on an exempt breakdown — all of them fail here. It is a warning, so the invoice is accepted.

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

If VAT category Code (BT-118) is 'Z', or 'E', VAT exemption (or exception) reason code (BT-121) must exist with one of the values from paragraph 11.2.4 of XML implementation standards on Tax exemption (or exception) reason code - specific to Saudi Arabia.

What does this mean?

The rule runs on the VAT breakdown (BG-23), not on the line: on every cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory whose letter in cbc:ID is Z, E or O. It reads the reason code cbc:TaxExemptionReasonCode there and compares it with the list for the letter beside it, not with all the lists together. The line's cac:ClassifiedTaxCategory carries the letter and the rate, and this rule does not look at it.

The lists, as the executable test in the Authority's SDK (R3.4.8) has them: for zero-rated Z, VATEX-SA-32, VATEX-SA-33, VATEX-SA-34-1 to VATEX-SA-34-5, VATEX-SA-35, VATEX-SA-36, VATEX-SA-EDU, VATEX-SA-HEA and VATEX-SA-MLTRY; for exempt E, VATEX-SA-29, VATEX-SA-29-7 and VATEX-SA-30; and for out of scope O, a single code, VATEX-SA-OOS. The message names Z and E only; the test covers O as well.

The zero-rated list inside the SDK carries four more codes that the table in paragraph 11.2.4 of version 1.2 of the XML Implementation Standard does not: VATEX-SA-DIPLOMAT, VATEX-SA-DUTYFREE, VATEX-SA-ROYALDECREE and VATEX-SA-32(bis). The test accepts them, but check the current table on zatca.gov.sa before you build on them.

The comparison is literal: the code is one exact word from the list, in capitals; spaces around it are trimmed before comparing, while a space inside it fails it. And the rule speaks only when a non-empty code is there: a breakdown with no code, or an empty one, passes it — absence has its own codes: BR-KSA-69 for zero-rated, BR-KSA-23 for exempt and BR-KSA-24 for out of scope. So this code always means one thing: you wrote a code, and it is not on its category's list.

It is a warning: the invoice is accepted and recorded, with the warning attached. But the code is the basis on which this base carries no VAT, and a code off the list is a basis the list does not know. When the code is VATEX-SA-EDU or VATEX-SA-HEA, another rule joins in, and that one is an error: BR-KSA-49 requires the buyer's national ID.

Why does it happen?

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

  • A code without its suffix: VATEX-SA-34 on its own, where the list only knows VATEX-SA-34-1 to VATEX-SA-34-5; or a suffix invented by analogy, such as VATEX-SA-29-1.
  • A different spelling: vatex-sa-35 in lower case, VATEX_SA_35 with underscores, or VATEX SA 35 with spaces.
  • A dash that is not a hyphen: a code copied from a PDF or a Word file in which the ordinary hyphen became an en dash –, so it looks right and matches nothing.
  • A code from another category's list: VATEX-SA-29 (exempt financial services) on a zero-rated breakdown, VATEX-SA-32 on an exempt one, or anything other than VATEX-SA-OOS on an out-of-scope one — usually from a mapping that takes the reason from one list for everything that is not standard-rated.
  • The reason text in the code field: Export of goods where VATEX-SA-32 is expected.
  • European codes from an imported system, such as VATEX-EU-G or VATEX-EU-O; the Saudi list does not know them.

How to fix it

3 steps, then send the invoice again.

  1. 1
    Make the code a value from a closed list, not free text

    Store the code in your system as a value from a fixed enumeration tied to its category, not a text field that takes whatever a user types. If the code comes in from outside, normalise it once — capitals, no surrounding spaces — then refuse anything that does not match its category's list before the XML is built, rather than sending it and waiting for the warning. The official table is paragraph 11.2.4 of the XML Implementation Standard on zatca.gov.sa.

  2. 2
    Write it in the VAT breakdown, under the letter it belongs to

    Its place is the category block inside the breakdown, after the letter and the rate, with the reason text beside it: <cac:TaxCategory><cbc:ID>Z</cbc:ID><cbc:Percent>0</cbc:Percent><cbc:TaxExemptionReasonCode>VATEX-SA-35</cbc:TaxExemptionReasonCode><cbc:TaxExemptionReason>Medicines and medical equipment</cbc:TaxExemptionReason><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory>. Make sure the code is from the list of the letter above it: a correct code under the wrong letter fails just as an invented one does. The text has its own rule: BR-KSA-83.

  3. 3
    Pick the suffix that describes the supply

    The international transport codes are five, not one: VATEX-SA-34-1 transport of goods, VATEX-SA-34-2 transport of passengers, VATEX-SA-34-3 services directly connected and incidental to international passenger transport, VATEX-SA-34-4 supply of a qualifying means of transport, and VATEX-SA-34-5 services relating to goods or passenger transportation. Which one fits your supply is a tax question for zatca.gov.sa; what the rule says is that the code without a suffix is none of them.

This code does not block acceptance, so the invoice you have is compliant. Correct the data so the warnings disappear from future invoices.

Does ZATCA Tools prevent it?

Yes. The reason code in ZATCA Tools is never free text: it is picked from a fixed list of fifteen codes in TaxCategories, each tied to its category, and reasonCodeFor drops any code that does not belong to the line's category before the VAT breakdown is built — so a code that reaches the XML is always from its category's list. The invoice form only offers the reasons of the chosen treatment; the API upper-cases what it receives and then refuses the request with a 422 if the code is not on the list or belongs to another category; and category O always takes VATEX-SA-OOS. Two limits, stated plainly: our list does not yet include VATEX-SA-MLTRY or the four newer codes, so a merchant who needs one of them cannot pick it here today; and the reason is optional for Z and E, so when it is left out no code is written at all — which brings another warning, BR-KSA-69 or BR-KSA-23, not this one.

Related codes

Frequently asked questions

I wrote the code correctly and the warning is still there. Where is the mistake? +
In one of three places: the letter above it, because the code is compared with its category's list, not with all of them; a character the eye does not see, such as an en dash or a non-breaking space copied from a document; or the block itself, since the code can be right on your system's screen and wrong in the breakdown that was sent. Open the XML you sent and read cbc:TaxExemptionReasonCode in every cac:TaxSubtotal, character by character.
How does it differ from BR-KSA-69, 23 and 24? +
Those speak when the code is missing or empty; this one speaks when a code is there and is not on the list. They never meet on the same breakdown: an empty code passes this rule, and a non-empty code passes those. So if you see this code, the fix is to correct the code, not to add one.
Does the code go on every line as well? +
No. The line carries the letter and the rate in cac:ClassifiedTaxCategory, and the reason is written once, on the VAT breakdown for its category — which is how the Authority's own sample of a simplified invoice with a zero-rated item in its SDK writes it. This rule reads the breakdown and nothing else.
The invoice was accepted with this warning. Do I need to do anything about it? +
The document was recorded as it was sent, and its code does not change. If the mistake was a spelling and the basis itself is right, correct the mapping and the next invoices go out clean. If the category itself was wrong — an exempt supply sent as zero-rated, say — that is the tax treatment of an issued document, corrected with a note, and a matter for your adviser or zatca.gov.sa. How notes work is in credit and debit notes in Saudi e-invoicing.
Should I use VATEX-SA-DIPLOMAT or VATEX-SA-DUTYFREE? +
The executable test in the Authority's SDK accepts both on category Z, but neither is in the table of version 1.2 of the XML Implementation Standard. Check the current table on zatca.gov.sa, and whether the basis applies to your supply, before you write either.
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