Qoyod
Pricing

Knowledge Base

E-Invoice Structure in Saudi Arabia (UBL 2.1)

Every Phase Two–compliant e-invoice in Saudi Arabia is not just an image or a PDF file, but a structured XML document that systems read before any human does. This document is built on a fixed, predefined structure: a specific ordering of elements, a precise nesting between them, and main sections each with a clear role. If this ordering breaks or a mandatory element is missing, the Fatoora platform rejects the document or issues a warning.

This technical guide is aimed at developers and technical accountants who want to understand the structure of the e-invoice document from the inside: what the three major sections are, how they interlock within a single XML tree, and the ordering of elements among them. We focus here on the overall structure only. As for the deep details of each section (header fields, line-item composition, the XSD schema), each has its own dedicated guide that we reference where relevant. This guide is part of the e-invoicing technical documentation.

series. Qoyod’s e-invoicing software builds this structure automatically behind the scenes, so you never need to write XML by hand. But understanding the structure helps you read the generated invoice, interpret validation messages, and confirm that the data is complete before submission.

What is meant by e-invoice structure?

The invoice structure is the way invoice data is arranged inside a single XML document. This structure follows the UBL 2.1 standard (Universal Business Language), the global standard adopted by the Zakat, Tax and Customs Authority (ZATCA) for Phase Two of e-invoicing.

The document is not a flat list of fields, but a tree. It starts with a single root element that contains everything, then the sections branch out from it, and smaller elements branch out from each section. This nesting is the core of the idea: the position of an element within the tree determines its meaning. The same number means something different depending on whether it sits in the header, inside a line item, or in the totals section.

To illustrate, here is the simplest possible structure for a tax invoice before filling in the details:

<Invoice>
  <!-- 1. Header: from, to, when, identification numbers -->
  <cbc:ID>INV-001</cbc:ID>
  <cbc:IssueDate>2026-06-23</cbc:IssueDate>

  <!-- 2. Line items: one line per product or service -->
  <cac:InvoiceLine> ... </cac:InvoiceLine>

  <!-- 3. Totals and tax + stamp extensions -->
  <cac:TaxTotal> ... </cac:TaxTotal>
  <cac:LegalMonetaryTotal> ... </cac:LegalMonetaryTotal>
</Invoice>

Notice two prefixes that recur: cbc: andcac:. The first stands for Common Basic Components and refers to simple, single-value fields (a number, a date, text). The second stands for Common Aggregate Components and refers to composite elements that contain other elements inside them. This distinction explains why some tags hold a direct value while others hold further tags.

These prefixes are not decoration, but namespace names defined in the document’s header. Every invoice document opens by declaring these namespaces on the root element, so systems know which standard each tag comes from. A missing namespace declaration or an error in its address makes the document unreadable from the outset, before any content-level validation.

<Invoice
  xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
  xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
  xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
  xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
  ...
</Invoice>

The namespace declaration ext: is what later allows adding the cryptographic stamp extensions. As for the default namespace (with no prefix), it indicates that the document is of type Invoice in the UBL standard. These four lines are the document’s “wrapper” that embraces all three sections.

Anatomy of the e-invoice document structure

Branches of the invoice document in XML
The main elements into which the invoice root, Invoice, branches.
Document tree

The root Invoice

Header: general data

Invoice parties (seller and buyer)

Repeated line items (InvoiceLine)

Totals and tax (LegalMonetaryTotal / TaxTotal)

Extensions and stamp (UBLExtensions)

Each branch contains sub-elements in a specific order defined by the standard.

The three main sections of the invoice document

Whatever the invoice type (a tax invoice for businesses, B2B, or a simplified invoice for consumers, B2C), the document splits logically into three major parts. Understanding these three parts is the key to reading any e-invoice.

1. Header: the invoice’s identity and its parties

The header is the topmost part of the document. It carries the data that identifies the invoice as a whole: its number, its type, its date, and its unique identifier, in addition to the seller and buyer data. This data applies to the entire invoice, not to a particular line item.

The main header elements in their natural order:

<cbc:ProfileID>reporting:1.0</cbc:ProfileID>
<cbc:ID>INV-2026-001</cbc:ID>
<cbc:UUID>3cf5ee18-ee25-4a3b-9b1c-1f2e3a4b5c6d</cbc:UUID>
<cbc:IssueDate>2026-06-23</cbc:IssueDate>
<cbc:IssueTime>14:30:00</cbc:IssueTime>
<cbc:InvoiceTypeCode name="0100000">388</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode>

