There are three ways to get an invoice from Odoo to SERES: type it by hand into their portal, run it through a third-party middleware, or connect the ERP directly. You don't choose the platform (a large customer or a public contract imposes it), but you do choose the number of layers. And every extra layer is a place where a status can get stuck halfway.
We implemented the four-day deadline wrongly twice in a row: the diff is at the end.
The only thing you decide: where the invoice status lives
It's an architecture question: where does the fact that an invoice was accepted live? Outside Odoo, someone looks at it on another screen and copies it by hand. Inside, next to the journal entry, it can be filtered, it triggers alerts and it reconciles without anyone typing.
The three paths, measured in daily work
In money they can't be compared without knowing your volume and your contract. In daily work they can.
| Path | Who types | Where the status lives | What breaks first |
|---|---|---|---|
| Web portal, by hand | One person, invoice by invoice | Only in the portal | The day that person is absent. In Odoo everything still shows as “sent” |
| Third-party middleware | Nobody, as long as everything goes well | In the middleware, and sometimes in Odoo too | The statuses: two truths that don't match |
| Connection from the ERP itself | Nobody | In Odoo, next to the invoice | If the platform changes the channel, it's up to you |
The middle option dominates search results: whoever sells it has a product to sell. Without a technical team it's reasonable, but know what you're buying: one more layer to check when something doesn't add up.
Which documents travel, and in what format
Royal Decree 238/2026 of 25 March (BOE of the 31st, in force on 20 April) establishes in article 7.1 that the electronic invoice must follow the EN16931 semantic model and use one of four syntaxes: CII, UBL, EDIFACT invoice message or Facturae message.
Two details in the same article condition any integration: every invoice issued through a private exchange platform is signed with an advanced electronic signature (7.3), and carries a unique code with the issuer's tax ID, number and series, and issue date (7.5). The ERP produces that, not the connector.
When the pressure starts is another matter: the fourth final provision defers the effects by twelve months for those invoicing more than eight million euros and twenty-four for everyone else, counted from the entry into force of the ministerial order developing the public invoicing solution. That order sets the date, not you.
Purchase orders and delivery notes are a different story: the regulation only names the EDIFACT invoice message. The order and the dispatch advice live in the bilateral agreement with your customer: the BOE doesn't require that, your customer does, and your customer sets the rules.
FACe: what changes when the customer is the Administration
Here the rule is earlier and different. Article 4.1 of Law 25/2013 requires invoicing the Administration through the corresponding general entry point for public and private limited companies, entities without Spanish nationality, permanent establishments of non-residents, UTEs (joint ventures) and several other types on that same list. Administrations may exclude invoices of up to 5,000 euros by regulation: they may, they are not obliged to.
Three things you won't find in a normal B2B: thirty days to submit it from the actual delivery (article 3); an advanced electronic signature based on a recognised certificate (article 5.1); and identifying the recipient administrative bodies (article 9.1): accounting office, managing body and processing unit. Without those codes the invoice goes in and bounces back days later.
In Odoo there's a version trap. The core module l10n_es_edi_facturae (“Spain - Facturae EDI”, LGPL-3) generates Facturae 3.2.2 and signs it with the company's certificate. But in Odoo 17 the administrative centre roles come from a separate module, l10n_es_edi_facturae_adm_centers (“Administrative Centers Patch” in its manifest, marked auto_install). In 18 and 19 that module no longer exists: its data lives inside the main one. When migrating from 17, check that those roles are still in the database.
The four-day deadline: what the BOE says, word for word
People often repeat that “the Crea y Crece Law gives four days to communicate the invoice status”. The law doesn't say that. Law 18/2022, in its article 12, amends article 2 bis of Law 56/2007, and on statuses it says only one sentence: “The recipient and the issuer of electronic invoices must provide information on invoice statuses”. The deadline is in the regulation. Royal Decree 238/2026, article 10.3, verbatim:
“Information on invoice statuses must be sent within a maximum of four calendar days, excluding Saturdays, Sundays and national public holidays, from the date on which the reported status occurs in each case.”
Neither working days nor plain calendar days: four calendar days excluding Saturdays, Sundays and national public holidays, a third way of counting. And 10.1 places the obligation on the recipient: when you send, your customer has the deadline; when you receive, you do. That paragraph also requires commercial acceptance or rejection with its date, and full actual payment with its own.
The case: we got the count wrong twice in a row
In the first version of our SERES connector for Odoo, the field was called verifactu_deadline and the column read “Plazo VeriFactu (4 días hábiles)”. Two errors in one label: it doesn't come from VeriFactu and they aren't working days. This is how it looked in Odoo 19:

We changed the label and, with it, the arithmetic: out went the loop that skipped weekends, in came a straight addition of four days.
-def _add_business_days(start, days):
- current, added = start, 0
- while added < days:
- current += timedelta(days=1)
- if current.weekday() < 5: # Mon-Fri
- added += 1
- return current
+STATE_REPORT_DEADLINE_DAYS = 4
...
- doc.verifactu_deadline = _add_business_days(doc.sent_date, 4)
+ doc.state_report_deadline = doc.sent_date + timedelta(days=STATE_REPORT_DEADLINE_DAYS)
And there came the second error: reading “four calendar days” without the clause that follows. With the document in the screenshot, sent on Wednesday 8 July 2026, three dates come out depending on how you count.
| Count | Date | Verdict |
|---|---|---|
| 4 working days (v1) | Tuesday 14 July | Correct by chance, false label |
| 4 plain calendar days (v2) | Sunday 12 July | Two days early, and on a Sunday: excluded |
| Article 10.3 of RD 238/2026 | Tuesday 14 July | The right one: skipping Saturday 11 and Sunday 12 |
The lesson: a deadline like this isn't written by hand in a computed field. It needs the BOE text in front of you, a calendar of national holidays as data, and a test for the ugly case, an invoice sent on the eve of a long weekend. A wrongly calculated deadline breaks nothing: it alerts late, or it alerts on a Sunday.
“Sent” is not “accepted”
The costliest mistake in these integrations is treating an invoice as fine when it is only sent. An honest cycle has at least six statuses (draft, XML generated, sent, accepted, rejected and error) and only two, accepted and rejected, say that someone on the other side has looked at it. In the screenshot four coexist: draft, XML generated, accepted and rejected.
With the same honesty: the transport channel to SERES is not yet operational in what we have built. The method that sends raises an explicit exception (there is no self-service test environment) and the statuses in that screenshot are set by a demo action marked as such in the log.
One last detail, in case anyone builds the receiving side. Our module called _get_edi_decoder on an empty recordset. In Community it works. In Odoo.sh, which runs Enterprise, account_invoice_extract overrides it with an ensure_one(), and an empty account.move() blows up with “Expected singleton”. The real build caught it; the local test bench, which is Community, passed it.
VeriFactu is something else, and it arrives at the same time
Confusing them costs money. B2B regulates the format and exchange between companies. VeriFactu regulates what your software does internally when issuing: the chained, tamper-proof record of each invoice. Neither covers the other. If you're going with both, start with what VeriFactu is and how to comply with it using Odoo.
Before deciding
- Where the status of each invoice will live, and who checks it every morning.
- Whether your ERP signs with an advanced electronic signature and, when the Administration is involved, whether accounting office, managing body and processing unit appear in the XML.
- And if someone shows you a green test suite, what it ran on: Community locally and Enterprise on Odoo.sh are not the same.
Removing a layer isn't always the right answer, but it is almost always the right question: if the platform is imposed, what remains to decide is whether the status of your invoices lives inside your ERP or outside it.
Frequently asked questions
Is the four-day deadline in working days or calendar days?
Neither. Article 10.3 of Royal Decree 238/2026 says “four calendar days, excluding Saturdays, Sundays and national public holidays”. It's its own way of counting, and the obligation falls on the recipient of the invoice, not on the issuer.
Can I send the invoice to the Administration directly from Odoo?
Odoo generates the Facturae 3.2.2 and signs it with the company's certificate. Check that the invoice carries accounting office, managing body and processing unit: in Odoo 17 those administrative centres come separately and in 18 and 19 they are already in the main module. Without them, the general entry point rejects it.
Are B2B e-invoicing and VeriFactu the same obligation?
No. VeriFactu regulates how your software generates and protects each invoicing record internally. B2B e-invoicing regulates the format and exchange between companies, on its own calendar. Complying with one doesn't cover the other.
What we do about this
Do you have SERES imposed and Odoo inside?
Tell us what your customer requires and which Odoo version you're on, and we'll tell you what can be done from the ERP and what can't. Write to us at comercial@flexigobe.com or call +34 616 809 504.
