Oman · · 11 min read

Inside the Oman Tax Data Document (TDD): Engineering Walkthrough

The Oman Tax Data Document is the XML report the Tax Authority receives as corner five: what it carries, the 66 rules it must pass, and how it is generated.

Last updated .

What is the Oman Tax Data Document?

The Tax Data Document (TDD) is the XML document that reports a single transaction to the Oman Tax Authority (OTA) under the Fawtara e-invoicing programme. It carries CustomizationID urn:peppol:taxdata:om-1 and ProfileID urn:peppol:taxreporting, it is generated from the underlying PINT OM invoice, and it travels over the Peppol network to the Authority — the fifth corner in Oman's 5-corner model.

It is not a replacement for the invoice, and it is not a stripped-down copy of one either. A TDD holds a short tax-relevant summary and the complete original invoice embedded inside it. That single design decision explains most of the engineering: the summary is what the Authority reads first, and the embedded invoice is what makes the report self-evidencing.

If you are scoping Fawtara, the TDD is where most engineering hours land. This is the deep-dive companion to our Oman Fawtara readiness guide.

CustomizationID and ProfileID

CustomizationID = urn:peppol:taxdata:om-1
ProfileID       = urn:peppol:taxreporting

Rule ibr-tdd-01 fixes the first value and ibr-tdd-02 fixes the second. Both are fatal. Together they disambiguate the TDD from every PINT and BIS document, and they drive validator selection, routing and ingestion on the Authority's side.

The full identifier set for Oman — billing, self-billing and the TDD — is tabulated on the PINT OM CustomizationID reference.

What the TDD carries

The document root is pxs:TaxData in the namespace urn:peppol:schema:om-taxdata:1.0. Three groups sit under it.

The header

Element What it is Rule
cbc:CustomizationID Always urn:peppol:taxdata:om-1 ibr-tdd-01
cbc:ProfileID Always urn:peppol:taxreporting ibr-tdd-02
cbc:UUID The TDD's own identifier ibr-tdd-58
cbc:IssueDate Date only — a timezone here is a failure ibr-tdd-04
cbc:IssueTime Valid UBL issue time ibr-tdd-05
pxs:DocumentTypeCode S, R or D ibr-tdd-06
pxs:DocumentScope D, IP or INP ibr-tdd-07
pxs:ReporterRole 01 or 02 ibr-tdd-08

There is deliberately no cbc:ID at the root: ibr-tdd-03 fails a TDD that carries one. The identifier is cbc:UUID.

The three code lists are small and worth learning, because picking the wrong value is a silent business error rather than a syntax one:

  • pxs:DocumentTypeCodeS submit, R resubmit (revise a TDD already reported), D disregard (void one already reported). An older S/R/W/F list circulated before version 1.0.0 of the TDD process; W and F are no longer valid and the current Schematron rejects them.
  • pxs:DocumentScopeD domestic, IP international exchanged via Peppol, INP international exchanged outside Peppol. "International" covers both imports and exports; it is not import-only.
  • pxs:ReporterRole01 the seller is reporting, 02 the buyer is reporting.

The three parties

The root carries three party blocks, and each is an address and nothing else:

Block Content Constraint
pxs:ReportingParty cbc:EndpointID with a four-digit schemeID ibr-tdd-11 to ibr-tdd-13
pxs:ReceivingParty cbc:EndpointID with schemeID 0242 ibr-tdd-15 to ibr-tdd-17
pxs:ReportersRepresentative Exactly one cac:PartyIdentification/cbc:ID on scheme 0242 ibr-tdd-19 to ibr-tdd-21

Rules ibr-tdd-10, -14 and -18 enumerate what may not appear in these blocks, and the list is long: no PartyName, no PostalAddress, no PartyTaxScheme, no PartyLegalEntity, no Contact. Adding a helpful company name to the reporting party is a fatal error. Identifiers and registration names belong further down, on the reported document — and even there cac:PartyName is forbidden, so a trading name has nowhere to go. Use cac:PartyLegalEntity/cbc:RegistrationName.

Scheme 0242 is the Peppol Service Provider identifier scheme, which is why both the receiver and the representative use it: the Authority receives as a service provider, and the reporter is represented by one.

The reported transaction

