Certified Peppol Access Point

Odoo Peppol Integration and API

Send customer invoices from Odoo over the Peppol network and the other global e-invoicing networks. Odoo keeps issuing the invoice; the connector converts it, validates it against the destination country's rules, delivers it, and writes the outcome back.

Odoo ERP

Open Source Business

GoRoute.ai Gateway

Certified Peppol Access Point

Peppol
DBN
Finvoice

How do you send a Peppol invoice from Odoo?

Raise the invoice in Odoo as usual. An addon module reads it once Odoo validates it, converts it to a structured UBL document, and posts it to a certified Peppol Access Point over a REST API. The Access Point validates it, looks up the buyer, delivers it, and writes the status back into Odoo.

Nothing changes about how your finance team works. That is the single most common question asked before any integration is agreed, so it is worth answering first: the person entering an invoice keeps entering it the same way, in the same screens, from a sales order, a subscription or a service bill. The connector sits alongside that workflow rather than in front of it, and it takes over at the point where Odoo marks the invoice validated.

The rest of this page works through the pieces in order: what Odoo's own invoicing produces and where the network asks for more, what the setup wizard asks you for, what the API path looks like if you would rather write the integration yourself, which identifiers have to be right before anything will route, what comes back after a document is sent, and a full worked example in Belgium — which is where two thirds of this page's readers are. If you want the document format explained first, what a UBL invoice is is the shorter read, and how the Peppol network works covers the delivery side.

Stage Where it happens What it produces
Invoice validated Odoo A posted customer invoice with a number, and the trigger for everything after it
Mapping The addon, using the field mapping you configured once A UBL document carrying party identifiers and coded tax
Validation GoRoute, before transmission A compliance score with named rule failures, not a bare pass or fail
Lookup and delivery The Peppol network The document in the buyer's system, and a signed receipt back
Status Back into Odoo, and to any webhook endpoint you register Queued, sending, sent — or a named failure reason

Why Connect Odoo to GoRoute.ai?

Leverage the power of open-source ERP with enterprise-grade e-invoicing compliance.

Open Source Freedom

Keep your open-source philosophy while adding enterprise e-invoicing capabilities. No vendor lock-in.

REST API Integration

Python module using Odoo's native API. Seamless integration with accounting, sales, and subscription modules.

Multi-Company Ready

Handle multiple companies within single Odoo instance. Company-specific e-invoicing configurations and compliance rules.

Invoice Automation

Automatically convert sales orders, subscription invoices, and service bills to compliant UBL format. No manual intervention.

Modular Architecture

Install as Odoo addon module. Compatible with Community and Enterprise editions. Easy updates and maintenance.

Custom Fields Support

Map custom invoice fields to UBL elements. Support for industry-specific requirements and local tax authorities.

Simple Odoo Integration Process

Get your open-source ERP connected to global e-invoicing networks in 3 steps.

1

Install Odoo Addon

Download and install the GoRoute.ai addon module from Odoo Apps Store or directly from our repository. Compatible with Odoo 14, 15, 16, and 17.

  • One-click installation from Apps Store
  • Compatible with Community & Enterprise
  • Automatic dependency management
2

Configure API Connection

Set up API credentials and map Odoo invoice fields to UBL format. Configure customer Peppol IDs and tax settings for automated processing.

  • Secure API key authentication
  • Field mapping configuration wizard
  • Multi-company support setup
3

Test & Go Live

Test invoice transmission with sandbox customers. Once validated, enable automatic e-invoicing for all customer invoices with real-time status tracking.

  • Sandbox testing environment
  • Real-time delivery tracking
  • Automated error handling

Is Odoo Peppol ready, and what does Odoo do on its own?

“Peppol ready” is not really a property of an accounting system, which is why the question is harder to answer than it looks. Being reachable on the network means three separate things are true: you have a participant identifier registered in the network's directory, the documents you produce pass the rule set that applies where they are going, and you have a route to a certified Access Point that can send and receive on your behalf. None of those three is something Odoo does by itself, and none of them is difficult once you know that is the shape of the problem.

What Odoo does, it does well, and it is worth being precise about it because the integration work is only the difference between this list and the next one. Odoo raises a customer invoice from a sales order, a subscription or a service bill. It holds the customer record, the company record, the chart of accounts and the tax configuration behind them. It numbers the invoice from its own sequence, posts it, and renders it as a PDF for a human to read. It keeps the accounting entries that follow. A business running Odoo already has, in one place, almost every fact an electronic invoice needs.

What it does not produce on its own is a network document. A PDF is a picture of an invoice: a person can read it, and a machine cannot post it without someone retyping the numbers. The network carries something different — the same facts as structured data, in UBL 2.1, following the Peppol BIS Billing 3.0 profile of the European standard EN 16931, so that a buyer's accounts-payable system and a tax authority can both validate and book it without reading it. Between the two sits conversion, validation against the destination country's rules, a directory lookup for the buyer's address, delivery over the AS4 transport, and a status coming back. That is the part the connector adds.

