Skip to content

German B2B e-invoicing

This guide defines how Accountify and each client Odoo 19 Online database handle German domestic B2B electronic invoices. The client Odoo database remains the accounting system of record and the electronic-invoicing endpoint. Accountify provides tenant readiness, work routing, status monitoring, evidence, and exception handling; it does not become a parallel invoice issuer or archive.

Implementation contract, not legal advice

The rules below reflect official German guidance checked on July 3, 2026. Tax/legal owners must approve each tenant's applicability, exceptions, retention policy, and rollout. Regulatory changes must trigger a contract and capability review.

Regulatory baseline

Under section 14 UStG, an E-Rechnung is issued, transmitted, and received in a structured electronic format that enables electronic processing. A standalone PDF is an other invoice, not an E-Rechnung, for supplies performed from January 1, 2025 onward.

The BMF E-Rechnung FAQ establishes the current operational baseline:

Date or period Requirement
From January 1, 2025 Domestic businesses must be able to receive E-Rechnungen. An email inbox is legally sufficient, although Accountify uses structured intake where enabled.
January 1, 2025 through December 31, 2026 All issuers may use paper or, with recipient consent, another electronic format such as PDF instead of an E-Rechnung.
Through December 31, 2027 The preceding issue transition continues for issuers whose prior-year turnover does not exceed EUR 800,000. Non-conforming legacy EDI may also continue through this date.
After the applicable transition A qualifying domestic B2B invoice must be issued as an E-Rechnung unless an exception applies.

The BMF identifies XRechnung and ZUGFeRD from version 2.0.1, excluding the MINIMUM and BASIC-WL profiles, as common compliant formats. All VAT invoice-required information must be present in the structured part. For a hybrid document, the structured data is authoritative if it differs from the rendered image.

Common exclusions include B2C invoices, many VAT-exempt supplies, invoices up to EUR 250 gross, travel tickets that qualify as invoices, and supplies by small businesses under the applicable Kleinunternehmer rule. B2G requirements are separate and can impose different formats, identifiers, thresholds, and transport routes. Applicability must therefore be decided from transaction facts, not merely the customer's country.

Product boundary

Concern Authority and responsibility
Legal invoice and ledger record Client Odoo
Structured XML and Odoo attachments Client Odoo; Accountify may retain encrypted evidence under the approved retention policy
E-invoice format and customer endpoint Client Odoo partner/company configuration
Peppol registration and transport Client Odoo/Odoo Peppol service, per company and endpoint
Work queue, review, readiness, exception, and status projection Accountify
Tax applicability and exception policy Approved tenant accounting policy
Cross-client reporting Accountify projections and warehouse marts; never a second ledger

Peppol is a transport network, not the German mandate itself. German law does not prescribe one transport path. Accountify supports Odoo's Peppol path first because it provides structured send/receive behavior and status evidence, while retaining an email/upload path for valid structured files and counterparties not using Peppol.

Verified Odoo 19 surface

The current runtime snapshot confirms account_peppol, account_edi_ubl_cii, documents_account_peppol, and German localization support. Odoo's electronic invoicing documentation states that Odoo can generate structured invoice XML, send invoices through Peppol, and receive Peppol vendor bills either as draft bills in a purchase journal or as Documents records.

Purpose Model and verified fields Accountify policy
Company registration res.company: account_peppol_proxy_state, peppol_can_send, peppol_eas, peppol_endpoint Read for readiness; configuration remains an authorized Odoo administration action
Inbound routing res.company: peppol_reception_mode, peppol_purchase_journal_id, documents_account_peppol_folder_id Read and validate against approved tenant profile
Partner format and route res.partner: invoice_edi_format, invoice_sending_method, peppol_eas, peppol_endpoint, peppol_verification_state Read; controlled configuration only after counterparty verification
Invoice document account.move: ubl_cii_xml_id, ubl_cii_xml_filename, peppol_message_uuid, peppol_move_state, state, type, totals, and write_date Read and synchronize; draft/post behavior follows the AP or AR contract
Purchase journal account.journal: is_peppol_journal, incoming_einvoice_notification_email Read readiness and routing
Odoo proxy registration account_edi_proxy_client.user: edi_identification, edi_mode, proxy state Operations-only read; secrets and private keys are prohibited from Accountify projections

The runtime exposes partner formats zugferd, xrechnung, and ubl_bis3; Peppol delivery states ready, to_send, processing, done, error, and skipped; and company registration states from not_registered through receiver or rejected. These values are snapshot-specific and must be checked per tenant before enablement.

