Skip to main content

Send your own PINT OM UBL

UBL XML (Direct)โ€‹

You can also submit UBL you have produced yourself. This is a JSON call to POST /api/v1/documents: the XML travels as a string in the document field. You do not POST raw XML, and this endpoint has no application/xml request body.

On this path GoRoute does not alter your document. It is transmitted exactly as you submitted it โ€” no QR code is added. If your invoice needs those elements, generate them before you send.

Send Omani invoices as PINT OM, or as invoice data

An invoice or credit note from an Omani seller โ€” sent from a 0248 participant, or naming an OM VAT number as the seller's โ€” must be PINT OM (urn:peppol:pint:billing-1@om-1), or be sent as invoice data to POST /api/v1/invoices so GoRoute renders it as PINT OM and reports it to the Tax Authority. A BIS Billing 3.0 invoice from an Omani seller is accepted and logged for now, but do not rely on that: GoRoute can refuse it. The refusal is HTTP 422 with error_code OMAN_PINT_OM_REQUIRED, and its message starts with [OMAN-PINT-OM-REQUIRED]. Only a new document is refused: sending again a document GoRoute has already accepted returns its existing transaction, as any idempotent resend does.

import json
import requests

with open("oman-invoice.xml", encoding="utf-8") as f:
invoice_xml = f.read()

response = requests.post(
f"{BASE_URL}/api/v1/documents",
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
json={
"receiver_scheme": "0248",
"receiver_id": "OM1100054321",
# The Omani seller, the reporter of the Tax Data Document. Always send it.
# Left out, some GoRoute services take the seller from the document and
# others use any of your organisation's participants; under the wrong
# one the TDD is held.
"sender_scheme": "0248",
"sender_id": "OM1100099001",
# The PINT OM identifier: without it the BIS 3.0 default is assumed
# and the call is refused with 422 DOCUMENT_TYPE_MISMATCH.
"document_type": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@om-1::2.1",
# The PINT process. Always send it. Left out, some GoRoute services set it
# from document_type; others assume the BIS 3.0 process, no SMP record
# matches, and the send fails with TRANSPORT_ERROR.
"process_id": "urn:peppol:bis:billing",
"document": invoice_xml,
},
)
# The document above is transmitted exactly as submitted.
print(response.status_code, response.json()["transaction_id"])

The same call with curl, reading a JSON body you have already assembled:

curl -X POST https://app.goroute.ai/peppol-api/api/v1/documents \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @request.json

receiver_scheme, receiver_id and document are the required fields; sender_scheme and sender_id are optional, but name them on every Omani send (below). A successful call returns 202 Accepted with a transaction_id. The same request is documented in full under Sending an Invoice.

Set document_type to the PINT OM identifierโ€‹

document_type defaults to the Peppol BIS Billing 3.0 identifier. A PINT OM document sent without it is refused with HTTP 422 DOCUMENT_TYPE_MISMATCH, and nothing is created: the identifier's root part must be the XML's root element, and its customisation part must equal the document's own cbc:CustomizationID. The error body's expected_document_type is the value to send. For Oman:

Documentdocument_typeprocess_id
Invoice, debit note, prepayment invoice (380, 383, 386)urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@om-1::2.1urn:peppol:bis:billing
Credit note (381)urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:peppol:pint:billing-1@om-1::2.1urn:peppol:bis:billing
Self-billed invoice (389)urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:selfbilling-1@om-1::2.1urn:peppol:bis:selfbilling
Self-billed credit note (261)urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:peppol:pint:selfbilling-1@om-1::2.1urn:peppol:bis:selfbilling

Send the process_id from the table every time; that is correct on every GoRoute service. A GoRoute service that sets the process from the document type uses the same value when you leave it out, and refuses a named process that does not match the PINT OM document type with HTTP 422 PROCESS_ID_MISMATCH (the body's expected_process_id is the value to send; nothing is created). A service that does not yet set it fills an omitted process_id with the BIS 3.0 process (urn:fdc:peppol.eu:2017:poacc:billing:01:1.0). A PINT OM document sent with that process fails with TRANSPORT_ERROR ("Failed to resolve SMP endpoint"): the buyer's SMP record publishes the PINT OM document type under the PINT process only, so no endpoint matches.

Name the party that issues the document as the senderโ€‹

On a PINT OM send, sender_scheme and sender_id must name the party that issues the document, as 0248 and its VATIN. That is the Omani seller, or the buyer on a self-billed invoice or credit note (389, 261), because a self-billed document travels from the buyer to the seller. The Tax Data Document's reporter is the request's sender, not the party in the XML. Sent under another identity, the document is delivered but its TDD is held with C5_OM_REPORTER_NOT_ENABLED and is never filed. The sender must be a participant of your organisation.

If you leave the sender out, a GoRoute service that orders the default sender uses the issuing party from the document when it is an active participant of your organisation, and otherwise your organisation's participant registered first; a service that does not yet order it uses any of your organisation's active participants. Name it, and check sender_peppol_id on the transaction.

A document that was sent with the wrong sender or process cannot be sent again as it is: the same XML is answered with the existing transaction, and the same invoice number with changed XML is refused as a duplicate. Give the invoice a new number (and so a new UUID) and send it again with the fields above.

The rules for every document you submit yourself are in Send your own XML.

Which receiver to nameโ€‹

A buyer on Peppol is named by its own identifier, 0248:OMโ€ฆ for an Omani VAT-registered buyer. A document whose buyer has no Peppol identifier is addressed to one of the stand-in participants that the Solution Reference Architecture defines in section 10.3.1. Put the same value in the request (receiver_scheme 0248, receiver_id below) and as the buyer's cbc:EndpointID in the XML:

receiver_idUse it for
997770000099A B2C sale (a simplified tax invoice, or a buyer with no VAT number and no Peppol ID), and a profit-margin scheme invoice
997770000097An export to a buyer who is not registered on Peppol
997770000095A buyer in Oman who is not yet on Peppol, other than B2C
997770000096A deemed supply that is not to be shared with the buyer
997770000098A self-billed import that is not subject to the Oman e-invoicing rules

A document addressed to a stand-in is not sent over Peppol: the architecture forbids exchanging it with a Corner 3. GoRoute reports it to the Tax Authority only, and you receive tdd.reported_via_substitute once the report is filed. Give the buyer their copy yourself, for example as a PDF. PINT OM also makes the Seller UUID (BTOM-004) mandatory on an invoice to 997770000099 (IBR-173-OM), and a B2C invoice needs its QR code embedded before you send, because GoRoute does not alter a document you submit.

An export can also name the buyer's own identifier: when GoRoute's lookup confirms that the buyer is not registered for the document, the invoice is reported under 997770000097 instead, as for an invoice data send.

Imports are recorded through the imports API, not through POST /api/v1/documents.

Earlier revisions of this page documented an endpoint that does not exist

This page previously told you to POST raw UBL, with a raw-XML content type, to a send path nested underneath /api/v1/documents, and said GoRoute would add the QR code, hash and signature to it. No such endpoint has ever existed, and code written against it has never worked. Use POST /api/v1/documents as shown above, and note that it does not modify your document.