BR-KSA-69 Warning — the invoice is accepted

Zero-rated category without an exemption reason code

Every VAT breakdown whose category is Z, zero-rated, carries a reason code from the Authority's list, such as VATEX-SA-32 for export of goods or VATEX-SA-35 for medicines. It is a warning, so the invoice is accepted, but it leaves at a zero rate without stating its basis. The rule reads the document-level VAT breakdown, not the line.

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

A VAT breakdown (BG-23) with VAT Category code (BT-118) 'Zero rated' shall have a VAT exception reason code (BT-121).

What does this mean?

The place being checked is the document's VAT breakdown (BG-23): every cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory whose cbc:ID (BT-118) is Z. Inside it, cbc:TaxExemptionReasonCode (BT-121) must be present and must not be empty once spaces are trimmed. The check runs per breakdown, and the rule names no document family: tax invoices, simplified invoices and their credit and debit notes are all covered.

The executable test in the compiled schematron the Authority ships with its SDK asks about presence only: is the element there, with something in it? The test text printed beside the message lists codes, but the condition that actually runs does not compare the value with them. Comparing the value is the job of another rule, BR-KSA-CL-04, also a warning: a code from the exempt list on a zero-rated breakdown passes this rule and fails that one.

The list BR-KSA-CL-04 accepts for the zero-rated category, with the wording of paragraph 11.2.4 of the XML implementation standard: VATEX-SA-32 export of goods, VATEX-SA-33 export of services, VATEX-SA-34-1 to VATEX-SA-34-5 for international transport of goods and passengers, the services connected with it and qualifying means of transport, VATEX-SA-35 medicines and medical equipment, VATEX-SA-36 qualifying metals, VATEX-SA-EDU private education to citizen, VATEX-SA-HEA private healthcare to citizen, and VATEX-SA-MLTRY qualified military goods. The SDK build we read also accepts VATEX-SA-DIPLOMAT, VATEX-SA-DUTYFREE and VATEX-SA-ROYALDECREE, whose wording is not in the standard's table we hold — take those from the Authority's current list on zatca.gov.sa.

The code does not travel alone: wherever it is present, the reason text (BT-120) must sit beside it in cbc:TaxExemptionReason, or BR-KSA-83 warns. A word-for-word match against the Authority's wording is written into the schematron but commented out, so what runs today is a check that some non-empty text exists. Writing the Authority's own English wording is still the safe choice.

It is a warning: the invoice is cleared or reported, and the code comes back with the acceptance in warningMessages. In our tests on the Authority's sandbox, a zero-rated document without the element at all came back with this code alone. BR-KSA-CL-04 stays silent when the element is absent or empty: its executable condition treats a missing code as acceptable and leaves the warning to this rule, which is what the live answer showed. Prepayment lines have a twin of this rule, BR-KSA-93.

Why does it happen?

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

  • The reason written only on the line, in cac:Item/cac:ClassifiedTaxCategory. UBL allows the element there, but this rule reads nothing except the document-level VAT breakdown, so the copy on the line is invisible to it.
  • A system built on the European EN16931 rules as published: they include BR-Z-10, which forbids any reason on a zero-rated breakdown, so the system leaves it out on purpose. The Authority's copy of those rules drops BR-Z-10 and adds this rule, which asks for the opposite.
  • The reason text sent without its code: Export of goods in cbc:TaxExemptionReason with no cbc:TaxExemptionReasonCode. The text is BT-120 and the code is BT-121, and this rule asks for the code.
  • A template that always writes the code element and only sometimes fills it, so <cbc:TaxExemptionReasonCode/> goes out empty or holding spaces — and to this rule empty is the same as absent.
  • A store shipping abroad zeroes the tax on the order, and the integration switches the category to Z without adding VATEX-SA-32 for goods or VATEX-SA-33 for services.
  • The category switched to Z to silence the VAT on a line — a sample, a gift, a discount, a price said to include tax — with no legal basis. Here the missing code is a symptom, not the fault: there is no reason because the supply is not zero-rated at all.
  • The code in the wrong place: in the text field, glued to the category letter (Z-VATEX-SA-32), or in a document note.

How to fix it