<cac:AccountingSupplierParty> ... </cac:AccountingSupplierParty>
<cac:AccountingCustomerParty> ... </cac:AccountingCustomerParty>

Here we see a live example of nesting. AccountingSupplierParty is a composite element that contains within it the seller’s name, tax number, and address. The header, then, is not flat fields but contains composite elements that branch out in turn. Each of these fields has its own mandatory rules and specific format that we do not expand on here.

To understand the nesting better, look at how the seller element is built internally. It does not carry the seller’s name alone, but contains a Party element Party that in turn branches into the legal name, the tax number, the address, and the identification scheme:

<cac:AccountingSupplierParty>
  <cac:Party>
    <cac:PartyIdentification>
      <cbc:ID schemeID="CRN">1010101010</cbc:ID>
    </cac:PartyIdentification>
    <cac:PostalAddress> ... </cac:PostalAddress>
    <cac:PartyTaxScheme>
      <cbc:CompanyID>300000000000003</cbc:CompanyID>
    </cac:PartyTaxScheme>
    <cac:PartyLegalEntity>
      <cbc:RegistrationName>Example Trading Establishment</cbc:RegistrationName>
    </cac:PartyLegalEntity>
  </cac:Party>
</cac:AccountingSupplierParty>

This multi-layered nesting is what makes the header deeper than it appears. A single seemingly single element (the seller) folds into four layers of nested elements. The buyer element AccountingCustomerParty follows the same structure. The essential difference between them is that the tax invoice (B2B) requires a tax number for the buyer, whereas the simplified invoice (B2C) does not require it because the buyer is an end consumer.

To go deeper into each header field (the unique identifier UUID, the invoice type code, the two parties’ data, and the invoice counter ICV), see the dedicated guide “Invoice Header,” as it covers each element individually with its examples and rules.

2. Line Items: the details of products and services

The second section is the body of the invoice: the list of line items. Each line in the invoice (a product or a service) is represented by an independent InvoiceLine element. If the establishment sells three items in a single invoice, the element repeats three times within the same document.

<cac:InvoiceLine>
  <cbc:ID>1</cbc:ID>
  <cbc:InvoicedQuantity unitCode="PCE">2</cbc:InvoicedQuantity>
  <cbc:LineExtensionAmount currencyID="SAR">200.00</cbc:LineExtensionAmount>
  <cac:Item>
    <cbc:Name>Consulting service</cbc:Name>
  </cac:Item>
  <cac:Price>
    <cbc:PriceAmount currencyID="SAR">100.00</cbc:PriceAmount>
  </cac:Price>
</cac:InvoiceLine>

Each line item carries its serial number, quantity, unit of measure, price, line total, and item name, in addition to its own tax details. Notice the nesting again: Item andPrice are two composite elements inside the line item, not two flat fields. This allows each line item to carry a different tax rate from the others (a taxable item at 15% and an exempt item, for example) within a single invoice.

The order of line items matters: they are numbered ascending from 1, and the line sums must match the totals in the third section, otherwise the arithmetic validation fails. As for the detailed rules of line-item composition (line-level discounts, tax codes, and units of measure), that is the subject of the dedicated guide “Invoice Lines.”

Illustrating the repetition of the line-item element within the document

From line items to totals
How the invoice line items relate to the totals values.
1

Repeated line items InvoiceLine

2

Summing line values and tax

3

Matching LegalMonetaryTotal

The sum of the line items must match the totals values, otherwise the invoice is rejected.

3. Totals, Tax & Extensions: the legal stamp

The third section brings the invoice figures together in their final form and carries the security data that proves their integrity. It splits practically into two adjacent groups: the tax totals and the legal monetary totals.

<cac:TaxTotal>
  <cbc:TaxAmount currencyID="SAR">30.00</cbc:TaxAmount>
  <cac:TaxSubtotal>
    <cbc:TaxableAmount currencyID="SAR">200.00</cbc:TaxableAmount>
    <cbc:TaxAmount currencyID="SAR">30.00</cbc:TaxAmount>
    <cac:TaxCategory>
      <cbc:Percent>15.00</cbc:Percent>
    </cac:TaxCategory>
  </cac:TaxSubtotal>
</cac:TaxTotal>

<cac:LegalMonetaryTotal>
  <cbc:LineExtensionAmount currencyID="SAR">200.00</cbc:LineExtensionAmount>
  <cbc:TaxExclusiveAmount currencyID="SAR">200.00</cbc:TaxExclusiveAmount>
  <cbc:TaxInclusiveAmount currencyID="SAR">230.00</cbc:TaxInclusiveAmount>
  <cbc:PayableAmount currencyID="SAR">230.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>

