You connect your system to the Fatoora platform, send your first invoice, and wait for ZATCA’s response. Instead of a clean acceptance, you get back a reply with a list of messages carrying codes and English text. This is the moment of truth in integrating e-invoicing with Qoyod’s e-invoicing system: understanding the structure of the error ZATCA returns determines whether your invoice is accepted or rejected.
This page is the parent reference for e-invoicing errors. It explains the categories of errors any system runs into, how ZATCA returns these errors in its response, the fundamental difference between a warning and a rejection, and how to start diagnosis systematically. Each category has a dedicated page that dives into its details, and you’ll find the links to them in their place within this guide.
The target audience here is the developer or technical integration lead who builds or maintains an accounting system’s connection to the Fatoora platform. That’s why you’ll find real JSON examples of ZATCA responses, along with an explanation of the technical fields as they appear in practice. English technical identifiers such as validationResults and status stay as they are because they are actual field names in the API.
Why e-invoices fail in the first place
An e-invoice in Phase Two is not a PDF file sent by email. It is a structured XML document that follows the UBL 2.1 standard, digitally signed, and linked by a hash chain to the previous invoice. Every element in this document is subject to strict validation rules set by ZATCA. Any deviation from the specification produces an error.
The causes of failure fall into four sequential layers. The invoice passes through them in order and stops at the first layer where it fails. Understanding this order saves you hours of wrong diagnosis, because you’ll know where to look first.
- Structure and XML format layer. Is the document syntactically valid XML? Does it follow the UBL 2.1 schema? Are the mandatory fields present and in their correct places?
- Business rules layer. Are the values logical? Does the sum of the invoice line items equal the total? Does the calculated VAT rate match the amount? Is the tax number in the correct format?
- Signature and hash layer. Is the digital signature valid? Is the certificate (CSID) valid? Does the hash value of the previous invoice match what ZATCA expects?
- Clearance vs. reporting layer. Did you send the invoice through the correct path? The tax invoice (B2B) goes through clearance, and the simplified invoice (B2C) is reported within 24 hours.
Structure layer (XML / XSD schema)
Business rules layer (BR-KSA)
Signature, hash, and stamp layer
Clearance or reporting layer
Breaking down the four layers
Each of the four layers deserves a deeper understanding, because the cause of the error determines where the fix belongs. Fixing at the wrong layer wastes time and does not solve the problem.
Layer one: structure and XML format. This layer verifies that the document itself is valid before looking at its content. ZATCA expects XML that follows the UBL 2.1 schema precisely, with the correct namespaces and the specified element order. An error here means ZATCA couldn’t read the invoice at all, so there’s no point checking its values. Systems that build XML by hand are the most exposed to this layer, while systems that generate the document automatically per the specification usually get past it.
Layer two: business rules. After confirming the document is readable, ZATCA examines the logic of its values. Are the totals consistent? Is the tax calculated correctly? Are the dates logical? Are the interrelated fields compatible? This layer is the source of most practical errors, because it exposes any flaw in your accounting system’s calculations before it reaches ZATCA.
Layer three: signature and hash. This layer verifies the integrity of security and sequencing. The digital signature proves the invoice was issued by you and was not altered. The hash chain proves the invoices are consecutive with no deletion or insertion. Any break in the certificate, the signature, or the sequence stops acceptance, and the cause is often a configuration issue that affects an entire batch of invoices rather than a single one.
Layer four: clearance vs. reporting. This layer concerns the path and the outcome. Even if the invoice is structurally sound, logically valid, and correctly signed, sending it through the wrong path produces a status error. Classifying the invoice type (B2B or B2C) correctly is a condition for passing this layer.
How ZATCA returns errors: the response structure
When your system sends an invoice to the Fatoora platform, ZATCA returns a structured response. The technical heart of this response is the validationResults object. This object contains everything you need to know the fate of the invoice and the cause of any problem.
The response usually contains the following core fields:
- validationResults: the object that gathers all the validation results.
- status: the overall status of the invoice. Common values are PASS, WARNING, or ERROR.
- errorMessages: an array of error messages that block acceptance of the invoice.
- warningMessages: an array of warning messages that do not block acceptance but point to a potential problem.
Each message within the two arrays follows the same shape: a type field for the message type, code for the error code that identifies it, category for the error category, and message for the descriptive text. The code is your most important key, because it is fixed and unchanging, whereas the text may be phrased in different ways.
This is an example of a response for an invoice that was accepted but with a warning. Note that status here is WARNING and the errorMessages array is empty, so the invoice is accepted:
And this is an example of a rejected invoice. status here is ERROR, and the errorMessages array contains at least one message. The presence of any element in errorMessages means the invoice will not be accepted until it is corrected:
The first diagnostic rule stems directly from this structure: Read status first, then examine errorMessages before warningMessages. Don’t waste your time on a warning while there’s an error blocking acceptance. Handle the errors, then look at the warnings.
An invoice rejected due to a failure in the signature layer takes a different shape. Note here that category points to the signature rather than the calculation, and this directs you straight to layer three:
And when the flaw is in the document structure itself, a different category appears, indicating that the XML did not pass schema validation. This type stops everything before looking at the invoice values:
Comparing the three rejected examples reveals a practical rule: the category field alone tells you which layer you need to examine, before you read the message text. BR_CALCULATION points you to business rules, SIGNATURE to the signature, and XML_SCHEMA to the structure. Build your routing logic on this field to shorten diagnosis time.
status: PASS, WARNING, or ERROR
errorMessages: errors that stop acceptance
warningMessages: notes that don’t stop acceptance
Each message: type, code, category, and message
Warning vs. rejection: the difference that changes everything
Confusing a warning with a rejection is the most common misunderstanding we see among developers new to the system. The difference isn’t cosmetic; it determines whether the invoice is legal and valid or not.
A warning alerts you to a potential problem or a recommended field that is missing, but it does not block acceptance of the invoice. The invoice is accepted, takes its number, and becomes valid. Even so, ignoring warnings over the long term may accumulate problems in your data quality or reveal a misconfiguration in your settings that deserves attention.
A rejection or error means the invoice was not accepted and does not exist legally. You cannot deliver it to the customer as an approved tax document until you correct the error and resend. Any element in the errorMessages array is enough to reject the entire invoice.
| Aspect | Warning | Error |
|---|---|---|
| status value | WARNING | ERROR |
| Appears in | warningMessages | errorMessages |
| Is the invoice accepted? | Yes | No |
| Does it need immediate correction? | Recommended, not mandatory | Mandatory before sending |
| Legal effect | The invoice is valid | The invoice does not exist |
Practical takeaway: treat every error as a top priority that halts the process, and treat every warning as an item on an improvement to-do list. Don’t mix the two in your application logic.
Clearance vs. reporting: two different paths for two different responses
One of the most important sources of confusion in diagnosing errors is failing to distinguish between the clearance and reporting paths. Each path has a different timing, a different response, and different consequences on failure.
Clearance applies to the standard business-to-business (B2B) tax invoice. Here you send the invoice to ZATCA before delivering it to the buyer, and you wait for real-time approval. If clearance fails, you don’t have an invoice to deliver in the first place. The details of this path are on the Clearance in e-invoicing.
Reporting applies to the simplified consumer (B2C) tax invoice. Here you issue the invoice and deliver it to the customer immediately, then report it to ZATCA within 24 hours. The invoice is valid upon issuance, and reporting is a later step. But repeated reporting failure exposes you to accountability later on.
The impact on diagnosis is direct: an error in the clearance path halts your transaction with the customer at that very moment, whereas an error in the reporting path may pass unnoticed until an audit. So monitor reporting results with the same seriousness as clearance, despite the difference in timing.
| Criterion | Clearance (B2B) | Reporting (B2C) |
|---|---|---|
| Timing | Before delivery | Within 24 hours after delivery |
| Effect of the error | Prevents delivery | Prevents acceptance of the report |
| Clearance-Status | 1 | 0 |
Error categories and their dedicated pages
E-invoicing errors are distributed across clear categories, each corresponding to the category field in the error message. Below is a map of the major categories along with what each one means in practice.
Structure and XML format errors
This category appears when the XML document itself is corrupted or does not conform to the UBL 2.1 schema. Examples: a missing mandatory field, wrong element order, an incorrect data type, or a missing namespace. These are structural errors that prevent ZATCA from reading the invoice at all. The dedicated XML errors page is in preparation and will cover all the codes of this category in detail.
Business rules and validation errors
This is the most common category. The invoice is structurally sound, but its values don’t pass the calculation rules. The best known are the BR-series errors, such as the sum of line items not matching the total, or an error in calculating VAT. The complete validation rules are documented on the Validation Rules for the invoicepage, and the dedicated validation errors page is in preparation to link each code to its cause and solution.
Signature and hash errors
This category appears when validation of the digital signature or the hash chain fails. Examples: an expired or invalid CSID certificate, a signature that doesn’t match the invoice content, or a hash value of the previous invoice that doesn’t sequence correctly. The dedicated signature errors page is in preparation and will detail the certificate lifecycle and the causes of signature failure.
Clearance errors, reporting errors, and rejected invoices
These categories relate to the sending path itself and its final outcome. Clearance errors occur in the B2B path before delivery, and reporting errors in the B2C path after delivery, while rejected invoices are the final result of any unhandled error. The pages for these three categories (clearance errors, reporting errors, rejected invoices) are in preparation, and will link each rejection scenario to the appropriate correction procedure.
For handling these responses programmatically, see the Error Handling in the APIguide, which explains how to capture the response, interpret its fields, and build retry logic.
HTTP status codes vs. validation errors
Many developers confuse two levels of response: the HTTP status code on one hand, and the validationResults content on the other. Distinguishing between them is essential for building sound handling logic.
The HTTP status code tells you whether your request reached ZATCA and was processed technically. The result of validating the invoice, on the other hand, lives inside the response body in validationResults. You may get a success code at the HTTP level while the invoice is rejected at the validation level, and the opposite is also possible.
| HTTP code | Meaning | Appropriate action |
|---|---|---|
| 200 | The request was processed, examine validationResults for the result | Read status inside the body |
| 202 | The invoice was accepted with warnings | Log the warnings, the invoice is valid |
| 400 | Invalid request or rejected invoice | Correct then resend |
| 401 | Authentication failure (certificate or token) | Verify the credentials and CSID |
| 500 | A temporary error on ZATCA’s server | Retry later with a backoff strategy |
The practical rule: don’t rely on the HTTP code alone to judge acceptance of the invoice. Always open the response body and read status and errorMessages. A 200 doesn’t automatically mean your invoice is accepted; it means your request was processed and the result is waiting for you in the body.
Retry logic and handling temporary errors
Not all errors are data errors. Some are temporary and relate to a network interruption or load on ZATCA’s server. Distinguishing a permanent error from a temporary one determines whether resending is helpful or harmful.
A permanent error relates to the invoice content: a wrong total, an invalid signature, a missing field. Resending the same invoice without correction will fail with the same result. Here your system must fix the cause first.
A temporary error relates to the connection or the state of ZATCA’s server, such as a 500 code or a timeout. Here retrying is reasonable, but under controls:
- Exponential backoff logic. Don’t retry immediately but at increasing intervals, so you don’t overload the server.
- A maximum number of attempts. Set a ceiling on the number of attempts before logging the invoice for manual review.
- Idempotency. Use the invoice’s unique identifier (UUID) to guarantee two invoices aren’t created when a send is repeated after an unclear interruption.
This distinction is fundamental specifically in the clearance path. Because clearance is real-time, a temporary interruption should be handled with a smart retry, not by canceling the transaction with the customer. Detailed retry logic is documented in the API Error Handling guide.
Step-by-step error diagnosis methodology
When a response comes back with an error, follow this sequence instead of guessing. This methodology turns diagnosis from a random search into a defined process.
- Read status. If it’s PASS, the invoice is accepted and you’re done. If it’s WARNING, it’s accepted with notes. If it’s ERROR, start correcting.
- Examine errorMessages first. Ignore the warnings temporarily and focus on what blocks acceptance.
- Capture the code field. The code is fixed and identifies the error precisely, unlike the text which may change. Log the code in your system to track its recurrence.
- Determine the category. The category guides you to the layer: business rule, signature, structure, or sending path.
- Link the code to its dedicated page. Every code is documented on its category’s page along with its root cause and the steps to resolve it.
- Correct then resend. After correcting, resend the invoice and verify that status has become PASS.
Log every recurring error with its code and date. This log reveals the patterns: if a single code recurs frequently, the problem is in your system’s configuration rather than a specific invoice, and treating the root cause saves you hundreds of future errors.
How Qoyod helps you deal with ZATCA errors
Qoyod handles the entire technical layer on your behalf, so you don’t need to craft XML by hand or manage the signature yourself. This reduces the categories of errors you might face from four to almost none.
- Automatic generation of compliant XML. Qoyod builds the invoice document per the UBL 2.1 standard and the Phase Two specification, eliminating structure and format errors at the source.
- CSID certificate and signature management. Qoyod manages the compliance stamp identifier (CSID), the digital signature, and the hash chain automatically, so you don’t worry about certificate expiry or a break in the sequence.
- Real-time clearance and reporting within 24 hours. Qoyod sends the tax invoice (B2B) for real-time clearance and reports the simplified invoice (B2C) within the statutory window, through the correct path for each type.
- Automatic VAT calculation. Qoyod calculates tax at 15% on every transaction and matches the line-item sums with the total, avoiding the most common business-rule errors.
It remains for you to register the compliance identifier (CSID) with ZATCA once at the start, and Qoyod guides you through this step. Qoyod’s technical support is available 24 hours, 7 days a week to help you if you face any error message you don’t understand.
Common errors worth early attention
Some errors recur for everyone starting integration. Knowing them in advance shortens the road.
Totals mismatch. The most common business-rule error. The sum of the net line items must equal the invoice total before tax. Any minor rounding difference is enough to reject the invoice, so unify the rounding logic in your system.
Tax number in the wrong format. An establishment’s tax number must be 15 digits beginning and ending with a specific digit per ZATCA’s rule. An error in the number of digits rejects the invoice immediately.
Expired CSID certificate. The certificate has a defined lifespan. If your system doesn’t renew it, all invoices start failing in the signature layer all at once. Monitor the certificate’s expiry date before it arrives.
Sending the invoice through the wrong path. Sending a B2B invoice through the reporting path instead of clearance (or vice versa) produces status errors. Make sure your system classifies the invoice type correctly before sending.
Initial registration and the CSID compliance identifier
Many of the first signature errors don’t relate to invoices, but to setting up the compliance stamp identifier (CSID) at the start of integration. This step is done once, but an error in it stops all invoices later.
The compliance identifier is the digital certificate that proves your system is authorized to issue signed invoices. You obtain it from ZATCA through an initial registration process in which your system is linked to your account with ZATCA. Even with a system that handles the technical layer, registering the identifier with ZATCA remains your responsibility, because it’s tied to your tax identity.
Common errors at this stage include an expired activation code (OTP), establishment data that doesn’t match your record with ZATCA, or an attempt to issue invoices before registration is complete. These are configuration errors, not data errors, and are resolved on ZATCA’s portal, not in your accounting system.
After registration is complete and the identifier is linked, the responsibility for renewing the certificate and managing the signature moves to your system. Here the difference shows between systems that manage the certificate automatically and those that leave it to the user, since the former spares you a sudden interruption when the certificate expires.
Let Qoyod handle the complexities of e-invoicing
From generating compliant XML to the digital signature and real-time clearance, Qoyod manages the entire technical layer so your invoices are issued in compliance with ZATCA without error messages.
From fixing the invoice to fixing the system
The difference between a technical team that spends its day chasing individual errors and a team that issues its invoices quietly is not in the number of errors, but in how they handle them. The first fixes each invoice on its own; the second fixes the root cause once.
Every recurring error code is a signal of a structural flaw in the setup. A recurring calculation code means a flaw in the rounding logic. A recurring signature code means a problem in certificate management. A recurring path code means an error in classifying the invoice type. Treat the root, and hundreds of dependent errors disappear all at once.
That’s why building an internal error log is worth the effort. Log every code, its date, and its recurrence count, and rank the codes by frequency. The most frequently recurring code is the first one you treat, because fixing it achieves the greatest impact. This approach turns errors from a daily nuisance into a clear improvement map.
Systems that handle the entire technical layer, such as Qoyod, remove most of these categories from the start, so your error log shrinks to the rare configuration cases. But understanding the structure remains useful, because it makes you able to read any error message and identify its layer immediately, whether you built the integration yourself or relied on a ready-made system.
Frequently asked questions
What is the difference between warningMessages and errorMessages in ZATCA’s response?
errorMessages contains the errors that block acceptance of the invoice, so any element in it means a rejection. warningMessages contains alerts that don’t block acceptance but point to a potential problem. Handle the errors first, then look at the warnings.
Is the invoice considered valid if status returns WARNING?
Yes. A WARNING status means the invoice was accepted and the errorMessages array is empty. The invoice is legally valid, and the warning is merely a note on data quality that is best addressed later.
What is the difference between clearance and reporting when an error appears?
Clearance applies to the tax invoice (B2B) and happens before delivering the invoice to the buyer, so its error halts the transaction immediately. Reporting applies to the simplified invoice (B2C) and happens within 24 hours after issuance, so its error doesn’t void an invoice that was already issued but does require handling.
Why should I rely on the code field rather than the text?
The code field is fixed and identifies the error precisely, whereas the descriptive text in message may be phrased in different ways or change. Tie your system’s logic to the code to ensure stable diagnosis and accurate tracking of each error’s recurrence.
What are the most common business-rule errors?
The sum of the net line items not matching the invoice total before tax, errors in calculating VAT at 15%, and a tax number in an incorrect format. Unifying the rounding logic and verifying the format prevents most of them.
Does Qoyod exempt me from dealing with these errors?
Qoyod handles generating compliant XML and managing the signature, the CSID certificate, clearance, and reporting automatically, reducing the technical error categories to a minimum. It remains for you to register the compliance identifier with ZATCA once at the start.