VAT Return Support Report
Two endpoints turn the invoices you have sent and received into the boxes of the Oman VAT return, and let you open any figure to see the documents behind it.
All paths below are relative to https://app.goroute.ai/peppol-api. Every call is scoped
to the organisation of the API key you send.
Nothing here files anything with the Oman Tax Authority, and no figure on it is a tax position. It aggregates documents that crossed the Peppol network into the shape of the return so that a preparer can check them.
Six boxes are not added up from your documents, and three of them are yours to
complete. Boxes 5b, 6c and 6d depend on decisions held in your ledger, not on any
invoice โ bad debts, refunds, returns, the capital-asset split and input-tax
apportionment; the response marks them manual. 6c is a partial exception: a purchase
already classified as a capital asset is counted there for you. Boxes 1d, 1e and 2a are
switched off because the Oman return has not activated them; the response marks them
not_activated. The derivation field says so, box by box.
The two endpointsโ
| Method and path | What it does |
|---|---|
GET /api/v1/reports/vat | The 20 return boxes for a period, with coverage and exceptions |
GET /api/v1/reports/vat/documents | Every document that carried tax in that period, line by line |
Both require the transactions:read permission โ the same permission that lets you
read your transactions one at a time. There is no separate reporting scope, because the
report exposes nothing you could not already retrieve document by document.
GET /api/v1/reports/vatโ
Query parametersโ
| Name | Required | Type | Meaning |
|---|---|---|---|
period_start | yes | date (YYYY-MM-DD) | First day of the tax period |
period_end | yes | date (YYYY-MM-DD) | Last day of the tax period |
vat_number | no | string | Restrict to one taxpayer registration, matched on the seller VAT number |
Two rules are enforced, and both return 422:
period_endmust not come beforeperiod_start.- The period must not exceed 460 days. A tax period is a quarter, or a year at the widest. Anything longer is not a return, so the request is refused rather than answered.
curl -H "X-API-Key: $GOROUTE_API_KEY" \
"https://app.goroute.ai/peppol-api/api/v1/reports/vat?period_start=2027-01-01&period_end=2027-03-31"
How a figure gets into a boxโ
Four decisions shape every number, and all four are stated back to you in the basis
block of the response so you never have to assume them.
The tax point is the invoice date, not the transmission date. An invoice dated 31 March and sent on 2 April belongs to the first-quarter return. This matters more in Oman than it used to: the amended Article 143 requires an invoice when consideration is received before the supply, so a prepayment invoice and the supply it anticipates can legitimately fall in different periods.
The accounting currency is OMR. Amounts are serialised as strings with exactly three decimal places, because OMR runs to 1000 baisa and a return is not a place to lose one.
Foreign currency. Where an invoice declares BT-111 โ the VAT amount in the accounting currency โ that declared figure wins, and no rate we hold may overrule it. Otherwise USD is converted at the Central Bank of Oman peg of 0.384500. Per-line amounts are scaled by the header ratio rather than converted line by line, so the split by rate still adds up to the header total.
Anything that cannot be placed in OMR is excluded, never counted at face value. A
document in a currency with no conversion available โ including one with no currency code
at all โ is left out of every box and listed under exceptions. Silently valuing a
foreign invoice as though it were rials is the failure this rule exists to prevent.
Credit notes are subtracted, not added.
The boxesโ
Box numbers, labels and definitions come from the Oman Tax Authority's own VAT Taxpayer
Guide: VAT Return Filing. Each box in the response carries a derivation telling you
where its figure came from.
derivation | What it means for you |
|---|---|
derived | Added up from documents in the period |
computed | Arithmetic on other boxes, per the guide's own formula |
manual | Left empty on purpose. Enter it from your records |
not_activated | Not in use on the Oman return today |
| Box | Label | Derivation |
|---|---|---|
| 1a | Supplies of goods / services taxed at 5% | derived |
| 1b | Supplies of goods / services taxed at 0% | derived |
| 1c | Supplies of goods / services tax exempt | derived |
| 1d | Supplies of goods, tax levy shifted to recipient inside GCC | not_activated |
| 1e | Supplies of services, tax levy shifted to recipient inside GCC | not_activated |
| 1f | Supply of goods as per profit margin scheme | derived |
| 2a | Purchases from the GCC subject to Reverse Charge Mechanism | not_activated |
| 2b | Purchases from outside of GCC subject to Reverse Charge Mechanism | derived |
| 3a | Exports | derived |
| 4a | Import of Goods (Postponed payment) | derived |
| 4b | Total goods imported | derived |
| 5a | Total VAT due under (1(a)+1(f)+2(a)+2(b)+4(a)) | computed |
| 5b | Adjustment of VAT due | manual |
| 6a | Purchases (except import of goods) | derived |
| 6b | Import of goods | derived |
| 6c | VAT on acquisition of fixed assets | manual |
| 6d | Adjustment of input VAT credit | manual |
| 7a | Total VAT due (5(a) + 5(b)) | computed |
| 7b | Total input VAT Credit (6(a) + 6(b) + 6(c) + 6(d)) | computed |
| 7c | Total (7(a) + 7(b)) Net VAT | computed |
The full definition from the guide is returned with every box, so the preparer sees the rule that decided the mapping without leaving the response.
The OTA form writes 7c as 7(a) + 7(b), treating 7(b) as a credit. The response computes it
as due minus credit, so a positive number means payable to the Tax Authority and a
negative number means refundable. The box's own note says this on every response.
Two mappings are worth knowing because they are the ones a naive reading of the XML gets
wrong. An export carries UBL tax category Z on the wire, but belongs in box 3a, not
1b โ the guide is explicit that 1b excludes exports. A reverse-charge import is
rendered as S, but belongs in 2b, not 1a. Both are placed from the transaction type
captured before the document was rendered, not from the code that went on the wire.
Response shapeโ
{
"jurisdiction": "OM",
"basis": {
"box_structure": "Oman Tax Authority โ VAT Taxpayer Guide: VAT Return Filing",
"tax_point": "invoice date (BT-2)",
"accounting_currency": "OMR",
"fx_policy": "OMR native; USD at the Central Bank of Oman peg of 0.384500; a declared BT-111 accounting-currency VAT amount overrides any rate we would apply",
"standard_rate_percent": "5"
},
"positioning": "Return support, not a filing. ...",
"period": { "start": "2027-01-01", "end": "2027-03-31" },
"vat_number": null,
"boxes": [
{
"code": "1a",
"label": "Supplies of goods / services taxed at 5%",
"definition": "Total value of standard rated supplies of goods and services in the Sultanate, including deemed supplies. Report the VAT-exclusive value only.",
"base": "412500.000",
"vat": "20625.000",
"document_count": 318,
"derivation": "derived",
"note": "",
"transaction_ids": [
"7c1f7d54-2a3f-4a51-9a2f-1c9d0a6b5e21",
"b0e4f2a1-8c77-4d2e-9f10-2a5b6c7d8e90"
]
}
],
"coverage": {
"facts_in_period": 340,
"documents_excluded": 4,
"credit_notes": 11,
"boxes_awaiting_manual_entry": ["5b", "6c", "6d"],
"statement": "340 document(s) carried tax facts in this period; 4 excluded and listed under exceptions. Boxes 5b, 6c, 6d require entry from your records.",
"transactions_in_period_by_transmission_date": 352,
"gap_note": "12 transaction(s) transmitted in this window carry no tax facts. ..."
},
"exceptions": [
{
"transaction_id": "7c1f7d54-2a3f-4a51-9a2f-1c9d0a6b5e21",
"document_number": "INV-2027-0912",
"issue": "no OMR conversion available",
"detail": "currency EUR; excluded from all boxes"
}
]
}
base is column 1 of the return, the value excluding VAT. vat is column 2. Both are
null where the box holds no figure. Box 5a, 7a, 7b and 7c carry a VAT amount only.
transaction_ids lists every document counted in the box, one entry per document, so it is
as long as document_count. The example above is shortened. It is the same list the
drill-down filters on, which makes it the audit trail for the figure:
GET /api/v1/reports/vat/documents?box=1a returns exactly
these transactions.
Nine boxes never carry that list, and an empty drill-down on them is the right answer.
transaction_ids is always [] on the four computed boxes (5a, 7a, 7b, 7c), on the two
adjustment boxes you complete yourself (5b, 6d) and on the three not_activated boxes
(1d, 1e, 2a). Ask the drill-down for one of them โ for example
GET /api/v1/reports/vat/documents?box=5a โ and you get 200 with count: 0 and an
empty documents array, not an error. Nothing has gone wrong in your request: a computed
box has no documents of its own, only the boxes its formula adds up; an adjustment box is
filled from your own records; and a not-activated box is not in use on the Oman return, so
any line that mapped to one was set aside and appears under exceptions instead. To trace
a computed figure, drill into the derived boxes named in its label โ for 5a that is 1a,
1f, 2a, 2b and 4a.
Box 6c is the exception among the three manual boxes, and it can hold documents. A
received purchase whose tax fact is flagged as a capital asset is counted in 6c, and its
transaction is added to 6c's transaction_ids exactly as it would be for a derived box โ
so GET /api/v1/reports/vat/documents?box=6c can return documents. The capital-asset
classification is not something an invoice carries, so 6c only fills up for purchases that
have already been classified as capital assets in the data behind the report; otherwise a
standard-rated purchase goes to 6a. Read an empty 6c as "nothing was classified as a
capital asset", not as "this box never has documents". 6c stays listed in
boxes_awaiting_manual_entry either way, because it may still need an apportionment
figure from your records.
Read coverage before you trust the boxesโ
coverage is the honesty check on the report, and it is the first thing to look at.
facts_in_periodโ documents whose invoice date falls in the period and from which tax figures were extracted.transactions_in_period_by_transmission_dateโ documents transmitted in the same window. It is a different count on purpose, and the two will rarely match.documents_excludedโ documents or lines left out of every box. Every one appears inexceptions.boxes_awaiting_manual_entryโ normally["5b", "6c", "6d"].gap_noteโ present only when fewer facts were found than transactions transmitted.
A gap_note is not automatically a problem: some documents legitimately fall in another
tax period, because the tax point is the invoice date. The rest are documents from which
figures have not been extracted. Closing that difference is an internal operation on our
side, not something you can call โ if a gap does not explain itself, raise it with support
before you rely on the period.
Exceptions you may seeโ
issue | What happened |
|---|---|
no OMR conversion available | The document is in a foreign currency with no conversion, or carries no currency code. Excluded from every box. |
extraction assumption | A figure was read with a caveat, which is spelled out in detail. The document is still counted. |
no seller VAT number | An outbound document that cannot be attributed to a taxpayer registration. Still counted. |
no return box for this line | The line's category has no box on the Oman return โ out-of-scope supplies are the usual cause. Excluded. |
maps to box 1d/1e/2a, which is not activated | The document used a GCC reverse-charge category the Oman return does not currently activate. Excluded, and the tax treatment needs review. |
GET /api/v1/reports/vat/documentsโ
The drill-down. A figure you cannot trace back to the invoices behind it is an assertion, not evidence, so this returns every document that carried tax in the period, with its per-rate lines.
| Name | Required | Type | Meaning |
|---|---|---|---|
period_start | yes | date (YYYY-MM-DD) | First day of the tax period |
period_end | yes | date (YYYY-MM-DD) | Last day of the tax period |
box | no | string | A return box code, for example 1a. Narrows the response to the documents behind that box |
Pass a box and you get back only the documents behind that box. An unrecognised code is
rejected with 422; a recognised code is echoed back in the box field, and count is
the number of documents after filtering, so it narrows with the list. Leave box out and
you get every document that carried tax in the period.
box filters now, and this page used to say it did notUntil today this page said that box was checked and then ignored, and told you to filter
in your own code instead. That is no longer true. If you read the old wording and wrote a
client-side filter, or decided against a server-side reconciliation because of it, this is
the paragraph that withdraws the advice.
The filter was added to the product on 4 September 2026, and on 13 September 2026 we confirmed it is in the builds behind both the test and the live service. A filter in your own code still gives the same answer โ it is simply no longer necessary.
Three details matter if you are reconciling a box back to its documents.
- Filtering picks whole documents, not single lines. A document whose lines belong to more than one box is returned in full when you ask for any one of those boxes, with all of its lines. Add up the lines you asked for, not the document totals, or a multi-rate invoice will overstate the box.
transaction_idson each box of the main report is the list this filter is built from.GET /api/v1/reports/vatreturns it on every box, andGET /api/v1/reports/vat/documents?box=โฆselects exactly those transactions. You can use it directly as the audit trail for a figure without making a second call.- A computed, adjustment or not-activated box answers with nothing. Boxes 5a, 7a, 7b,
7c, 5b, 6d, 1d, 1e and 2a hold no
transaction_ids, so asking for one of them returns 200 withcount: 0rather than an error โ drill into thederivedboxes instead. Box 6c is the one box markedmanualthat does collect documents: capital-asset purchases are counted there. The boxes shows which is which.
This endpoint does not accept vat_number. It covers the whole organisation for the
period.
Response shapeโ
{
"period": { "start": "2027-01-01", "end": "2027-03-31" },
"box": "1a",
"count": 340,
"documents": [
{
"transaction_id": "7c1f7d54-2a3f-4a51-9a2f-1c9d0a6b5e21",
"document_number": "INV-2027-0912",
"tax_point_date": "2027-02-14",
"direction": "sent",
"is_credit_note": false,
"buyer_name": "Muscat Trading LLC",
"seller_name": "Al Batinah Supplies LLC",
"currency": "OMR",
"taxable_amount": "1250.0000",
"tax_amount": "62.5000",
"omr_taxable_amount": "1250.0000",
"omr_tax_amount": "62.5000",
"om_invoice_kind": null,
"om_invoice_kinds": [],
"is_simplified": false,
"source": "canonical",
"warnings": [],
"lines": [
{
"canonical_category": "standard",
"ubl_code": "S",
"tax_rate": "5.0000",
"taxable_amount": "1250.0000",
"tax_amount": "62.5000",
"exemption_reason_code": null
}
]
}
]
}
Three fields repay attention:
directionโsentis your output tax,receivedis your input tax.sourceโcanonicalmeans the figures were captured before the document was rendered, so the category and the transaction type are exactly as you supplied them.ublmeans they were recovered from the stored document afterwards. Both are usable;canonicalis the stronger record.canonical_categoryagainstubl_codeโ the category as you meant it, beside the code that actually went on the wire. They differ for exports and reverse charge by design, and that pair is what makes a box defensible to an inspector holding the original document.
Money is returned as strings throughout, at the precision it is stored: four decimal places at document and line level, three in the report boxes.
Related pagesโ
- Oman country guide โ the mandate dates, PINT OM validation rules and the QR code
- Audit Log API โ who did what, and when