Here appears value-added tax with its rate (15%), the taxable amount, the total before and after tax, and the amount due for payment. These figures must reconcile arithmetically with the line-item sums in the second section. Any difference due to rounding is handled according to specific rules in the standard.

Alongside the totals, this part carries the mandatory security elements in Phase Two, usually placed in the signature extension at the top of the document within UBLExtensions:

<ext:UBLExtensions>
  <ext:UBLExtension>
    <ext:ExtensionContent>
      <!-- Cryptographic Stamp with CSID key -->
      <!-- Document hash (Hash) -->
      <!-- Public key and digital signature -->
    </ext:ExtensionContent>
  </ext:UBLExtension>
</ext:UBLExtensions>

The cryptographic stamp is a digital signature using the ECDSA algorithm, generated with the cryptographic stamp identifier (CSID) issued by the Authority for each device or branch. To it are added the document hash (Hash using the SHA-256 algorithm), the previous invoice’s hash to form an interlinked chain, and a QR code. These elements together make the invoice authenticated and tamper-resistant. Generating these extensions and managing the CSID certificate happen automatically in Qoyod.

How the sections interlock in the document tree

Now that we know the three sections, let us look at the full picture. Everything lives inside a single root element named Invoice. Directly beneath it come the stamp extensions first, then the simple header fields, then the composite header elements (the seller and the buyer), then the tax totals, then the monetary totals, and finally the line items.

It may seem surprising that the line items come at the end of the document even though they are the visual “body” of the invoice. This is one of the most important differences between the visible form of the invoice and its actual structure in XML: the visual order for the reader differs from the order of elements in the tree. What matters to systems is the element’s position within the hierarchy, not its place on the page.

Here is the full structure simplified, in its actual element order:

<Invoice>
  <ext:UBLExtensions> ... </ext:UBLExtensions>   <!-- stamp and signature -->

  <cbc:ProfileID> ... </cbc:ProfileID>            <!-- start of header -->
  <cbc:ID> ... </cbc:ID>
  <cbc:UUID> ... </cbc:UUID>
  <cbc:IssueDate> ... </cbc:IssueDate>
  <cbc:InvoiceTypeCode> ... </cbc:InvoiceTypeCode>
  <cbc:DocumentCurrencyCode> ... </cbc:DocumentCurrencyCode>
  <cac:AccountingSupplierParty> ... </cac:AccountingSupplierParty>
  <cac:AccountingCustomerParty> ... </cac:AccountingCustomerParty>

  <cac:TaxTotal> ... </cac:TaxTotal>              <!-- start of totals -->
  <cac:LegalMonetaryTotal> ... </cac:LegalMonetaryTotal>

  <cac:InvoiceLine> ... </cac:InvoiceLine>        <!-- line items at the end -->
  <cac:InvoiceLine> ... </cac:InvoiceLine>
</Invoice>

This order is not optional. The UBL 2.1 standard imposes a specific sequence for elements inside the parent element. Placing InvoiceLine before TaxTotal for example violates the schema and leads to the document being rejected at validation. This is why Qoyod always builds the tree according to the correct sequence without any intervention from you.

Illustrating the order of elements inside the invoice tree

The mandatory order of invoice elements
The order of the main elements as imposed by the standard.
Element order
1

UBLExtensions (extensions and stamp)

2

Invoice header (identifiers and dates)

3

Seller and buyer

4

TaxTotal (total tax)

5

LegalMonetaryTotal (totals)

6

InvoiceLine (repeated line items)

Breaking the element order fails schema validation.

The difference between structure and schema

Many people confuse the invoice structure with the invoice schema. The difference is fundamental. The structure is the actual order of elements in a particular invoice document. As for the schema it is the rules that govern that structure: which elements are mandatory, which are optional, what type of value is allowed in each field, and what their correct order is.

In other words: the schema is the template, and the structure is the document that follows the template. When you send your invoice to the Fatoora platform, the platform verifies that your document’s structure matches the approved schema. Any violation (a missing mandatory element, a wrong order, or a value in an incorrect format) is detected at this stage. The details of the schema files and the XSD validation rules are the subject of the dedicated guide “Invoice Schema.”

The structure’s journey from creation to approval