One honest limit, stated here rather than discovered in a procurement meeting: this page does not tell you what your own Odoo release includes. Odoo's own feature set moves between versions and differs between editions, and what ships in a given release is a question for Odoo's documentation for that version, not for us. What is described here is the GoRoute connector path, which supports Odoo 14, 15, 16 and 17 in both Community and Enterprise editions, on Odoo.sh, on self-hosted installations and on third-party hosting. Whichever provider you end up asking, get the version support you would be relying on in writing.

Connecting Peppol to Odoo: the setup wizard and what it asks for

Three things, done once, and then nothing per invoice and nothing per user. Install the addon module, from the Odoo Apps Store or directly from our repository, with dependencies resolved automatically. Enter your API credentials, so the addon can authenticate; the key travels in the X-API-Key header on every request and is scoped to your organisation. Then set the mapping, which is what the configuration wizard is for.

The wizard asks for three kinds of thing. Which Odoo invoice fields correspond to which UBL elements — most of them are obvious and pre-filled, and the interesting ones are the handful your business uses differently from everybody else. Your customers' Peppol identifiers, which is the subject of its own section below because it is the part that takes the longest. And your tax settings, so that a rate in Odoo becomes a coded tax category in the document rather than just a number.

Two things the wizard handles that are easy to overlook until you need them. Custom fields can be mapped to UBL elements, which is what lets industry-specific invoicing survive the conversion instead of being flattened into a generic document — construction, healthcare and professional-services billing all carry fields a stock invoice does not. And a single Odoo instance running several companies is handled as several configurations rather than one, so each company keeps its own identifiers, its own compliance rules and its own e-invoicing settings.

What the wizard cannot do is decide your business rules, and no integration can. Which of your Odoo products is a service and which is a licence, whether a customer in another member state is reverse-charged, what unit a metered line is measured in — these are decisions, made once by someone who knows the business, and then applied to every invoice afterwards. They are cheap to get wrong and cheap to fix, provided you test before you send. There are two recorded walkthroughs of the whole sequence if you would rather watch it than read it: connecting Odoo in under four minutes, and the full eleven-minute API demonstration with twelve chapters.

How does the Odoo Peppol API work?

The addon is one way in; the API underneath it is the other, and it is the same interface either way. If you have your own development team, or your Odoo estate carries enough local modification that a packaged addon would fight it, you can write directly against the REST API and skip the module entirely. The path is the same one the addon takes.

You POST the UBL document to the send endpoint with your API key in the X-API-Key header. What comes back is not a bare acknowledgement: the response carries a status, a message identifier to correlate against, and a validation block reporting the UBL and Schematron outcomes and any warnings. A document that fails does so with the rule that broke and the field it broke on, which is a ticket somebody can act on rather than a rejection code that starts a conversation.

Three properties of the interface matter more than the request shape does. Batches take between 1 and 1,000 invoices in a single request, with validation and processing as separate stages — which is the difference between a month-end that works and one that does not, because a design sending one invoice per call is fine in testing and fails on the last day of the month. Validation-only calls carry no per-call charge, along with status lookups and webhooks, so validating the same invoice forty times while getting a mapping right costs nothing. And the directory lookup is available as its own call: give it any ISO 6523 participant identifier and it returns the document types and processes that receiver supports, along with the receiving Access Point endpoint. That is how you find out a buyer is reachable before you build an invoice for them.

You can exercise all of it before anything reaches a customer. Our free developer sandbox issues a test API key, and it points at four deterministic test receivers that simulate success, timeout, validation failure and recipient-not-found end to end, including the webhook events each one produces. The compliance gate in the sandbox is the same five-layer gate as production — UBL 2.1 XSD, business rules, code lists, the baseline EN 16931 and Peppol BIS 3.0 Schematron, and any national specialisation that applies — so a sandbox result is a production result.

Going live changes your key and nothing else. The test key becomes a live key, GoRoute issues your Peppol certificate, registers your participant identifier in the production directory, and unlocks real sending and receiving. The API surface is identical, so there is no code change at the switch — which is the property you actually want from a sandbox, and the one that is easiest to promise and hardest to deliver. The full specification, a Postman collection and code samples are published at docs.goroute.ai, and the API services page sets out the interface as a whole.

Which identifiers have to be right in Odoo first

This is the part almost every project underestimates, and it is not a technical task. A Peppol address is not an email address. It is an identifier plus the scheme that identifier belongs to, and the pair has to be registered in the network's directory before anything can be delivered to it. Which identifier and which scheme depends on the country: a Belgian business is registered under its ten-digit enterprise number in scheme 0208, an Omani one under its VAT identification number carried with an OM prefix in scheme 0248.

