Invoice Responses
GoRoute does not currently offer an API for sending an Invoice Response. If you have received an invoice and want to tell the supplier that you have accepted it, rejected it, or have a question about it, there is no GoRoute endpoint that will send that message over the Peppol network for you today. This page explains what the Peppol Invoice Response is, what GoRoute does do, and what to do instead.
Earlier revisions of this page published a call for sending an Invoice Response, along with a request format and a set of status codes to send. None of it was ever built, and any integration written against it will fail. If you built against that page, nothing you can change in your request will make it work โ see What to do instead.
What a Peppol Invoice Response isโ
Peppol defines an Invoice Response message (a UBL ApplicationResponse) that lets a buyer tell
a supplier what has happened to an invoice โ that it has been received, accepted for payment,
rejected, queried, or paid. It travels over the same network as the invoice, in the opposite
direction, and it is a distinct Peppol business document with its own profile.
It is optional in most of the Peppol network. Where a country's rules require it, that requirement falls on the buyer, and it is not currently something GoRoute can carry out on your behalf.
What GoRoute does todayโ
Message Level Status, in the Oman flow onlyโ
The platform generates and exchanges a Message Level Status (MLS) automatically as part of
the Oman tax-reporting flow. An MLS is also a UBL ApplicationResponse, but it is a different
thing from an Invoice Response: it reports what happened to the message โ whether it was
accepted or rejected in transit โ rather than a buyer's commercial decision about the invoice.
Three things follow from that, and they are worth being blunt about:
- It is automatic. You do not trigger it, and there is no request body for you to fill in.
- It is Oman only. It is produced by the Oman tax-reporting pipeline, which is enabled for Oman document exchanges. An invoice sent to a Belgian, Australian or Dutch buyer has no MLS.
- The codes are
AP(accepted) andRE(rejected). These are values you read off a transaction. There is no call that lets you choose one and send it.
Reading an MLSโ
Where an MLS exists, you can retrieve it in its original, unaltered form. Which call you use depends on who wrote the MLS, and there are two:
| The MLS you want | The call |
|---|---|
| The one GoRoute sent on your behalf, acknowledging a document that arrived for you | GET /api/v1/transactions/{transaction_id}/mls?leg=sent |
| The buyer's accept or reject of an invoice you sent | GET /api/v1/oman/transactions/{transaction_id}/mls?leg=received |
| The Oman Tax Authority's answer on your invoice's Tax Data Document | GET /api/v1/oman/transactions/{transaction_id}/mls?leg=authority |
Both return the UBL ApplicationResponse XML and both need an API key with the
transactions:read permission.
GET /api/v1/transactions/{transaction_id}/mls?leg=received cannot return the buyer's
answer. It searches your own organisation, and the answer is addressed to GoRoute's
service-provider identity rather than to yours, so it is filed under GoRoute's organisation.
The call answers 404 DOCUMENT_NOT_STORED whether the buyer has answered or not.
Earlier versions of this page said a 404 was the normal "no MLS yet" case. That is true for
leg=sent, and for any transaction outside the Oman flow, which has no MLS at all. It is
not true for the buyer's answer: use the Oman call for received and authority.
The full account of both calls โ the required leg, the three refusal codes, and how to tell
whether a service has the Oman call at all โ is on one page, so that these two cannot drift
apart:
Fetching an MLS document in the Oman
guide.
Ask GET /api/v1/transactions/{transaction_id}/reporting first to see which legs exist. Read
the legs from mls.legs[], but do not follow the document_url it gives a received leg โ
it names the call that cannot serve it.
import requests
API_BASE = "https://app.goroute.ai/peppol-api"
def get_sent_mls(transaction_id: str) -> str | None:
"""The MLS GoRoute sent on your behalf, as UBL XML, if there is one."""
response = requests.get(
f"{API_BASE}/api/v1/transactions/{transaction_id}/mls",
params={"leg": "sent"},
headers={"X-API-Key": "your_api_key"},
)
if response.status_code == 404:
return None # No MLS was sent for this transaction
response.raise_for_status()
return response.text
def get_received_mls(transaction_id: str, leg: str = "received") -> str | None:
"""The buyer's MLS (leg="received") or the Tax Authority's (leg="authority")
on an Omani invoice you sent. Needs a service with the Oman pack switched on."""
response = requests.get(
f"{API_BASE}/api/v1/oman/transactions/{transaction_id}/mls",
params={"leg": leg},
headers={"X-API-Key": "your_api_key"},
)
if response.status_code == 404:
return None # Not answered yet, or the Oman pack is not on this service
response.raise_for_status()
return response.text
Status events for invoices you sentโ
If a status comes back about an invoice you sent, and it arrives through the Oman MLS flow,
GoRoute raises a webhook event for it. The event name reflects the status: response.accepted
when the message was accepted, response.rejected when it was rejected, and
response.received when the status is anything else, with mls.received beside it. They go to
the organisation that owns the invoice, even though the buyer's access point addresses its
status message to GoRoute's Service Provider identity rather than to you; see
Response Events for the payload. Subscribe to these
the same way as any other event โ see Webhook Setup.
They are things you are told about; they are not things you can send.
What to do insteadโ
If you need to accept, reject or query an invoice you have received, handle it outside the Peppol network for now:
- Record the decision in your own system. Your accounts payable workflow is the source of truth for whether an invoice is approved, queried or paid. See Processing Documents for the pipeline.
- Contact the supplier directly โ email or your existing supplier portal โ when you need to reject an invoice or ask about it. Give the invoice number and the specific reason, so the supplier can issue a credit note or a corrected invoice.
- Ask the supplier for a credit note where an invoice is wrong. A credit note is a real Peppol document, it travels the network normally, and GoRoute both sends and receives it. That is the supported way to correct an invoice that has already been exchanged.
If you need thisโ
Invoice Response support is not published on a roadmap, and this page does not promise it. If sending Invoice Responses over Peppol is a requirement for you โ particularly if it is a regulatory requirement in a market you operate in โ tell us, through Support, and say which market and which profile you need. That is the useful signal, and it is more use to us than a guess.
Next Stepsโ
- Accounts Payable โ received invoices as draft bills in Odoo
- Processing Documents
- Webhook Setup
- Best Practices