Exactly one pxs:ReportedTransaction is allowed — ibr-tdd-09 counts them — and it holds two mandatory children plus an optional one:

  • pxs:ReportedDocument (ibr-tdd-22) — the tax-relevant summary.
  • pxs:SourceDocument (ibr-tdd-23) — the original invoice, whole.
  • pxs:CustomContent, optional, which must use the simple cbc:Value element (ibr-tdd-55).

The transaction block itself also records when the original document was received: cbc:IssueDate (ibr-tdd-59) and cbc:IssueTime (ibr-tdd-60).

The reported document, field by field

pxs:ReportedDocument is the summary the Authority reads. It restates a small set of invoice fields:

PINT OM invoice field TDD field Rule
cbc:CustomizationID cbc:CustomizationID ibr-tdd-24
cbc:ProfileID cbc:ProfileID ibr-tdd-25
cbc:ID (invoice number) cbc:ID ibr-tdd-26
Document UUID cbc:UUID, a version 5 UUID ibr-tdd-27
cbc:IssueDate cbc:IssueDate ibr-tdd-28
cbc:InvoiceTypeCode / cbc:CreditNoteTypeCode pxs:DocumentTypeCode (380, 381, 383, 389, 261) ibr-tdd-29
cbc:DocumentCurrencyCode cbc:DocumentCurrencyCode ibr-tdd-30
cac:AccountingSupplierParty cac:AccountingSupplierParty — tax scheme identifier, plus a legal-entity registration name where that block is used ibr-tdd-32, -42, -62
cac:AccountingCustomerParty cac:AccountingCustomerParty — VAT identifier, plus a legal-entity registration name where that block is used ibr-tdd-33, -50, -64
cac:TaxTotal/cbc:TaxAmount cac:TaxTotal/cbc:TaxAmount, one per currency ibr-tdd-34 to -36
cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount pxs:MonetaryTotal/cbc:TaxExclusiveAmount ibr-tdd-37, -52, -53

Four details in that table catch people out.

The document type code moves element. In UBL the code sits on cbc:InvoiceTypeCode or cbc:CreditNoteTypeCode depending on the document root. In the TDD it is always pxs:DocumentTypeCode. Note that the same element name means two different things in two places: at the root of the TDD it is S/R/D, and inside the reported document it is the UNTDID invoice type code.

The reported UUID is not the invoice's own UUID. ibr-tdd-27 requires a version 5 UUID, and a version 5 UUID is computed from a namespace plus a name rather than drawn at random. Oman's Solution Architecture v1.0.1 §10.2.3 defines the name as a fixed join of invoice fields, so the value is reproducible: the Authority recomputes it and compares. Copy the invoice's random cbc:UUID into this slot and the document fails.

There is one tax total per currency, not per rate. ibr-tdd-35 requires exactly one cac:TaxTotal in the document currency, and ibr-tdd-36 exactly one more if an accounting currency is used — which ibr-tdd-31 requires to be a different currency from the document currency. There is no per-category or per-rate breakdown in the reported document, and no pxs:TaxLine element exists. If you are building a category-by-category structure here, stop: the Authority gets the detail from the embedded invoice.

The monetary total is pxs:MonetaryTotal, not LegalMonetaryTotal. Exactly one, carrying cbc:TaxExclusiveAmount in the document currency (ibr-tdd-52, ibr-tdd-53).

One conditional worth encoding properly: ibr-tdd-42 makes the seller's tax identifier mandatory except for an invoice for import of goods, an import-of-service reverse charge, or a profit-margin self invoice. The rule reads the transaction-type bit string on the source invoice to decide, so the exemption is derived, never asserted by the sender.

The source document — the whole invoice travels with it

pxs:SourceDocument/cec:ExtensionContent must contain a complete UBL 2.1 Invoice or CreditNote. ibr-tdd-57 states it directly, and ibr-tdd-23 makes the block itself mandatory.

This is the single most commonly misunderstood part of the TDD. A TDD is not a redacted tax extract that leaves the commercial detail behind. Line descriptions, quantities, allowances, payment terms — all of it is inside the report, because the embedded invoice is the evidence the summary is drawn from. The reported document exists so the Authority can index and match at scale without parsing the invoice first, not so the invoice can be withheld.

Two consequences follow for anyone sizing this work. TDD payloads are roughly invoice-sized plus a small header, so storage and transmission planning should assume a second copy of every invoice. And there is nothing to negotiate about which commercial fields "have to" go to the Authority: under this design they all do.