The invoice structure goes through a series of steps from the moment of its creation until its approval by the Authority. Understanding this journey completes the picture, because the structure is not static, but is built, stamped, and sent in a specific order.

  1. Building the tree: The document is generated with its three sections, ordered according to the mandatory UBL sequence, with the namespace declarations on the root element.
  2. Computing the hash (Hash): The SHA-256 hash of the document is computed after its canonicalization, and is linked to the previous invoice’s hash to form the chain.
  3. The cryptographic stamp: The document is signed with the cryptographic stamp identifier (CSID), so the signature and public key are added inside UBLExtensions.
  4. Generating the QR code: The QR code is built in TLV format and embedded in the structure, carrying the seller data, the tax number, the total, the hash, and the signature.
  5. Validation and submission: The document is sent to the Fatoora platform. The tax invoice undergoes clearance and returns stamped by the Authority, while the simplified invoice is reported within 24 hours.

Any error in the order of the sections is detected at validation before the journey is complete. This is why the document is built in the correct sequence from the start, rather than being reordered later. The invoice counter (ICV) and the previous invoice’s hash ensure that each invoice comes in its correct position within the establishment’s invoice chain, so no invoice can be deleted or another inserted without breaking the chain.

This interlinking between the hash, the counter, and the signature is what turns the document from an editable text file into an authenticated record. Were someone to change a single number in any section after stamping, the computed hash would differ from the stored hash, and the tampering would be exposed instantly.

A complete example: reading an invoice from top to bottom

Let us bring the above together in one sequential reading of a complete invoice document. Start from the root element Invoice with its namespace declarations. The first thing you meet is the UBLExtensions extension that carries the stamp and the signature. This is the security part that proves the document’s authenticity.

After it, the simple header fields begin: the profile identifier ProfileID that determines whether the invoice is for clearance or reporting, then the invoice number, its unique identifier UUID, its date, its type code, and its currency. Following that come the composite header elements: the seller with its four layers, then the buyer with its similar structure.

We then move on to the totals: TaxTotal carries the total tax and its breakdown by rate and taxable amount, then LegalMonetaryTotal with its four amounts (the line total, the amount before tax, the amount including it, and the amount due). Finally come the line items InvoiceLine one after another, each line item with its quantity, price, item, and tax.

If you read any invoice in this order, you know the position of every piece of data instantly. The date is in the header, the item price is in the line item, the total tax is in the totals section, and the signature is in the extension. This discipline of positions is what makes millions of invoices machine-processable without ambiguity.

Start today

Phase Two–compliant invoices without writing a single line of XML

Qoyod builds the complete e-invoice structure automatically: the header, the line items, the totals, and the cryptographic stamp, in the order the Authority requires. You write the invoice, and Qoyod handles the rest.

Start your free trial and issue compliant invoices

Invoice types and their impact on the structure

Invoice types share the same overall structure, but they differ in some fields and in how they are processed by the Authority. The two most prominent types:

  • The tax invoice (B2B): used between establishments. It undergoes “Clearance,” meaning it is sent to the Authority first, which returns it stamped, and it is not delivered to the buyer until after that.
  • The simplified tax invoice (B2C): used with the consumer. It is delivered to the buyer immediately, then reported to the Authority within 24 hours (“Reporting”).

Alongside them, the credit note and the debit note follow the same structure with additional fields that link them to the original invoice. The difference in structure between these types is usually limited to the invoice type code InvoiceTypeCode and some fields related to the counterparty, while the three major sections remain constant across all of them.

The position of the QR code in the structure

The QR code is an integral part of the invoice structure, not just a visual addition on the page. In Phase Two, the code is embedded inside the document in TLV format (Tag-Length-Value), meaning a series of tags each with a number, a length, and a value, encoded in Base64.

The QR code for the tax invoice carries nine tags: the seller’s name, its tax number, the timestamp, the invoice total including tax, the total tax, the document hash, the cryptographic stamp, the public key, and the signature. These nine tags are drawn from the three sections: the seller’s name and number from the header, the totals from the totals section, and the hash and stamp from the security extension.

That is, the QR code is not an independent fourth section, but an encoded summary of the data distributed across the three sections. This explains why it is generated at the end of the journey after the structure and stamp are complete: it cannot be built before the hash is computed and the document is signed, because it carries them.

Common structural errors and how to read them

Most validation messages arise from a flaw in the structure rather than in the numbers themselves. Knowing which section the error belongs to shortens the resolution time. The most prominent patterns:

  • A missing mandatory element in the header: The absence of the seller’s tax number or the invoice type code halts validation immediately, because these fields identify the invoice as a whole.
  • Wrong order of sections: Placing InvoiceLine before TaxTotal violates the UBL sequence and is rejected, even if the values are correct.
  • Arithmetic inconsistency: If the sum of the line items does not equal the LineExtensionAmount value in the totals, the conflict between the second and third sections is detected.
  • Incorrect identifier format: A commercial registration number or tax number with the wrong number of digits is caught at the field level in the header before submission.

