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.

Two fields on POST /api/v1/invoices control this, and a delivery object in the response tells you what was decided. This page covers both, 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.

The two fieldsโ€‹

Both go at the top level of the POST /api/v1/invoices body, beside invoice, and both default to auto.

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

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.

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.
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.

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
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.

  1. An Oman document goes over the network as PINT OM, always. If either party is in Oman, no other format or channel applies, and asking for one is refused.
  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.

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_ONLYEither party is in Oman 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.
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.
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.