How the TDD is generated

Derive it from the validated PINT OM invoice. Never author it alongside the invoice in the ERP — two sources of the same truth diverge, and the divergence surfaces as a rejection weeks later.

The transform is deterministic given its inputs, but it is worth being precise about what those inputs are, because "pure function of the invoice" is not quite right. Reading the invoice gives you the identifiers, parties, currencies and amounts. Four things it cannot give you have to be supplied:

  1. Which endpoint is reporting — the seller's or buyer's Peppol participant identifier, with its scheme.
  2. Which endpoint receives — the Authority's participant identifier on scheme 0242.
  3. The reporter's representative — the service provider's own identifier, also on scheme 0242.
  4. When the original document was received, as a date and a time.

Everything else is derived. Because the reported document's UUID is a version 5 UUID computed from invoice fields, regenerating a TDD for the same invoice with the same inputs produces the same identifier, which is what makes retries safe.

Keep the transform free of database lookups and outbound calls. Two things follow. Every published PINT OM sample becomes a unit test, so a failure is a gap in the transform rather than a debate about interpretation. And the whole transform stays reviewable in a single pull request.

Validation: 66 rules, all fatal

The TDD goes through the same layered validation as the source invoice:

  1. XSD — the pxs, cac, cbc and cec namespaces.
  2. Schematronpeppol-om-tdd.sch, compiled to peppol-om-tdd.xslt and run on Saxon-HE 12.4.
  3. Code-list checks — currency code, document type code, document scope, reporter role, participant identifier scheme.
  4. Cross-document consistency — the reported document's identifiers and parties against the embedded source invoice.

The TDD Schematron carries 66 rules and every one of them is flagged fatal. This is a real difference from the invoice packs, where a rule can fire at warning level and be logged for audit. In the TDD pack there is no warning level: a rule that fires stops the document. Any pipeline that treats TDD Schematron output as advisory is mis-built.

Rule identifiers are worth surfacing in your own error messages. ibr-tdd-17 tells you the receiving party's scheme is wrong; ibr-tdd-27 tells you the UUID is not version 5. Both are one-line fixes once you know which rule fired, and unrecognisable otherwise.

How the TDD reaches the Tax Authority

Over Peppol, through the same send path as any other document.

PINT OM invoice ──► validate ──► transmit on Peppol to the buyer ──► persist receipt
                              │
                              └─► TDD transform ──► validate ──► send on Peppol to the OTA ──► persist delivery

The Authority is addressed as an ordinary Peppol participant. ibr-tdd-17 requires the receiving party's endpoint scheme to be 0242 — the Peppol Service Provider identifier scheme — which is the structural statement that corner five is a participant on the network, not a portal you upload to. In GoRoute's implementation the TDD is submitted through the same document-send service as an invoice, carrying metadata that links the report back to the transaction it describes, so its delivery is reconciled against the original invoice.

Two persistence points matter, and both are evidence of compliance:

  • The Peppol receipt for the invoice exchange between supplier and buyer.
  • The delivery record for the TDD leg to the Authority.

Lose either and the audit trail is incomplete.

When this becomes mandatory in Oman

Tax Authority Decision No. 189/2026 makes electronic tax invoices mandatory from 1 April 2027 for taxable persons whose annual supplies exceed OMR 5,000,000, and from 1 October 2027 for those at or below that threshold. It has been in law since publication in Official Gazette No. 1660 on 9 August 2026, amending the VAT Executive Regulations at Article Three.

Ahead of those dates the Tax Authority has said a voluntary pilot of 100 companies starts from end-August 2026. That is an Authority statement about a pilot, not a legal phase in the decision.

An earlier indicative schedule circulated — February 2027 and August 2027 — from the Authority's FAQ. It was never law and the statutory dates are later, not earlier. Anyone still planning to the old dates has about two extra months, not two fewer. The full reading is in Oman sets its e-invoicing dates, and the global picture is in the e-invoicing mandates 2026 tracker.

