Skip to main content

Delivery and Formats

Every invoice you send answers two questions: which format the document is written in, and which way it travels to the buyer. Until now GoRoute answered both for you โ€” Peppol BIS 3.0 UBL, over the Peppol network. You can now say what you want instead, and there is a second route: a PDF you send by email, with the machine-readable invoice embedded inside it.

Three fields on POST /api/v1/invoices control this, and a delivery object in the response tells you what was decided. This page covers all three, the rules that decide when you leave the choice to us, and the cases where a delivery is refused because the law does not allow it.

When this arrived, and what it was checked against

The two request fields, the delivery response object, the issued status and the hybrid PDF were released on 7 September 2026. Before that date POST /api/v1/invoices had no format or channel field, every document went over the Peppol network, and there was no delivery object in the response.

Everything on this page was read from the product source in this repository and cross-checked against the machine-readable description that the test service publishes, on 7 September 2026. The production service does not publish its description, and both services report their version as 1.0.0, so we cannot tell them apart by asking. Our release record pins the same build to production, but that is a record, not a probe. If your integration depends on this and you are calling production, confirm with support before you build on it.

Added 6 October 2026: the third field, destination, and the AUTHORITY_REFUSED row in the refusals table. Both were read from the product source in this repository and cross-checked against the machine-readable description the test service publishes, on that date. The field itself is not new โ€” it is older than this page's account of it.

The three fieldsโ€‹

All three go at the top level of the POST /api/v1/invoices body, beside invoice. The first two default to auto and the third to peppol, so leaving all three out is the behaviour described throughout this page.

{
"invoice": { "...": "your canonical invoice" },
"document_format": "auto",
"delivery_channel": "auto",
"destination": "peppol"
}

document_format โ€” which syntax we renderโ€‹

ValueWhat you get
autoThe default. UBL, in the profile the buyer's country and Peppol entry call for. This is what you got before this release.
ublPeppol BIS 3.0, or PINT UBL where the country uses it.
xrechnungThe German public-sector customisation, KoSIT XRechnung 3.0, rendered in UBL. Use it for a German public buyer that asks for the German profile.
ciiEN 16931 in the CII syntax โ€” the XML that goes inside a ZUGFeRD or Factur-X PDF. This is an email format: see the refusal below.
zugferdExactly the same as cii. It is a spelling, not a different document.

delivery_channel โ€” which way it travelsโ€‹

ValueWhat happens
autoThe default. We look the buyer up on the Peppol network. If they are registered for this document, it goes over the network; if not, and email is lawful for your country, the document is issued for you to email.
peppolOver the network, with no lookup. The buyer's participant identifier must be on the invoice.
emailThe document is built, stored, and handed back to you to send. The transaction status becomes issued and GoRoute never transmits it.
If you ask for email and only have the buyer's VAT number

Every document GoRoute files is addressed to a participant identifier, even one that never goes on the network. When you set delivery_channel to email and the buyer has no peppol_id but does have a vat_number, we derive an identifier from that VAT number using the standard scheme for the country, and record the document under it. This is the same derivation the WooCommerce plugin makes, so the same buyer always ends up as the same receiver. It happens only when you ask for email explicitly, not under auto.

destination โ€” the buyer, or the tax authority insteadโ€‹

The first two fields both assume the document is going to the buyer, and only argue about how. destination is the field that questions the assumption.

ValueWhat happens
peppolThe default, and what every call did before this field existed. The document goes to the buyer, as document_format and delivery_channel decide. Everything else on this page describes this value.
authorityThe document goes to the tax authority only, and to no buyer. No Peppol lookup is made and no email decision is taken. The delivery object comes back with channel: "authority".

authority exists for regimes where a sale is reported to the tax agency and the buyer โ€” often a member of the public with no Peppol address โ€” receives a PDF rather than a network document. GoRoute serves two cases today: Spain's Verifactu records, such as a consumer ticket, and Poland's KSeF invoices.

On production, authority works only for an enrolled Spanish or Polish organisation, and its filings are real