4 steps, then send the invoice again.

  1. 1
    Write the code and its text in the document VAT breakdown

    Inside every cac:TaxSubtotal/cac:TaxCategory whose category is Z, straight after cbc:Percent: <cbc:TaxExemptionReasonCode>VATEX-SA-32</cbc:TaxExemptionReasonCode>, then <cbc:TaxExemptionReason>Export of goods</cbc:TaxExemptionReason>, then cac:TaxScheme. The code in capitals exactly as listed, with no spaces and no prefix. You may keep it on the line as well, but this is the place that is checked.

  2. 2
    Pick the reason from what the supply really is

    The reason describes what actually happened: goods that left the Kingdom, a service to a non-resident, a medicine, international transport. Whether zero rating applies to your supply, on what conditions, and which documents you keep to support it, such as shipping documents, is a regulatory question for your tax adviser and zatca.gov.sa, not for us. If nothing on the list describes the sale, the letter itself is probably wrong and the line is standard-rated S — the four letters are covered in BR-KSA-18.

  3. 3
    Do not put a reason on the standard-rated breakdown

    Do not silence the warning by writing a reason on every breakdown in the document. A standard-rated S breakdown carries no reason, and the European rule BR-S-10, which the Authority kept, warns about it. The education and health codes bring a condition of their own: VATEX-SA-EDU and VATEX-SA-HEA require the buyer's national ID under BR-KSA-49, which is an error.

  4. 4
    An accepted invoice is not edited

    The warning means the document was recorded as it stands, so do not resend it or change it. Fix the mapping for the documents that follow. If it turns out the category itself was wrong — not only the code — the correction is a credit note followed by a new invoice under the right treatment, once your adviser confirms it; the steps are in credit and debit notes in Saudi e-invoicing.

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?

No, and that is a decision rather than an oversight: in ZATCA Tools the reason is optional and never guessed, because a guessed reason tells the Authority a legal basis the merchant never gave. On the invoice form a VAT treatment list appears once the establishment adds zero-rated in its establishment profile, and beside it a reason list whose first option is Not specified; it suggests the establishment's default reason or the last one it used for that category. The first zero-rated invoice with no history starts without a reason unless the merchant picks one, and it is issued and accepted with this warning. Over the API, tax_reason_code is optional. A line that names none takes the reason the other lines of its category name on the same document, when they all name one; when they name two it stays without one, since picking either would be a guess, and the response comes back with status warnings carrying this code. When no line names a reason, it takes the establishment's default for that category, then the last reason used for it on its issued documents, and otherwise goes out without one, with the same warning. A code our list does not know, a code of another category, or a code on a standard-rated line is refused before signing with invalid_lines. Shopify orders shipped out of the Kingdom with no tax charged are always issued zero-rated with VATEX-SA-32, so no zero-rated line leaves that integration without a reason. A credit or debit note inherits the category and the reason of the invoice it adjusts, so a note on a zero-rated invoice without a reason returns the same warning. The code is written with its English text in the document-level VAT breakdown only, and each reason gets its own breakdown: an API document mixing two zero-rating reasons goes out with two, each with its own amount, which ZATCA accepts with warning BR-Z-08; a full credit or debit note gives each reason back its own share. Our list does not include VATEX-SA-MLTRY or the newer codes in the Authority's SDK, and the API refuses them.

Related codes

Frequently asked questions

Was my invoice rejected because of this code? +
No. It is a warning: the invoice is accepted and the warning is recorded with it. If your invoice really was rejected, the cause is another code in the response — the Authority separates errorMessages, which reject, from warningMessages, which are only recorded. How to read the response is covered in ZATCA error codes explained.
I wrote the code on the line itself — why did the warning come back? +
Because the rule does not look at lines. Its context is cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory at document level, and the element inside cac:ClassifiedTaxCategory on the line is outside its check. Move the code and its text to the VAT breakdown, or write them in both places.
Is the reason text on its own, such as "Export of goods", not enough? +
Not for this rule. It asks for the code (BT-121) itself; the text (BT-120) is a separate field that BR-KSA-83 requires whenever the code is present. The European rules accept either one in other places; the Authority's version accepts only the code here.
I chose VATEX-SA-EDU and was asked for the buyer's national ID — why? +
Because zero rating for private education and private healthcare depends on the buyer being a citizen, so a document carrying either code carries the buyer's national ID with scheme NAT, or it is rejected under BR-KSA-49. The details are on that page.
What is the difference between this rule and BR-KSA-CL-04? +
This one asks whether the zero-rated breakdown has a code at all. BR-KSA-CL-04 asks whether the code belongs to its category's list. So the exempt code VATEX-SA-29 on a zero-rated breakdown satisfies this rule and fails that one. Both are warnings.
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