Do not build ordinary integration behavior on transient send wizards. An automated outbound send command requires a clone-proven, allowlisted Odoo business operation with fixed inputs and authoritative status readback. Until that proof exists, staff posts and sends in Odoo while Accountify monitors the result.

Tenant capability profile

Store one versioned profile per Odoo connection and company:

{
  "contract_version": "einvoicing-capability.v1",
  "company_id": 11,
  "german_b2b_receive_supported": true,
  "german_b2b_issue_supported": false,
  "account_peppol_installed": true,
  "ubl_cii_installed": true,
  "german_localization_installed": true,
  "peppol_proxy_state": "receiver",
  "peppol_endpoint_scheme": "9930",
  "peppol_endpoint_hash": "sha256:...",
  "reception_mode": "journal",
  "purchase_journal_id": 12,
  "supported_formats": ["xrechnung", "zugferd", "ubl_bis3"],
  "inbound_fixture_passed_at": "2026-07-03T10:00:00Z",
  "outbound_fixture_passed_at": null,
  "evidence_expires_at": "2026-08-02T10:00:00Z"
}

receive_supported and issue_supported are separate gates. Installation alone proves neither. A profile is enabled only when:

  • the company, German localization, VAT identity, endpoint scheme/ID, and production/test mode are correct;
  • Peppol registration is in the required send/receive state when Peppol is used;
  • the purchase journal or Documents folder is configured and company-safe;
  • the integration user can read required invoice, attachment, partner, journal, and status fields;
  • valid and invalid XRechnung/ZUGFeRD fixtures produce the expected result;
  • duplicate, credit-note, correction, attachment, and status-error cases pass;
  • original structured content and required evidence remain retrievable under the approved retention policy; and
  • capability evidence is current and drift monitoring is active.

One Peppol endpoint can have only one active receiver registration. Database migration, clone testing, or provider changes must not register a production endpoint in two places. Test with Odoo demo mode or an approved non-production endpoint.

Inbound supplier invoice flow

flowchart TD Sender[Supplier] Intake[Peppol or structured file intake] Odoo[Client Odoo] Bill[Draft vendor bill and XML] Sync[Accountify synchronization] AP[AP workbench] Review[Review and approval] Post[Odoo posting] Sender --> Intake --> Odoo --> Bill --> Sync --> AP --> Review --> Post
  1. Odoo receives the structured invoice through Peppol or an approved structured-file channel.
  2. Odoo creates a draft vendor bill in the configured purchase journal, or stores the document in the configured Documents folder for controlled conversion.
  3. Accountify synchronizes the bill, structured attachment identity/hash, vendor reference, totals, dates, status, and source metadata.
  4. The structured XML is the primary extraction source. OCR/vision is used only for an unstructured attachment or a supported enrichment need; it must not overwrite structured values silently.
  5. Accountify deduplicates and routes the item into the supplier invoice workbench, preserving the structured source and any human-readable representation.
  6. Staff resolves vendor, tax, account, analytic, PO/receipt, duplicate, and policy exceptions.
  7. Posting follows the AP review, authorization, freshness, and Odoo readback contract.

Inbound receipt does not prove tax correctness, entitlement to input VAT, successful posting, or payment approval. Invalid XML, unsupported profiles, supplier identity conflicts, and structured/rendered differences become explicit exceptions.

Outbound customer invoice flow

flowchart TD Draft[Draft customer invoice] Approve[Accounting approval] Post[Post in client Odoo] Validate[Generate and validate E-Rechnung] Send[Odoo sends by approved route] Readback[Accountify status readback] Done[Delivered evidence] Exception[Owned exception] Draft --> Approve --> Post --> Validate --> Send --> Readback Readback -->|done| Done Readback -->|error or stale| Exception
  1. The client invoice is created and posted in Odoo under the applicable AR workflow.
  2. Odoo selects the configured partner format and route. Customer endpoint details must be verified; prefilled values are not sufficient evidence.
  3. Odoo generates the structured document and sends it through the approved path. For Peppol, Odoo reports done after delivery to the recipient's access point.
  4. Accountify reads back invoice state, XML attachment, message UUID, Peppol state, customer endpoint hash, and source write_date.
  5. Accountify records delivered only when the configured success evidence is present. queued, processing, timeout, missing XML, or divergent format becomes pending/exception, not success.
  6. Corrections and credit notes use native Odoo document types and retain an explicit link to the original invoice. Accountify never edits a delivered structured artifact in place.