The value is accepted by the request schema everywhere, but it only works where a jurisdiction pack on that service serves the route for your organisation. On production (https://app.goroute.ai/peppol-api), that is:

  • a Spanish organisation enrolled in Verifactu with its setup complete, whose records go to AEAT's production service; or
  • a Polish organisation enrolled in KSeF with its setup complete, whose invoices go to KSeF's production environment.

Everyone else gets 400 AUTHORITY_REFUSED. On a test service the same packs, where switched on, send to AEAT's and KSeF's test environments, which have no tax effect.

For Spain, the full account โ€” which AEAT service each GoRoute service uses, what the refusal says, what the one waived validation rule is, and what the raw-XML route accepts โ€” is on Spain โ€” Verifactu. For Poland, see Poland โ€” KSeF.

The delivery object in the responseโ€‹

A successful POST /api/v1/invoices now carries a delivery object saying what was decided and why.

{
"transaction_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "issued",
"message": "Invoice validated and issued for delivery by email: send the buyer the PDF from GET /transactions/{id}/pdf (a PDF/A-3 hybrid with the e-invoice embedded)",
"delivery": {
"channel": "email",
"format": "cii",
"profile": "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0",
"hybrid_pdf": true,
"hybrid_profile": "zugferd",
"buyer_on_network": false,
"reason": "The buyer is not on the Peppol network; the document goes by email."
}
}

profile is the customisation identifier of the UBL document GoRoute renders and stores as the record, which is why a Peppol BIS 3.0 identifier appears here beside "format": "cii". The stored document of record is always UBL; the CII is produced from the same invoice when the hybrid PDF or the CII download is asked for.

FieldMeaning
channelpeppol โ€” the document was queued for transmission. email โ€” it was issued and stored, and you send it. authority โ€” you sent destination: "authority" and it went to the tax authority only.
formatThe syntax of the deliverable: ubl, xrechnung (also UBL), or cii (the XML inside the hybrid PDF).
profileThe customisation identifier, BT-24, of the document that was rendered.
hybrid_pdftrue when GET /api/v1/transactions/{transaction_id}/pdf will give you a PDF/A-3 with the invoice XML embedded.
hybrid_profileThe name your seller's market knows the hybrid by: zugferd for a German or Austrian seller, factur-x for a French one, en16931 everywhere else it is produced, and absent when no hybrid is made.
buyer_on_networkWhat the Peppol lookup concluded, or null when no lookup was made. true means the buyer is registered. false means either that the buyer was not found, or that they were found but do not accept this document type and the document is going by email instead. Because one value covers both, read channel and reason for what actually happened rather than treating this as a plain "is my customer on Peppol" answer.
reasonOne sentence explaining the choice, when it is not the obvious one. null otherwise.

The status changes too. When channel is email, the response status is issued rather than queued, and the transaction stays issued forever. Nothing will submit, deliver or fail it. If you poll for status, treat issued as a third ending โ€” see Tracking Delivery.

GoRoute can send the email for you. POST /api/v1/transactions/{transaction_id}/email (an API key with the invoices:send permission) mails up to five addresses from GoRoute's verified sender with the same PDF the download gives you โ€” the hybrid for an EU seller, the plain PDF otherwise โ€” plus the XML document. The body takes to (one to five addresses), and optionally reply_to, sender_name (a display name only, up to 120 characters โ€” the From address stays GoRoute's verified sender), message and lang (en, ar, de, nl, fr). message is the seller's own note to the buyer: plain text, up to 2,000 characters, carried in the mail. It answers 202 with sent_to and message_id, and records each send under the transaction's metadata.emails.

A sending domain of your own does not change this call. If you have registered and verified your own domain โ€” see Sending Invoice Email from Your Own Domain โ€” it changes the From address of the draft invoice emails, POST /api/v1/drafts/{draft_id}/send-via-goroute and POST /api/v1/drafts/{draft_id}/resend, and of nothing else. This call still sends from GoRoute's verified sender.