The practical rule: read the validation message, identify the mentioned element, then ask which section it belongs to. This positioning leads you directly to the data source that needs correcting, whether it is the establishment setup, the customer data, or a particular line item.

Why does understanding this structure matter to you?

Even if you never write XML by hand, understanding the structure benefits you practically in several situations:

  • Interpreting validation messages: When the Authority issues a warning, it often points to a particular element in the tree. Knowing which section the element belongs to speeds up diagnosing the cause.
  • Reviewing data completeness: You realize which data belongs to the header (once per invoice) and which repeats with each line item, so you check the correct source when something is missing.
  • System integration: If you connect an external system through an API, you need to understand the positions of elements to read the generated invoice or build your reports on it.
  • Verifying the integrity of totals: You know that the line-item sums must equal the totals, so you catch data-entry errors before submission.

In the end, the structure is not an isolated technical detail, but the language in which your systems communicate with the Fatoora platform. The deeper you understand it, the fewer errors in your invoices and the faster your resolution of any warning.

How Qoyod handles the invoice structure on your behalf

Qoyod is a solution compliant with Phase Two of e-invoicing. When any invoice is issued, Qoyod builds a complete XML document according to the UBL 2.1 standard: it arranges the header, the line items, and the totals in the sequence the schema requires, generates the cryptographic stamp, the QR code, and the chain hash, and manages the CSID certificate for each branch.

Qoyod also validates the format of the identification numbers (the commercial registration, the tax number, and the counterparty’s identifiers) before submission, catching one of the most common causes of warnings early. It then handles the clearance path for business-to-business invoices, and the reporting path within 24 hours for simplified invoices. All of this without you writing a single line of XML.

Try Qoyod free for 14 days, no credit card required.

A structural summary of the three sections

To fix the picture, here is what each section carries and its position in the tree. The header is at the top of the document after the security extension, and it carries what applies to the entire invoice: the identification numbers, the dates, the currency, and the seller and buyer data with their nested layers. Its data appears once per invoice.

The totals section follows the header, and carries the tax figures and the final amounts that must reconcile arithmetically with the line items. As for the line items, they come at the end of the document, their element repeating for each item, and each line item carries its own quantity, price, and tax. And the security extension at the top ties everything together with a stamp, a hash, and a signature that turn the document into an authenticated record.

These three sections, with their wrapping of namespaces and their security extensions, make up every e-invoice in Saudi Arabia. A difference in invoice type changes some fields, not the structure. And once you master reading this structure, diagnosing any warning and understanding any generated invoice becomes straightforward.

Frequently asked questions

What are the main sections in the e-invoice structure?
Three sections: the header (the invoice’s identity and its parties), the line items (a line per product or service), and the totals and tax with the cryptographic stamp extensions. They all live inside a single root element named Invoice.

What is the structure standard adopted in Saudi Arabia?
The UBL 2.1 standard (Universal Business Language), the global standard adopted by the Zakat, Tax and Customs Authority for Phase Two of e-invoicing. The document format is XML.

Why do the line items come at the end of the document even though they are the body of the invoice?
Because the reader’s visual order differs from the order of elements in the XML tree. The UBL standard imposes a specific sequence in which the header and totals come before the line-item lines. What matters to systems is the element’s position in the tree, not its place on the page.

Do I need to write XML myself to issue a compliant invoice?
No. Qoyod builds the complete XML structure automatically, so you enter the invoice data through a simple interface and Qoyod generates the compliant document in the correct order and with the cryptographic stamp.

What is the difference between the invoice structure and its schema?
The structure is the actual order of elements in a particular invoice. The schema is the rules that govern that structure: the mandatory and optional elements, their formats, and their order. The schema is a template, and the structure is a document that follows the template.

Does the structure change with the invoice type?
The three major sections are constant across all types. Some fields and the invoice type code InvoiceTypeCode differ between the tax invoice (B2B), the simplified invoice (B2C), and the notes, but the overall structure is the same.

Guides

Continue your learning journey

Explore the rest of Qoyod’s guides, or start applying what you’ve learned.

Live webinars hosted by the Qoyod team to help you use the software easily and answer your questions.

Discover Qoyod’s latest updates, ongoing improvements, and new features in one place.

Our team is ready to help you and provide instant support for any issue you face, around the clock.