In Odoo that data lives in your contact and company records, which means the work is spread across a customer base rather than concentrated in a configuration screen. Two habits save weeks. Fix your own side first — your company records are a handful of entries entirely within your control, and getting them right removes most of the noise from early test results. Then count the gap before you plan around it: run a count of active customers with no usable identifier. That single number is the size of the data work, and it is much better known in week one than in week nine.

Identifiers are checked rather than trusted, which is a mercy. Belgian enterprise numbers carry a check digit — the last two digits are 97 minus the first eight modulo 97 — and Peppol validates it, so an invoice quoting a malformed number is rejected outright under rule PEPPOL-COMMON-R043. GoRoute enforces the scheme and the check digit at registration, which means a bad identifier is caught before it reaches the network rather than after your invoice bounces.

One thing that is not your job: registering yourself on the network. That is the Access Point's obligation, not the customer's. You supply the number; your provider registers you, and in Belgium is contractually obliged to do so under the enterprise-number scheme rather than the VAT scheme.

What comes back after an Odoo invoice is sent

The network answers, which is the largest practical difference between sending an e-invoice and emailing a PDF. There are two layers to the answer, and confusing them is the commonest reason a finance team believes an invoice is stuck when it is not.

The transport layer is the exchange itself. When the receiving Access Point takes the document it returns a signed receipt, and that receipt is evidence of handover: it proves the infrastructure serving your customer accepted the document, and it is what you keep if delivery is ever disputed. It does not prove a human has looked at the invoice, and it is not agreement with the amount. The business layer sits above it. Where a recipient sends one, a message-level response names what failed — a rule the document broke, or an identifier that did not resolve. Not every recipient sends one, which is worth knowing in advance rather than discovering during a month-end.

Inside Odoo this arrives as a status you can act on. A document moves through queued, sending and sent, and a failure carries a reason rather than a silence: TIMEOUT, VALIDATION_ERROR or RECIPIENT_NOT_FOUND. Failed transmissions are retried automatically with exponential backoff, and the addon creates an activity record in Odoo so a person sees it rather than a log file does. An invoice remains a valid invoice regardless of transmission status — a document that has not been delivered is not a document that does not exist.

Where an integration is listening, the same events are pushed rather than polled for. GoRoute posts document.received, document.validated, document.sent, document.failed and document.delivered events with HMAC-signed payloads, retried with exponential backoff and dead-lettered if your endpoint stays unreachable. An invoice raised in Odoo and one raised in the GoRoute portal end up in the same register carrying the same kind of record, because the connector is a route in rather than a separate system.

Two status models, kept apart. Odoo's invoice status answers a question about accounting: is this posted, is it paid. The Peppol status answers a question about delivery: did the document arrive, and was it well-formed. An invoice can be paid and undelivered, or delivered and unpaid, and neither state is an error. A dashboard that collapses them into one field will eventually tell somebody something untrue. And a document already delivered cannot be unsent, because it belongs to the recipient's records as much as to yours — a correction is a structured credit note referencing the original, sent the same way, not an edit to history.

Odoo Peppol integration in Belgium: a worked example

Belgium is where most of this page's readers are, and it is the clearest worked example available because the obligation there is already live rather than approaching. It also arrives in more than one language: Belgian readers search for this in Dutch, French and English, and the Dutch phrasing — Peppol-integratie — is by some distance the commonest of the three. Belgian invoicing law recognises the same thing, requiring support for Dutch, French and German.

The obligation itself. Structured electronic invoicing has been mandatory between Belgian VAT-registered businesses since 1 January 2026, and since the tolerance period closed on 31 March 2026 it has been enforced without exception. It covers every business established in Belgium and registered for Belgian VAT, including foreign companies with a Belgian fixed establishment and VAT groups. Three cases fall outside it: invoices to consumers, activities exempt under Article 44 of the Belgian VAT Code, and non-resident businesses with no fixed establishment — though that last group will still be sent structured invoices, so it needs a way to receive them.

The format is unusually simple. Belgium requires Peppol BIS Billing 3.0 in UBL 2.1, compliant with EN 16931, and publishes no national specialisation of its own — plain BIS 3.0 is the whole requirement, which makes Belgium cheaper to comply with than neighbours that layer national rules on top. A PDF is not a structured invoice, and neither is a PDF with an XML file attached alongside it. Document types follow the standard codes: 380 for a commercial invoice, 381 for a credit note, and corrections have to be issued as structured credit notes rather than emailed.