A documentation address in to is not a recipient

Addresses at example.com, example.net, example.org, example.edu and their subdomains, and anything under .example, .test, .invalid or .localhost, are reserved by internet standard (RFC 2606 and RFC 6761) and will never have a mailbox. A GoRoute service that enforces that refuses the whole call with 422 EMAIL_ADDRESS_UNDELIVERABLE and sends nothing; one that does not yet enforce it attempts the message and the message bounces. Either way the person never receives it, so if you are copying an example from these pages, substitute a real address in to before you run it. Only the recipients are checked โ€” to here, and the recipient and copies on the draft email calls. reply_to is a header rather than a recipient and is not checked. Nothing is looked up on the network: a real but wrong address still goes out and bounces exactly as before.

The attached PDF is only ever English or Arabic. lang sets the language of the email itself. The attachment is produced in Arabic when you ask for ar, and in English for every other value โ€” so a German, Dutch or French email carries an English PDF.

Refusals. These are checked in the order listed, so a transaction with nothing stored is refused before the rate limit is consulted.

Statuserror_codeWhen
404TRANSACTION_NOT_FOUNDNo transaction with that id in your organisation
409NO_DOCUMENTThere is no stored document to attach. An inbound transaction โ€” one somebody sent you โ€” answers this too
503MAIL_NOT_ENABLEDEmail sending is not switched on in this environment
422EMAIL_ADDRESS_UNDELIVERABLEOn a service that enforces reserved addresses: a recipient in to is a reserved test address that can never receive mail โ€” example.com, .test, .invalid, localhost and the other RFC 2606 / RFC 6761 reservations, such as an app-store reviewer's placeholder order. Nothing is sent, the refusal is recorded under emails with sent: false, and the document is unchanged. A service without that check accepts the call and the message bounces instead, so handle this code and do not rely on getting it
429EMAIL_RATE_LIMITEDThe same transaction has already been emailed three times in the last 24 hours
500PDF_GENERATION_FAILEDThe PDF could not be produced
502EMAIL_SEND_FAILEDThe mail provider would not accept the message

Treat the 429 as a temporary refusal rather than a failed send: the limit is three emails per transaction per 24 hours, and nothing is wrong with the invoice.

What auto actually decidesโ€‹

This is the rule in the order it is applied. Every step below is checked before the one under it. All of it assumes destination is peppol; destination: "authority" skips the whole rule, because there is no buyer to deliver to.

  1. An Oman document goes over the network as PINT OM, always. No other format or channel applies to one, and asking for one is refused. Which documents count as Oman documents is decided by one of two rules, and your own GoRoute platform tells you which โ€” see Which documents are Oman documents immediately below.
  2. cii (or zugferd) means email. CII is the syntax that travels inside a PDF; over Peppol the document is UBL. Asking for cii with delivery_channel: peppol is refused. Asking for cii on its own sets the channel to email for you.
  3. If the channel is email, is email lawful for the seller's country? If not, the send is refused in words. If it is, the document is issued.
  4. If you named a channel of peppol, or named any format other than auto, the document goes over the network with no lookup, and the buyer's participant identifier must be present.
  5. Otherwise โ€” auto and auto โ€” the buyer's own Peppol entry decides:
    • No participant identifier on the invoice at all: email, where email is lawful.
    • Registered, and accepts this document type: over Peppol, as UBL.
    • Registered, and accepts XRechnung but not the ordinary Peppol profile: over Peppol, as XRechnung. The reason field says so.
    • Registered, but does not accept this document type: email. This is the case that surprises people โ€” the buyer is on the network, and the document still goes by email, because over Peppol it would be rejected by their own service entry and by email it reaches them. Where email is not lawful, the send over Peppol is attempted anyway so that a genuine problem is visible rather than silently rerouted.
    • Not registered: email where lawful, otherwise the send over Peppol is attempted and fails visibly.
    • The lookup itself failed (the network could not be asked): over Peppol, exactly as before this release. A network problem never quietly changes how your invoice is delivered.