An access-point done state is transport evidence, not proof that the recipient accepted the commercial or tax treatment. Any later rejection/dispute remains a separate workflow.

Accountify API and projection contract

GET  /api/v1/tenants/{tenant_id}/e-invoicing/capabilities
GET  /api/v1/tenants/{tenant_id}/e-invoicing/documents
GET  /api/v1/tenants/{tenant_id}/e-invoicing/documents/{document_id}
POST /api/v1/operations/tenants/{tenant_id}/e-invoicing/capability-scans
POST /api/v1/operations/tenants/{tenant_id}/e-invoicing/documents/{document_id}/refresh

The first implementation exposes status and operations controls; it does not expose arbitrary send/retry. A later outbound command requires its own OpenAPI operation, authorization, idempotency, clone proof, and readback acceptance.

Each einvoice_document_summary contains:

  • tenant, connection, company, Odoo move ID, move type, state, write_date, and local resource version;
  • direction, structured format, transport, source/destination endpoint hash, and message UUID where available;
  • structured attachment ID, filename, SHA-256, immutable object-storage evidence reference when policy permits, and parse/validation result;
  • invoice number/reference, issue date, partner ID, currency, untaxed/tax/total amounts as decimal strings;
  • transport state, observed timestamps, last successful sync, exception code, and AP/AR work-item link; and
  • no private key, API token, raw endpoint credential, or unrestricted attachment URL.

Projection rows are rebuildable. Odoo and the original structured artifact remain authoritative. A document key is scoped by (tenant_id, connection_id, company_id, odoo_move_id); message UUID, supplier reference, or attachment hash alone is not globally unique.

Deduplication and evidence

Inbound duplicate detection combines, where available:

  • tenant/company and supplier identity;
  • structured invoice ID and type;
  • issue date and currency/amount;
  • Peppol message UUID;
  • original structured attachment SHA-256; and
  • existing Odoo duplicate indicators and vendor bill reference.

Hash equality is strong duplicate evidence but not the only rule. A corrected invoice may reuse commercial references with different structured content; conversely, equivalent XML can serialize differently. Suspected duplicates are quarantined for review and are never silently discarded.

At minimum retain the original structured part unaltered, its hash, receipt/send timestamps, route/status evidence, Odoo record identity, and correction relationships. The BMF FAQ currently states an eight-year VAT retention period and requires the structured part to remain intact in its original form. The approved retention policy must also account for GoBD, commercial-law, litigation-hold, privacy, and client-contract requirements.

Failure and status policy

Condition Classification Required action
Company not registered to receive capability_blocked Correct Odoo registration; do not claim tenant readiness
Counterparty not found or cannot receive selected format recipient_invalid Verify endpoint and agree another lawful route/format
Odoo state ready, to_send, or processing pending Poll with bounded backoff; show age and next check
Odoo state error delivery_failed Preserve safe error, open work item, correct, and use approved retry
Timeout during a future automated send unknown Read invoice/message state before any redelivery
Missing or changed structured attachment evidence_invalid Block completion and investigate drift
XML validation or business-rule failure document_invalid Quarantine; do not downgrade silently to PDF
Structured data differs from rendered representation content_mismatch Treat structured data as authoritative and require review

Acceptance and rollout

Before enabling a company in production, run and retain evidence for:

  1. A valid inbound XRechnung and ZUGFeRD fixture, including structured-field extraction and original-file retrieval.
  2. An invalid XML/profile and missing-required-field fixture that is quarantined.
  3. Duplicate delivery and corrected invoice/credit-note cases.
  4. A valid outbound invoice to a controlled recipient, including generated XML, transport status, and recipient endpoint verification.
  5. Wrong endpoint, unsupported format, access-point error, delayed processing, and timeout/readback cases.
  6. Multi-company isolation, role restrictions, attachment authorization, redaction, and cross-tenant negative tests.
  7. Database clone/provider migration without accidental production Peppol registration.
  8. Retention retrieval and integrity verification from the authoritative store and any approved evidence copy.

Roll out through non-production fixture tests, one controlled company with manual send/review, a monitored cohort, and only then broader tenant enablement. Automate ordinary routing only after measured evidence shows no unexplained loss, duplicate posting, or status misclassification.

Source register