Skip to main content

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.

This is return support, not a filing

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 pathWhat it does
GET /api/v1/reports/vatThe 20 return boxes for a period, with coverage and exceptions
GET /api/v1/reports/vat/documentsEvery 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โ€‹

NameRequiredTypeMeaning
period_startyesdate (YYYY-MM-DD)First day of the tax period
period_endyesdate (YYYY-MM-DD)Last day of the tax period
vat_numbernostringRestrict to one taxpayer registration, matched on the seller VAT number

Two rules are enforced, and both return 422:

  • period_end must not come before period_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.

derivationWhat it means for you
derivedAdded up from documents in the period
computedArithmetic on other boxes, per the guide's own formula
manualLeft empty on purpose. Enter it from your records
not_activatedNot in use on the Oman return today
BoxLabelDerivation
1aSupplies of goods / services taxed at 5%derived
1bSupplies of goods / services taxed at 0%derived
1cSupplies of goods / services tax exemptderived
1dSupplies of goods, tax levy shifted to recipient inside GCCnot_activated
1eSupplies of services, tax levy shifted to recipient inside GCCnot_activated
1fSupply of goods as per profit margin schemederived
2aPurchases from the GCC subject to Reverse Charge Mechanismnot_activated
2bPurchases from outside of GCC subject to Reverse Charge Mechanismderived
3aExportsderived
4aImport of Goods (Postponed payment)derived
4bTotal goods importedderived
5aTotal VAT due under (1(a)+1(f)+2(a)+2(b)+4(a))computed
5bAdjustment of VAT duemanual
6aPurchases (except import of goods)derived
6bImport of goodsderived
6cVAT on acquisition of fixed assetsmanual
6dAdjustment of input VAT creditmanual
7aTotal VAT due (5(a) + 5(b))computed
7bTotal input VAT Credit (6(a) + 6(b) + 6(c) + 6(d))computed
7cTotal (7(a) + 7(b)) Net VATcomputed

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.

Box 7c and the sign of the answer

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 in exceptions.
  • 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โ€‹

issueWhat happened
no OMR conversion availableThe document is in a foreign currency with no conversion, or carries no currency code. Excluded from every box.
extraction assumptionA figure was read with a caveat, which is spelled out in detail. The document is still counted.
no seller VAT numberAn outbound document that cannot be attributed to a taxpayer registration. Still counted.
no return box for this lineThe 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 activatedThe 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.

NameRequiredTypeMeaning
period_startyesdate (YYYY-MM-DD)First day of the tax period
period_endyesdate (YYYY-MM-DD)Last day of the tax period
boxnostringA 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.

Correction โ€” box filters now, and this page used to say it did not

Until 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_ids on each box of the main report is the list this filter is built from. GET /api/v1/reports/vat returns it on every box, and GET /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 with count: 0 rather than an error โ€” drill into the derived boxes instead. Box 6c is the one box marked manual that 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 โ€” sent is your output tax, received is your input tax.
  • source โ€” canonical means the figures were captured before the document was rendered, so the category and the transaction type are exactly as you supplied them. ubl means they were recovered from the stored document afterwards. Both are usable; canonical is the stronger record.
  • canonical_category against ubl_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.