An invoice line (Invoice Line) is the basic unit that carries the details of each item within the electronic invoice in Saudi Arabia. Every good or service you sell becomes a separate cac:InvoiceLine element in the XML file, carrying its quantity, unit price, line amount, and its own VAT. This page documents this element alone in technical detail, and explains how lines repeat and how their values aggregate to form the invoice total under the UBL 2.1 standard adopted by the Zakat, Tax and Customs Authority (ZATCA).
If you are looking for the complete structure of the invoice file, from the outer envelope down to the totals elements, refer to the Electronic Invoice Structure (Invoice Structure)page. As for the details of the invoice header, covering seller and buyer data and dates, that is the subject of the separate “Invoice Header” page. Here we focus exclusively on what happens inside each of the invoice lines.
cac:InvoiceLine element repeats once per item. It carries the identifier, the quantity, and the line amount before tax, and it contains within it the item data (cac:Item) and its price (cac:Price) and its line-level tax. The sum of cbc:LineExtensionAmount across all lines must equal the invoice total before tax in the cac:LegalMonetaryTotal.
What is the invoice line (cac:InvoiceLine) and why it matters
In the UBL 2.1 standard, an invoice consists of a general header followed by a list of lines. Each line represents a single sellable item: a product, a service, a delivery charge, or any item you want to price separately. The cac:InvoiceLine element is the container that gathers everything related to this single item in one place.
The importance of getting this element technically right stems from the fact that the Authority verifies that its calculations match. If a single line amount deviates from the product of quantity by unit price, the system rejects the entire invoice at clearance or reporting. Therefore the accuracy of every field inside the line is a condition for acceptance, not a cosmetic detail.
The invoice lines appear after the header data and before the final totals elements. The order of elements within the XML file matters in UBL, as the parser in the Fatoora platform expects each element in its designated position within the schema.
Position of the lines within the file
The invoice contains cac:InvoiceLine at least one element. There is no invoice without lines. The order of appearance is after the header-level total tax elements and before or after cac:LegalMonetaryTotal depending on the schema version, but the decisive reference is always the XSD file approved by the Authority, which defines the mandatory sequence.
Invoice Header
Repeating InvoiceLine lines
LegalMonetaryTotal = sum of the lines
The core fields inside the line element
Each cac:InvoiceLine element contains a set of fields directly at the line level, in addition to composite sub-elements. We start with the direct fields that carry the identifier, the quantity, and the amount.
This simplified example illustrates five essential fields. The unit price is 100 riyals, the quantity is 5 units, so the line amount is 500 riyals. Let us detail each field on its own.
The identifier (cbc:ID)
A unique sequential number for the line within a single invoice. It usually starts from 1 and increments with each new line. The identifier may not be repeated within the same invoice. This number links the line to any reference to it in other elements, such as line-level discounts.
The quantity (cbc:InvoicedQuantity)
The number of units sold of the item. The unitCode attribute is mandatory and specifies the unit of measure according to the approved code list (UN/ECE Recommendation 20). For example PCE for a piece, KGM for a kilogram, HUR for an hour, LTR for a liter. Choosing the correct code prevents the invoice from being rejected.
The list of unit codes is broad and covers most of what businesses sell. Here are the ones most used in the Saudi market:
PCEorEA: a piece or a single unit, for counted items.KGM: kilogram, for weighed items.LTR: liter, for liquids.MTR: meter, for fabrics, cables, and anything measured by length.HUR: hour, for services billed by time such as consultations.DAY: day, for daily rentals and subscriptions.MON: month, for monthly subscriptions.
Services raise a frequent question about the unit of measure. A service that is not sold by a numerical unit, such as an annual contract at a lump-sum price, usually uses the code PCE with a quantity of 1, or the appropriate time code if the service is billed by time. What matters is that the code is from the approved list, and that it is consistent with the nature of the item and the declared unit price.
The line amount (cbc:LineExtensionAmount)
This field is the pivot of the arithmetic verification. It represents the value of the line before VAT, after deducting any line-level reductions. The basic rule:
LineExtensionAmount = (InvoicedQuantity × PriceAmount) − AllowanceTotal
The currencyID attribute must match the invoice currency declared in the header. In the Saudi market the value is SAR in most cases. Any difference between the line currency and the invoice currency causes a validation error.
| Standard | Example | Mandatory? |
|---|---|---|
| cbc:ID (line number) | 1 | Mandatory |
| InvoicedQuantity (quantity) | 3 PCE | Mandatory |
| LineExtensionAmount (line value) | 300.00 | Mandatory |
The item element (cac:Item) inside the line
the cac:Item It describes the sold item itself: its name, its tax classification, and any additional identifiers. It is a composite element that sits inside cac:InvoiceLine and carries the “descriptive” part of the line, while the other fields carry the “quantitative” part.
The item name (cbc:Name)
A clear text description of the item that appears to the buyer. It must be understandable and match what you actually sell. Arabic is acceptable here, and this is one of the few places where free Arabic text appears inside a technical XML file.
The tax classification of the item (cac:ClassifiedTaxCategory)
It specifies the tax category applied to this item. The cbc:ID field carries the category code: S for the standard taxable rate, Z for the zero rate, E for exempt, O for out of scope of tax. The cbc:Percent field carries the rate, which is 15.00 for the standard rate in Saudi Arabia. As for cac:TaxScheme it always carries the identifier VAT for value-added tax.
Linking the item category here to the line-level tax category is a condition for consistency. If you declare that the item is subject to the standard rate in cac:Item then compute its tax at a zero rate in cac:TaxTotalthe Authority rejects the invoice for the mismatch.
The price element (cac:Price) and the unit price
the cac:Price It carries the price of a single unit of the item before tax. This price is the one multiplied by the quantity to arrive at the line amount. The distinction between the unit price and the line amount is fundamental: the first is for a single unit, and the second is for the full quantity.
The unit price (cbc:PriceAmount)
The value of a single unit in the declared currency. It must be consistent with the line amount through the quantity equation. The currencyID attribute matches the invoice currency.
The base quantity (cbc:BaseQuantity)
It specifies the number of units to which the unit price applies, and its value is 1 in normal cases. It is used when the price is declared for a group, such as the price of a pack containing twelve pieces.
The line-level tax (cac:TaxTotal)
In addition to the total tax in the invoice header, each line can carry its own cac:TaxTotal element that shows the tax amount computed on this line specifically. This is useful when the invoice contains items with different tax categories.
The tax amount (cbc:TaxAmount)
The value of the value-added tax computed on this line. It is calculated by multiplying the line amount by the tax rate. In the example: 500 riyals multiplied by 15% equals 75 riyals. Any deviation from this value, even by a single halala due to rounding, may cause a validation error if it does not comply with the approved rounding rules.
The amount after rounding (cbc:RoundingAmount)
The line total including tax after applying rounding. In the example: 500 riyals plus 75 riyals equals 575 riyals. This field helps the Fatoora platform verify the consistency of the rounded amounts across the entire invoice.
Line-level rounding rules
Rounding is one of the most common causes of invoice rejection. The Authority applies rounding to two decimal places (two halalas) on line amounts. The practical rule is to compute the tax on the line amount, then round the result to two decimal places before summing the line taxes.
An example that illustrates the importance of order: a line with an amount of 33.33 riyals and a tax of 15%. The exact tax is 4.9995 riyals, rounded to 5.00 riyals. If you summed the taxes of ten identical lines before rounding, the result would differ from summing them after rounding. Therefore compliant invoicing systems fix a single rounding policy across the entire invoice, so that the sum of the line taxes does not deviate from the declared total tax.
A deviation of even a single halala between the sum of the line taxes and the total tax in cac:TaxTotal is enough to reject the invoice. This is a fundamental reason that makes building lines manually risky, since the accountant needs to apply a consistent rounding rule on every line without exception.
Leave the XML details to Qoyod
Qoyod builds the XML file for each invoice line automatically according to the UBL 2.1 standard, computing the line amount, the tax, and the rounding with no manual intervention, and sends the invoice to the Fatoora platform directly.
Line-level allowances and charges (cac:AllowanceCharge)
the cac:AllowanceCharge It allows adding a discount or a charge to one specific line, instead of applying it to the entire invoice. The cbc:ChargeIndicator field specifies the type: a value of false means a discount (Allowance), and a value of true means an additional charge (Charge).
When there is a discount on the line, its amount is deducted before computing cbc:LineExtensionAmount. A practical example: the unit price is 100 riyals and the quantity is 5, so the gross total is 500 riyals. With a volume discount of 50 riyals, the line amount becomes 450 riyals, and the tax is computed on it. This order is mandatory: the discount first, then the tax on the net.
The reason for the discount or charge (cbc:AllowanceChargeReason)
A text description that clarifies the reason for the discount or the charge, such as “Volume discount” or “Delivery charge”. The Authority requires this field to explain any adjustment to the value, to preserve the transparency and auditability of the invoice.
Unit price × quantity
Subtract the discount (AllowanceCharge)
LineExtensionAmount
× tax rate = line tax
How the lines repeat and aggregate into the totals
A single invoice may contain one line or dozens of lines, and each line is an independent cac:InvoiceLine element with its own unique identifier. The real power of the standard shows in how these lines aggregate to form the invoice totals.
The golden rule: the sum of cbc:LineExtensionAmount across all lines must equal the value of cbc:LineExtensionAmount in the totals element cac:LegalMonetaryTotal. This match is the first thing the Fatoora platform verifies.
In this example there are two lines: the first is 500 riyals and the second is 300 riyals. Their sum of 800 riyals appears in cbc:LineExtensionAmount within the totals. A tax of 15% on 800 riyals equals 120 riyals, so the total including tax becomes 920 riyals in cbc:TaxInclusiveAmount.
The interrelation between the lines and the totals also includes the tax. The sum of cbc:TaxAmount across all lines must match the value of the total tax in cac:TaxTotal at the invoice level. And the breakdown of tax by category appears in the cac:TaxSubtotalelements, where lines of the same category are aggregated together.
Tax breakdown by category
When the invoice contains items with different tax categories, the standard groups similar lines by their categories inside a separate cac:TaxSubtotal for each category. So items subject to the standard rate are grouped in the Scategory, the zero-rated items in the Zcategory, and so on. This grouping allows the Authority to verify the correctness of each category on its own.
A complete example: an invoice with three different lines
Let us bring together everything above in a real-world example. A business sells three items in a single invoice: two computers, five consultation hours, and a zero-rated product. We see how each line is built independently, then how the values aggregate.
The first line: two devices at a unit price of 2,000 riyals. The line amount is 4,000 riyals, the tax category is standard, so the tax is 600 riyals. The second line: five consultation hours at 200 riyals per hour. The line amount is 1,000 riyals, the standard tax on it is 150 riyals. The third line: a zero-rated product at 500 riyals and a quantity of one. The line amount is 500 riyals, and the tax is zero because its category is Z.
The sum of the line amounts: 4,000 plus 1,000 plus 500 equals 5,500 riyals. This is the cbc:LineExtensionAmount in the totals. The sum of the tax: 600 plus 150 plus zero equals 750 riyals. So the total including tax becomes 6,250 riyals. Notice how each line carries its own independent tax category, and how the values aggregate precisely in the totals elements. Any flaw in a single line breaks this balance and rejects the entire invoice.
Common errors in building invoice lines
The most common causes of invoice rejection at clearance or reporting come from line-level errors. Here are the most prominent:
- Amount mismatch: the value of
cbc:LineExtensionAmountdoes not equal the product of the quantity by the unit price after the discount. - Currency difference: the
currencyIDattribute in the line differs from the invoice currency declared in the header. - Tax category contradiction: the item category in
cac:Itemdiffers from the category used in computing the line tax. - Wrong unit-of-measure code: the value of
unitCodeis not from the approved code list. - Rounding error: the tax amount does not comply with the approved rounding rules, so it deviates from the expected value by halalas.
- Totals mismatch: the sum of the line amounts does not equal the total in
cac:LegalMonetaryTotal.
The common thread among these errors is that they are arithmetic or structural, detected immediately by the Authority’s parser. Pre-validating the XML file before sending saves a great deal of time. Refer to the Invoice Schema (Invoice Schema) and its validation page to understand how automatic validation works.
The difference between a line-level discount and an invoice-level discount
Many people confuse a line-level discount with a discount on the entire invoice. The distinction matters because it changes the position of the element in the file and the way it is computed.
The line-level discount is placed inside cac:InvoiceLine and affects the amount of that line alone, so its tax is computed on the value after the discount. As for the discount on the entire invoice, it is placed at the header level in a separate cac:AllowanceCharge element, and its effect is distributed over the totals by tax category.
The practical rule: if the discount is tied to a specific item (a volume discount on a particular product), place it on the line. And if it is a general discount on the invoice (a loyal-customer discount on the full value), place it at the header level. Mixing the two positions causes a mismatch in the totals and rejects the invoice.
Charges follow the same logic. A delivery charge specific to an item is placed on its line with a value of cbc:ChargeIndicator equal to true. And a general shipping charge on the entire invoice is placed at the header level. In all cases the element needs a text reason in cbc:AllowanceChargeReason.
Best practices for building sound lines
Adhering to a number of practical rules raises the acceptance rate of your invoices from the first attempt:
- Start identifiers from 1 and increment regularly: do not leave gaps and do not repeat a number, as the unique identifier is a condition for every line.
- Unify the currency across the invoice: make sure that every
currencyIDin the lines matches the header currency. - Apply rounding with a single policy: round each line tax amount to two decimal places, and do not mix summing before and after rounding.
- Tie the tax category to the item, not to a manual calculation: let the
cac:Itemcategory be the source, and compute the tax directly from it. - Verify that the totals match before sending: make sure that the sum of the line amounts equals
cbc:LineExtensionAmountin the totals, and the sum of their taxes equals the total tax. - Use only approved unit codes: refer to the UN/ECE Recommendation 20 list and do not invent codes.
These rules seem simple, but applying them manually to an invoice with ten lines or more is exhausting and error-prone. That is why businesses rely on accounting software that applies them automatically and validates them before sending.
The relationship of invoice lines to the UBL 2.1 standard and XML formatting
All the elements we explained belong to the two namespaces in the UBL standard: the cac: prefix for the Aggregate Components such as cac:InvoiceLine andcac:Item, and the cbc: prefix for the Basic Components such as cbc:ID andcbc:LineExtensionAmount. This distinction is part of the standard’s structure and is not optional.
To understand the standard fully, see the UBL 2.1 standard in electronic invoicingpage. And to understand the general technical formatting of the XML file and how the elements integrate, refer to the XML invoice: the technical formatting of the electronic invoice.
page. The XSD schema approved by the Authority precisely defines which field is mandatory and which is optional, and what the constraints are on each value. Adhering to the schema is a condition for the invoice to be accepted in the second phase of electronic invoicing, where each file is digitally signed and then sent to the Fatoora platform for clearance (for B2B invoices) or reporting (for simplified B2C invoices).
How Qoyod helps you build invoice lines
Building the XML file manually for each invoice is a complex, error-prone technical task, especially with the tax and rounding calculations at the level of every line. This is where accounting software compliant with the Authority’s requirements comes in.
Qoyod generates the cac:InvoiceLine element for each item in your invoice automatically. You enter the item, the quantity, and the price from a simple interface, and the system takes care of building the technical fields: it computes the line amount, applies discounts before tax, computes the tax of each line with the correct rounding, and ensures that the sum of the lines matches the invoice totals.
After building the file, Qoyod signs it digitally and sends it to the Fatoora platform in accordance with the second-phase requirements, while managing the Cryptographic Stamp Identifier (CSID) registered with the Authority. The result is an invoice accepted from the first attempt, without you writing a single line of XML yourself. Qoyod is compliant with the second phase of electronic invoicing and officially approved by the Zakat, Tax and Customs Authority.
Try Qoyod free for 14 days. No credit card required.
Frequently asked questions about invoice lines in XML
How many lines are allowed in a single invoice?
There is no explicit maximum for the number of cac:InvoiceLine elements in the invoice, but there must be at least one line. The practical limit comes from the file size and the ability of the Fatoora platform to process it. Ordinary invoices contain from one line to dozens of lines.
Must all lines carry the same currency?
Yes. All the values of currencyID inside the lines must match the invoice currency declared in the header. You cannot mix two currencies inside a single invoice. In the Saudi market the currency is the Saudi riyal (SAR) in most cases.
What is the difference between the unit price and the line amount?
The unit price (cbc:PriceAmount) is the value of a single unit of the item. The line amount (cbc:LineExtensionAmount) is the value of the full quantity after the discount and before tax. The relationship: the line amount equals the unit price multiplied by the quantity minus the line-level discounts.
How do I apply a discount to a single line only?
You use the cac:AllowanceCharge element inside that line with a cbc:ChargeIndicator of a value of false. The discount amount is deducted before computing the line amount, so the tax is computed on the net value. As for the discount on the entire invoice, it is placed at the header level, not the line.
What if my items have different tax categories?
Each line carries its own tax category in cac:Item via cac:ClassifiedTaxCategory. Lines subject to the standard rate take the S category at 15%, the zero-rated ones the Zcategory, and the exempt ones the Ecategory. Then similar lines are aggregated in separate cac:TaxSubtotal elements at the invoice level.
Do I need to write these lines manually?
No. Compliant accounting software such as Qoyod builds the cac:InvoiceLine elements automatically from the invoice data you enter normally. You do not need to know the XML structure to issue a compliant invoice, as the system handles the calculations, the formatting, the signing, and the sending to the Fatoora platform.