Common engineering pitfalls

  1. Hand-authoring the TDD. Generate it from the validated invoice. A second hand-maintained data model is a second thing to get wrong.
  2. Omitting the source invoice. ibr-tdd-23 and ibr-tdd-57 both fail. If your TDD is a few kilobytes, you have built the summary and forgotten the evidence.
  3. Reusing the invoice's random UUID in the reported document. It must be a version 5 UUID derived from the invoice fields, and the Authority recomputes it.
  4. Decorating the routing parties. A PartyName on pxs:ReportingParty is fatal under ibr-tdd-10. Those blocks are addresses.
  5. Treating Schematron output as advisory. Every TDD rule is fatal; there is nothing to downgrade.
  6. Floating-point sums. Use decimal arithmetic with explicit rounding; the amounts are checked against the embedded invoice.
  7. Coupling TDD submission synchronously to the invoice send. Decouple them. If the Authority's endpoint is briefly unreachable the invoice should still leave, with the TDD queued and retried.

What GoRoute ships

GoRoute (POP000991) runs the TDD generator and the Peppol send path to the Authority in production. The TDD Schematron is compiled to XSLT at Docker build time and the four PINT OM invoice-family packs ship pre-compiled; all of them run in-process through Saxon-HE 12.4. The Oman regression suite in the API repository stands at 234 tests across 32 files, 16 of them on the TDD generator alone.

GoRoute is accredited by the Oman Tax Authority as an e-invoicing service provider, accredited 29 July 2026 through Union Digital Technologies SPC. For the architecture around this document, read Oman's 5-corner model explained; for the identifiers, the PINT OM CustomizationID reference; for programme context, the Oman Fawtara readiness guide.

Book a demo to see TDD generation run against your own sample invoices.


Sources: OpenPeppol PINT OM v1.0.1 artefacts as shipped in GoRoute's validator, including the peppol-om-tdd Schematron and its published examples; OpenPeppol PINT framework; Oman Tax Authority Fawtara documentation; Tax Authority Decision No. 189/2026, Official Gazette No. 1660, 9 August 2026; Saxon-HE 12.4.

Frequently asked questions

What is the Oman Tax Data Document?
The Tax Data Document (TDD) is an XML document with CustomizationID urn:peppol:taxdata:om-1 and ProfileID urn:peppol:taxreporting. It reports one transaction to the Oman Tax Authority under the Fawtara continuous transaction control regime. It carries a summary of the invoice plus the complete original invoice embedded inside it, and it travels over the Peppol network to the Authority as the fifth corner.
Is the TDD the same as the invoice?
No, but it contains one. The TDD wraps two things: a ReportedDocument block holding the tax-relevant summary — identifiers, both parties' tax IDs and names, total tax amount and total excluding tax — and a SourceDocument block that must contain the whole original UBL 2.1 Invoice or Credit Note. Rule ibr-tdd-57 fails the document if the source invoice is missing.
What CustomizationID and ProfileID does the TDD use?
CustomizationID urn:peppol:taxdata:om-1 and ProfileID urn:peppol:taxreporting, enforced by rules ibr-tdd-01 and ibr-tdd-02. Both are fatal, so a wrong value stops the document rather than warning about it.
How is the TDD generated?
It is derived from a valid PINT OM invoice by a transform that reads the invoice and adds the routing and timing values the invoice cannot know: which endpoint is reporting, which endpoint receives, the reporting service provider's own identifier, and the date and time the document was received. GoRoute runs this as an internal tdd_generator service.
What validates the TDD?
A dedicated Schematron, peppol-om-tdd.sch, compiled to XSLT and run on Saxon-HE 12.4. It carries 66 rules and every one of them is fatal — the TDD pack has no warning level, so any rule that fires stops the document.
How does the TDD reach the Oman Tax Authority?
Over the Peppol network, the same way any other document is sent. The Authority is addressed as an ordinary Peppol participant on scheme 0242, the Peppol Service Provider identifier scheme, which rule ibr-tdd-17 requires for the receiving party. There is no separate portal upload in this flow.
When does the Oman e-invoicing mandate apply?
Tax Authority Decision No. 189/2026 sets 1 April 2027 for taxable persons whose annual supplies exceed OMR 5,000,000, and 1 October 2027 for those at or below that threshold. The decision has been in law since its publication in Official Gazette No. 1660 on 9 August 2026.

Related posts

Building on Peppol?

GoRoute is a certified Peppol Access Point & SMP. Book a demo or read the docs to get started.

Book a demo Read the docs