Which documents are Oman documentsโ€‹

Two rules are in use, and which one applies to you depends on how far Oman's tax-reporting pack has been switched on for your GoRoute platform. Read it, do not guess it: call GET /api/v1/settings/organization and look at the read-only field pint_om_rule.

pint_om_ruleThe rule your platform applies
either_partyThe document is an Oman document when the seller or the buyer is in Oman
seller_or_0248_receiverThe document is an Oman document when the seller is in Oman; or it is an Omani buyer's own import record; or it is an Omani buyer's self-billed document; or it is delivered to a participant addressed under scheme 0248 (Oman's VAT identifier scheme)

Under seller_or_0248_receiver, "delivered to a 0248 participant" means the party the document is sent to has a Peppol identifier whose scheme is 0248 and whose value is not empty. A buyer with no Peppol identifier at all is not one.

The practical difference lands on sellers outside Oman. Under either_party, invoicing a buyer whose address is in Oman forces your document onto PINT OM. Under seller_or_0248_receiver, it does not โ€” unless that buyer is addressed as a 0248 participant โ€” so a format or channel that was refused before is now accepted.

The advice that is safe under either rule: if the seller is in Oman, the document goes over the network as PINT OM and is reported to the Oman Tax Authority. Build for that and you are right whichever rule your platform applies.

When a delivery is refusedโ€‹

All of these come back as HTTP 400 with a body of error, error_code and message. The message is written for a person and can be shown to one.

{
"error": "delivery_refused",
"error_code": "EMAIL_NOT_ALLOWED",
"message": "Belgian businesses must exchange structured e-invoices over Peppol since 1 January 2026; an invoice to a Belgian business cannot be delivered by email. Ask the buyer for the identifier their software receives e-invoices under."
}
error_codeWhen
OMAN_PINT_ONLYThe document is an Oman document and you asked for a format other than auto or ubl, or for the email channel. Omani documents are PINT OM, over the network, reported to the Tax Authority. Which documents count is decided by your platform's pint_om_rule โ€” see Which documents are Oman documents.
CII_IS_EMAIL_ONLYYou asked for cii or zugferd together with delivery_channel: peppol. Over Peppol the document is UBL. For a public buyer that wants the German profile, use document_format: xrechnung.
EMAIL_NOT_ALLOWEDThe seller's country does not permit an invoice to be handed to the buyer outside the network. See the table below.
BUYER_IDENTIFIER_REQUIREDThe document is going over Peppol, and invoice.buyer.peppol_id is missing.
BAD_DOCUMENT_FORMATdocument_format is not one of the five allowed values.
BAD_DELIVERY_CHANNELdelivery_channel is not one of the three allowed values.
AUTHORITY_REFUSEDYou sent destination: "authority" and nothing on this service can serve it โ€” which is the case on production for every organisation not enrolled in Spain's Verifactu โ€” or a jurisdiction pack that can serve it refused this particular document. The error field is authority_refused. Read message for which. See destination above.
You will normally see 422, not the last two codes

document_format and delivery_channel are constrained in the request schema, so a value outside the allowed list โ€” including a correct value in the wrong case, such as UBL โ€” is rejected by request validation with 422 Unprocessable Entity before the delivery rule ever runs. The two codes above exist behind that check. Handle 422 for a bad value; do not build a branch that waits for BAD_DOCUMENT_FORMAT.

Where email delivery is refusedโ€‹

GoRoute refuses an email delivery for sellers in four countries. These are statements of what GoRoute enforces, and why โ€” they are not a complete account of any country's e-invoicing law, and you should not read them as legal advice for your own situation.

Seller countryWhat GoRoute says
๐Ÿ‡ง๐Ÿ‡ช BelgiumBelgian businesses must exchange structured e-invoices over Peppol since 1 January 2026, so an invoice to a Belgian business cannot be delivered by email. Ask the buyer for the identifier their software receives e-invoices under.
๐Ÿ‡ด๐Ÿ‡ฒ OmanOmani invoices are reported to the Tax Authority. A buyer not on the network is filed under the substitute address, never emailed.
๐Ÿ‡ฎ๐Ÿ‡น ItalyItalian invoices go through the SDI exchange system, not by email.
๐Ÿ‡ต๐Ÿ‡ฑ PolandPolish invoices go through KSeF, not by email.

Every other seller country GoRoute serves may deliver by email when the buyer is not on Peppol.

The rule looks at the seller, not the buyer. The messages are worded around the buyer โ€” the Belgian one says "an invoice to a Belgian business" โ€” but what GoRoute actually checks is the country on invoice.seller. So a Belgian seller invoicing a buyer anywhere is refused the email channel, and a seller elsewhere invoicing a Belgian buyer is not. Read the refusal as being about your own establishment.

The hybrid PDFโ€‹

A hybrid is an ordinary, readable PDF with the machine-readable invoice attached inside it, so one file satisfies both a person and an accounting system. It is written as PDF/A-3, the embedded file is called factur-x.xml, and it is EN 16931 CII at conformance level EN 16931. Germany calls this ZUGFeRD, France calls it Factur-X; the file GoRoute produces is the same document under both names. The Extended profile is deliberately not offered.

You get the hybrid from the ordinary PDF download:

GET /api/v1/transactions/{transaction_id}/pdf
response = requests.get(
f"https://app.goroute.ai/peppol-api/api/v1/transactions/{transaction_id}/pdf",
headers={"X-API-Key": "your_api_key"},
)

with open("invoice.pdf", "wb") as f:
f.write(response.content)

Replace {transaction_id} with the transaction_id the send returned โ€” a UUID.

PointDetail
hybridDefaults to true. Pass hybrid=false for a plain PDF with nothing embedded.
Permissiontransactions:export, which is not implied by transactions:read.
Which documentsInvoices and credit notes whose seller is in one of the countries below, and which GoRoute holds as structured invoice data.

The hybrid is a superset of the plain PDF, so it is not only for email. A document you sent over Peppol also comes back as a hybrid, which is what German buyers' software expects when a PDF arrives alongside the network copy.

Which sellers get oneโ€‹

Thirty-two seller countries: the European Union, plus Iceland, Liechtenstein and Norway, plus Switzerland and the United Kingdom. That is wider than the EU, and it is worth saying plainly because a British or Swiss seller reading "EU" concludes the opposite.

Austria, Belgium, Bulgaria, Croatia, Cyprus, Czechia, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Iceland, Ireland, Italy, Latvia, Liechtenstein, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Switzerland, United Kingdom.

Outside that list the PDF is the plain one. Australia and New Zealand have no CII convention, and an Oman document never becomes a hybrid.

The one case where you ask for a hybrid and get a plain PDFโ€‹

The embedded XML is rendered from the canonical invoice GoRoute stored with the document. Not every send stores one.

  • Sends that do store it, and therefore produce a hybrid: POST /api/v1/invoices, a saved draft you send, a CSV or Excel import, a batch send, and documents pulled in by a connector.
  • The send that does not: raw UBL posted to POST /api/v1/documents. That path keeps only the XML you supplied and the metadata you sent with it.

When there is nothing to render from, the download quietly gives you the plain PDF. It does not fail and it does not warn you. If your customers expect a ZUGFeRD or Factur-X file, send invoices as structured data rather than as raw UBL.

Getting the XML on its ownโ€‹

To fetch just the machine-readable invoice, without the PDF around it:

GET /api/v1/transactions/{transaction_id}/document/content

Add syntax=cii for the EN 16931 CII โ€” the same XML that goes inside the hybrid โ€” or syntax=ubl for the stored UBL. With neither, you get whichever syntax was delivered: CII for a document issued for email, UBL for everything else.

If no CII can be produced โ€” because the canonical invoice was never stored, or because it is an Oman document โ€” the call answers 404 with the code CII_NOT_AVAILABLE.