Mutabiq checks Saudi ZATCA Phase 2 e-invoice XML before you submit it: pre-validation against published ZATCA requirements, not an approval by the authority. This page explains one rule, BR-KSA-40.
Five checks a month on the Free plan. The file is checked in memory and is never stored.
The message ZATCA prints
[BR-KSA-40]-If it exists in the invoice, the seller VAT registration number (BT-31) must contain 15 digits. The first and the last digits are "3"..
What Mutabiq reports
One entry for each way this rule can be reported.
Reported as
What kind of value was found — empty, not_15_digits and the like — never the value itself.
Seller VAT registration number is empty
Reported asemptypresent but empty
What is wrong
The seller is registered under a VAT tax scheme and the cbc:CompanyID that carries the seller VAT registration number (BT-31) is present but holds no value. ZATCA requires that number to be 15 digits beginning and ending with 3 under BR-KSA-40, and an empty value fails that test. Note that the same rule behaves differently for the buyer: a blank buyer number is passed over, a blank seller number is not.
What to check in your ERP
The element is being written and the value behind it is not, which normally means the field is empty in the company or branch record the export reads rather than missing from the mapping. Check the VAT registration number held against the issuing entity - and against the branch, if your system holds one per branch - and confirm the export reads the entity that actually issued this document.
Seller VAT registration number is not 15 digits
Reported asnot_15_digitsnot fifteen digits
What is wrong
The seller VAT registration number (BT-31), in cbc:CompanyID under the seller's VAT tax scheme, is not exactly 15 digits. ZATCA rejects it under BR-KSA-40, which requires 15 digits and nothing else - too few, too many, or any character that is not a digit all fail the same test.
What to check in your ERP
Send the 15 digits alone: no spaces, no dashes, no VAT or SA prefix, and no group separators. The common causes are a number stored with formatting for display and exported as stored, a value padded or truncated to a fixed column width, and the commercial registration number being mapped into this field by mistake - it is a different number and usually 10 digits. Correct it in the company record or the mapping, not in the exported file.
Seller VAT registration number does not begin with 3
Reported asfirst_digit_not_3does not begin with 3
What is wrong
The seller VAT registration number (BT-31), in cbc:CompanyID under the seller's VAT tax scheme, is 15 digits but does not begin with 3. Every Saudi VAT registration number does, and ZATCA rejects one that does not under BR-KSA-40.
What to check in your ERP
A 15-digit number starting with something else is usually a different identifier that has been mapped into this field - a commercial registration number, a national identifier, or a customer account code. Check the VAT registration number recorded against the issuing entity in your system. If it is stored correctly and the export still writes something else, the mapping is reading the wrong field.
Seller VAT registration number does not end with 3
Reported aslast_digit_not_3does not end with 3
What is wrong
The seller VAT registration number (BT-31), in cbc:CompanyID under the seller's VAT tax scheme, is 15 digits but does not end with 3. Every Saudi VAT registration number does, and ZATCA rejects one that does not under BR-KSA-40.
What to check in your ERP
The last digit is the one most often lost or altered on the way out: a value truncated to 14 digits and then padded, a number copied from a document that wrapped, or a group identifier appended in place of the final digit. Compare the value in the export with the registration certificate digit by digit. If your system stores a group VAT number and a per-entity one, confirm which of the two the export is reading.
The clause that runs
Quoted from the validation-rule stylesheet ZATCA publishes, at the file and line named below. The executed guard is what the check runs; the reported test is what it prints when it fails, and the two are not always the same.
Executed guard
not(matches(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '^[0-9]{15}$') and starts-with(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '3') and ends-with(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '3'))
Reported test
matches(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '^[0-9]{15}$') and starts-with(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '3') and ends-with(//cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID, '3')
As shipped in ZATCA SDK 3.4.8: the copy quoted here is, byte for byte, the file that release ships. The date in the file name is the name ZATCA gives the file; the rules in it are those of SDK 3.4.8.
A worked example
A synthetic document from the measured test corpus that trips this rule, shown where it differs from one that passed. Mutabiq's report names the class of the value, never the value itself.
Where it differs from a document that passed
− This example
+ A document that passed
</cac:PostalAddress><cac:PartyTaxScheme>−This example: <cbc:CompanyID>30000000000003</cbc:CompanyID>+A document that passed: <cbc:CompanyID schemeID="HQ">300000000000003</cbc:CompanyID> <cac:TaxScheme> <cbc:ID>VAT</cbc:ID>