The identifier is the enterprise number from the Crossroads Bank for Enterprises — ten digits, under scheme 0208, not the VAT scheme. In Odoo that goes on the company record for your own entity and on every Belgian customer's contact record. And there is a trap here that catches people who set this up before 2026: the Hermes service was decommissioned on 31 December 2025, with read-only access until March 2026. Until then every Belgian company was reachable on the network by default, because they had all been pre-registered and undeliverable documents were forwarded by email. That safety net is gone. A Belgian buyer who has not appointed a service provider is now genuinely unreachable, and a send to them fails at the lookup — which is a correct outcome rather than a fault. In Odoo it shows up as RECIPIENT_NOT_FOUND, and the first thing to check is not your mapping but whether that customer is on the network at all.

What happens if you do not comply is documented rather than vague. Administrative fines escalate per offence inside a three-month window — €1,500 for the first, €3,000 for the second, €5,000 for the third — and the clock resets after three months without a further breach. The larger commercial risk is not the fine: a buyer obliged to receive structured invoices may simply refuse a PDF, and an invoice that cannot be booked does not get paid, so the working-capital cost usually arrives before any penalty does. Looking further out, from 1 January 2028 Belgium adds near real-time reporting to the tax authority on a five-corner model, and has confirmed that no platform accreditation will be required — your provider needs to be a certified Access Point that can file both sides correctly, not a Belgian licence-holder. Worth designing for while you are in the code rather than reopening it in eighteen months. Our Belgium e-invoicing page covers the mandate, the penalties, the 2028 change and the platform in full.

So the realistic sequence for a Belgian Odoo user is short. Confirm your own enterprise number and its check digit. Appoint an Access Point and have it register you. Populate scheme 0208 identifiers across your Belgian customer records in Odoo, and count the gap first. Map the fields once, with the wizard or in your own code. Validate real documents in the sandbox before sending any of them. Then turn it on — and make sure you can receive as well as send, because the Belgian mandate is symmetrical. Running something other than Odoo? The same path from Stripe billing and from Business Central and Dynamics 365 is written out the same way.

Using Odoo for e-invoicing in Oman

Oman's Fawtara programme asks for things a stock Odoo invoice does not carry. These go deeper than a product page can.

Ready to Enhance Odoo with E-Invoicing?

Join businesses using GoRoute.ai to automate their global e-invoicing with open-source Odoo ERP integration.

Frequently Asked Questions

Everything you need to know about Odoo e-invoicing integration

Can Odoo send Peppol invoices?

Odoo raises the invoice; the Peppol part is what happens to it afterwards. A GoRoute addon module reads the invoice once Odoo validates it, converts it to UBL 2.1 in the Peppol BIS Billing 3.0 profile, and posts it to our certified Access Point, which validates it, looks the buyer up in the network directory, delivers it and writes the status back into Odoo. Nothing changes about how your finance team raises an invoice.

Is there an Odoo Peppol API?

Yes, and it is the same interface the addon uses. You POST the UBL document to the send endpoint with your key in the X-API-Key header, and the response carries a status, a message identifier and a validation block reporting the UBL and Schematron outcomes. Batches take between 1 and 1,000 invoices in a single request, validation-only calls carry no per-call charge, and directory lookups are available as their own call. The request and response shapes are in the API documentation.

Which Odoo versions and hosting are supported?

The addon supports Odoo 14, 15, 16 and 17 in both Community and Enterprise editions. It works on Odoo.sh cloud hosting, on self-hosted installations and with third-party hosting providers, and is deployed through Odoo's standard addon management. Ask any provider, including us, to confirm the version support you would be relying on in writing. Our own hosted infrastructure options are set out separately.

What is my Peppol identifier in Odoo, and where does it go?

A Peppol address is an identifier plus the scheme it belongs to, and it lives on your company record and on each customer's contact record in Odoo. A Belgian business uses its ten-digit enterprise number from the Crossroads Bank for Enterprises under scheme 0208; an Omani one uses its VAT identification number with an OM prefix under scheme 0248. Populating those across an existing customer base is usually the longest task in the project.

How do I connect Odoo to Peppol for the Belgian mandate?

Structured e-invoicing has been mandatory between Belgian VAT-registered businesses since 1 January 2026 and enforced without exception since the tolerance period closed on 31 March 2026. Confirm your enterprise number and its check digit, appoint an Access Point to register you under scheme 0208, populate identifiers across your Belgian customer records in Odoo, map the fields once, validate real documents in the sandbox, then send. Belgium publishes no national specialisation, so plain Peppol BIS Billing 3.0 is the whole format requirement. The Belgium page has the mandate in full.

What happens if an invoice fails to send from Odoo?

It fails with a reason rather than a silence: TIMEOUT, VALIDATION_ERROR or RECIPIENT_NOT_FOUND. Failed transmissions are retried automatically with exponential backoff and the addon creates an activity record in Odoo so a person sees it. The invoice remains a valid invoice regardless of transmission status. A Belgian recipient that will not resolve is usually a buyer who has not appointed a service provider, since the Hermes fallback was decommissioned on 31 December 2025.