Sending Peppol documents in France for your own company
Getting started with Peppol e-invoicing for your own French company: register and verify the company, send French UBL, CII or Factur-X invoices, report B2C and cross-border sales, go live. French UBL, CII and Factur-X on a French-accredited access point, with a signed mandate and its own regulated process.
This guide walks through everything needed to exchange Peppol documents for a company registered in France, assuming you are setting up your own French company, and that the company only sends documents over Peppol. Change any of the three answers at the top of the page to get the guide for a different situation.
What you are setting up
You are putting one company, your own or one you represent, on the Peppol network, so it can exchange invoices electronically with its customers and suppliers.
The setup is a one-time affair: registering the company and getting it verified takes a few minutes in the Recommand dashboard, and there is nothing to gain from automating something you do once. What you do integrate is the part that repeats: sending and receiving documents. Our existing integrations can also connect Recommand to accounting or invoicing software you already use, with no code at all.
A single team can hold several companies at no extra cost, useful if you run more than one legal entity, and the document volume of all of them counts towards one plan.
Onboarding companies that are not yours?
If you are building e-invoicing or Peppol integration into a product for your own customers, and will be registering their companies rather than only your own, switch the first answer above to Many companies. The API is the same; what changes is how companies, verification and billing are organised.
Peppol in France
French domestic e-invoicing follows the French e-invoicing reform rather than plain Peppol BIS 3. Recommand covers the French specifics for you, but they do change what you send and how a company is onboarded.
What is specific to France:
- A French-accredited access point and SMP. Companies you register with
country
FRare automatically published on a French-accredited SMP and exchange documents through the matching access point. You do not choose or configure this: it follows from the company's country. - A signed mandate. Before a French company can operate, its authorised representative signs a mandate that lets that accredited platform act for the company, and the file is reviewed before the company goes live. This is the one step in this guide that is not instant, so start it early.
- French document formats. Invoices and credit notes travel as French CIUS or Extended UBL, CII D22B (CIUS or Extended), or Factur-X (a PDF/A-3 with the CII XML embedded), next to plain Peppol BIS 3 UBL.
- Two processes. The same document types are published for a regulated
process (
urn:peppol:france:billing:regulated, transactions inside the French e-invoicing perimeter) and a non-regulated one (urn:peppol:france:billing:non-regulated, transactions outside it). - Mandatory content. French invoices carry a billing mode and three
statements (recovery costs, late-payment penalties, early-payment discount)
that plain EN 16931 does not require. They go in a
countrySpecificblock. - Lifecycle statuses. Inside the perimeter, receivers report back on the invoices they receive with an invoice lifecycle status.
- E-reporting. What falls outside the e-invoicing perimeter is reported instead: B2C sales as daily totals, and invoices to businesses abroad one by one. Recommand files both report types on the company's behalf.
- Identifiers are SIREN-based. French companies are published under scheme
0225.
Dates and legal scope
The reform phases the obligations in over time: from 1 September 2026 every company must be able to receive electronic invoices, with issuance starting for large and mid-size companies, and from 1 September 2027 issuance applies to small and micro companies as well. Confirm the schedule and what falls inside the perimeter with your accountant or legal advisor. This documentation describes what the API does, not what your obligations are.
Create your account and API credentials
- Sign up at app.recommand.eu/signup.
- Your account starts with a team. The team holds your company, your subscription and your document history, and you can invite colleagues to it.
- Create an API key on the API keys page. Note the key, the secret and your team ID.
- Check the credentials with a request that needs no data of its own:
curl -X GET https://app.recommand.eu/api/core/auth/verify \
-u key_xxx:secret_xxxIt answers {"success": true} when the key and secret are accepted, and 401
when they are not, so it tells you about your credentials and nothing else.
All endpoints in this guide live under https://app.recommand.eu/api/v1 and
accept HTTP Basic authentication with the key as username and the secret as
password. If you would rather not store a long-lived secret, JWT API keys and
OAuth2 with a JWT assertion are available too, see the
authentication guide.
Not planning to write any code?
Sending and receiving can also be driven entirely from the dashboard or through an integration, and each section below says how. The dashboard is available in English, Dutch, French and German; pick your language on the account page.
Try it safely first
You do not have to get anything right the first time. Everything below, adding the company, registering it, sending and receiving, can be done in a playground team first, where nothing is delivered over the real Peppol network, nothing is registered on it, and nothing is billed.
Open the team switcher at the top of the dashboard and pick Add playground. Give it a name, leave the Peppol Test Network box unticked, and you are switched into the new team straight away. There is nothing to set up beyond that.
Add a company to that team and use it as both sender and recipient to watch a document travel end to end. When the flow does what you want, repeat it once in your real team.
Two things worth knowing before you start:
POST /:companyId/generatetakes the same body as the send endpoint minus the email delivery options, which have no meaning when nothing is delivered, and returns the exact XML that sending would produce, fully validated, without transmitting, storing or billing it. Raw XML is not accepted here: there is nothing to generate from a document you already have. It also returns the resolveddocumentType,doctypeIdandprocessId.- Failure addresses. In a playground that is not connected to the Peppol Test
Network, sending to
404:404or0208:1234567894always fails, so you can exercise your error handling. Any other unregistered recipient is skipped without an error.
A playground stays useful after you are live, too: it is the safest place to try a new invoice layout or a new integration. See how can I test without sending real invoices.
Playgrounds are separate
Playground companies are not registered on the Peppol network and playground documents never leave it, so nothing you do there affects your real company.
Register the company
You are registering one company, once, so the dashboard is the shortest path.
- Open Companies and start the company wizard.
- Fill in the legal name, address and country, plus the identifiers described in the next section.
- Choose whether the company should also receive documents over Peppol, or only send them.
- Save. The company is registered on the Peppol network as part of this step: its identifiers and the document types for its country are set up for you.
Right after saving, the dashboard offers the verification step, which the section below covers. Note the company's ID from its detail page. Every API call for sending and receiving takes it in the path.
Rather create it from code?
The create company endpoint does exactly
the same thing, and returns the company id and a verificationUrl in one
response. It is worth using when company creation is part of a flow you are
automating, which is likely the case if you are registering many companies.
Switch the first answer above to Many companies for that version.
More than one entity?
Add each legal entity as its own company: run the wizard again. There is no per-company fee, and all of them share your document volume.
French identifiers and Peppol address
In France the identifier you register decides whether your documents will pass validation later, so it is worth getting exactly right.
| Field | French value |
|---|---|
country | "FR" |
enterpriseNumber | The nine-digit SIREN of the company |
enterpriseNumberScheme | "0002" |
vatNumber | FR + the French VAT number |
{
"name": "Société de Test SAS",
"address": "10 rue de la Paix",
"postalCode": "75002",
"city": "Paris",
"country": "FR",
"enterpriseNumber": "133512194",
"enterpriseNumberScheme": "0002",
"vatNumber": "FR23133512194"
}Use the SIREN with scheme 0002
French regulated invoices must carry the seller's nine-digit SIREN as
enterpriseNumber with enterpriseNumberScheme "0002". Because the seller
block of a document defaults to the company's own details, a company registered
with a SIRET or without the scheme produces invoices that are rejected at
validation time. Register the SIREN, and name a specific establishment through
the document's delivery.locationIdentifier (scheme 0009) when you need to.
One Peppol identifier is registered for the company:
0225:133512194is the French electronic address
The company's Peppol address is therefore 0225: followed by the SIREN.
French addresses may also carry a routing suffix, as in
0225:987654321_STATUTS; treat the whole string after the scheme as the
identifier when a recipient gives you one.
Both SIREN (9 digits) and SIRET (14 digits) are checked with the Luhn algorithm before they are filed, and numbers that disagree with each other are refused rather than guessed at.
Registering for sending only
Because you are only looking to send invoices or other documents, register the company without recipient registration:
set isSmpRecipient to false (or leave the checkbox unticked in the
dashboard).
{
"isSmpRecipient": false
}What that means:
- The company is not published as a recipient on an SMP, so nothing is delivered to it over Peppol through your integration.
- Registration succeeds even when the company already receives its documents through another Peppol provider. The other Peppol provider will remain in charge for processing received documents for this company.
- Nothing changes for sending: outgoing documents leave through the access point as normal.
Adding receiving later
You can flip isSmpRecipient to true on an existing company at any time.
Recommand then publishes it as a recipient and registers the document types for
its country. That registration is exclusive, so the company has to be
deregistered at its current provider first.
Sign the mandate and verify the company
French companies go through the same identity check as everyone else, plus two steps that are specific to France: the representative signs a mandate, and the resulting file is reviewed before the company goes live.
- Open the verification URL (from the create-company response, the dashboard, or a fresh one from the verify company endpoint).
- Read and sign the mandate. The verification page shows the mandate that authorises the French-accredited platform to act for the company on the Peppol network, naming the company by its SIREN and the establishment it is filed under. The representative accepts it before the identity check starts.
- Complete the identity check. The identity verification is what signs the mandate: the proof reference is recorded on it.
- Wait for the review. The signed mandate and the company's details are filed
with the accredited platform, and the verification sits in review until that
file is accepted. Only then does
isVerifiedbecometrueand the company start operating.
In some cases manual verification by our team will be required.
If that's the case, isVerified will remain false until this manual verification is completed.
The user is informed of this in the verification process.
Plan the review in
This is the one step of French onboarding that is not immediate. Start verification as soon as the company is created, and do not promise your users a same-minute go-live for France. If a file seems stuck, mail support@recommand.eu with the company ID.
Playgrounds skip the mandate
Companies in a playground team are never filed with the accredited platform, so there is no mandate and no review. Test the French flow in a playground first, then run the real thing once.
Verifying once, in the dashboard
You have one company, and it is verified once. There is nothing here worth automating: open Companies in the dashboard, pick the company and start verification. If you are authorised to act for the company, complete the check yourself; otherwise use the button to forward the link to whoever is.
The page is self-contained and works in any browser. The person completing it does not need a Recommand account.
That is the whole step. From here on the API takes over: sending and receiving documents is what you actually integrate.
Changing identifiers resets verification
Updating the company's vatNumber or enterpriseNumber sets isVerified back
to false, and the company has to be verified again before it can exchange
documents.
Pick the French document format and process
A French invoice needs three decisions: the format, the process, and the mandatory French content.
The format
Name the format with doctypeId on the send request. Leave it off and the
recipient is looked up and the document written in the first format, in our
order of
preference, they are
registered to receive. Peppol BIS 3 UBL comes first in that order, so a French
recipient who publishes it as well receives plain BIS 3: valid on the network,
but not what the French reform asks for inside its perimeter. Name the French
format you want for transactions inside the perimeter.
| Format | doctypeId |
|---|---|
| France UBL CIUS invoice | urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:peppol:france:billing:cius:1.0::2.1 |
| France UBL CIUS credit note | urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:peppol:france:billing:cius:1.0::2.1 |
| France UBL Extended invoice | urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#conformant#urn:peppol:france:billing:extended:1.0::2.1 |
| France CII CIUS | urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#compliant#urn:peppol:france:billing:cius:1.0::D22B |
| France CII Extended | urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100::CrossIndustryInvoice##urn:cen.eu:en16931:2017#conformant#urn:peppol:france:billing:extended:1.0::D22B |
| France Factur-X | urn:peppol:doctype:pdf+xml##urn:cen.eu:en16931:2017#conformant#urn:peppol:france:billing:Factur-X:1.0::D22B |
The CII and Factur-X document types carry both invoices and credit notes; the
documentType field of your request decides which one it is.
Start with France UBL CIUS unless you have a reason not to. Extended is for data the CIUS does not carry, and Factur-X is for recipients who want a human-readable PDF as the carrier.
The process
Set countrySpecific.businessProcess to say which side of the French perimeter
the transaction is on. The document is then sent over the matching process:
businessProcess | Process identifier | Use for |
|---|---|---|
REGULATED (default) | urn:peppol:france:billing:regulated | Transactions inside the French perimeter |
NON_REGULATED | urn:peppol:france:billing:non-regulated | Transactions outside it |
The recipient must have registered the document type for that process. Pass
the processId to the verify document support
endpoint to check exactly that
combination rather than "any process".
The mandatory French content
French UBL, CII and Factur-X require a countrySpecific block with the billing
mode and the three statements French invoices must carry. It is required for those
document types and must be omitted for plain EN 16931 documents.
{
"countrySpecific": {
"country": "FR",
"billingMode": "S1",
"businessProcess": "REGULATED",
"recoveryCostsNote": "Indemnité forfaitaire de 40 EUR pour frais de recouvrement.",
"latePaymentPenaltiesNote": "Pénalités de retard exigibles au taux prévu dans les conditions générales de vente.",
"earlyPaymentDiscountNote": "Aucun escompte accordé pour paiement anticipé."
}
}billingMode follows AFNOR XP Z12-012. The common ones are B1 (goods), S1
(services) and M1 (mixed); the full list, including already-paid, advance
payment, subcontracting and multi-seller variants, is documented on the send
document endpoint.
Invoicing outside France
The French formats and processes are for the French perimeter. A counterparty in another country is registered for the standard Peppol billing process, so a regulated document does not match anything they published.
For those invoices, send plain Peppol BIS 3 UBL and leave
the countrySpecific block out with it, it belongs to the French document types
only. The rest of the invoice is unchanged.
Three rules that reject a French invoice
- The seller's
enterpriseNumbermust be the nine-digit SIREN withenterpriseNumberScheme"0002". - The currency must be
EUR. - Factur-X needs a compliant PDF/A-3 to embed the XML in: either attach one as an embedded
attachment, or let Recommand generate it with
pdfGeneration.enabled.
Send a document
One endpoint sends everything: POST /:companyId/send. The companyId is the
sender, recipient is the Peppol address of the receiver, and document is the
invoice or credit note as JSON. Recommand will validate the document and generate the XML.
Already producing UBL or CII XML?
Raw XML sending is supported as well: set documentType to xml and pass the
document string in document, along with the correct doctypeId. See working
with raw UBL.
curl -X POST https://app.recommand.eu/api/v1/{companyId}/send \
-u key_xxx:secret_xxx \
-H "Content-Type: application/json" \
-d @send-invoice.json{
"recipient": "0208:0123456789",
"documentType": "invoice",
"document": {
"invoiceNumber": "INV-2026-001",
"issueDate": "2026-08-17",
"dueDate": "2026-09-16",
"currency": "EUR",
"buyer": {
"name": "Customer Company",
"street": "Customer Street 1",
"city": "Antwerp",
"postalZone": "2000",
"country": "BE",
"vatNumber": "BE0987654321"
},
"paymentMeans": [{ "iban": "BE68539007547034" }],
"lines": [
{
"name": "Consulting Services",
"quantity": "10.00",
"unitCode": "HUR",
"netPriceAmount": "100.00",
"vat": { "category": "S", "percentage": "21.00" }
}
]
}
}The seller block is filled in from your company when you leave it out, which is usually what you want: it keeps your registered identifiers and the document in agreement. The full field reference lives in sending invoices and sending credit notes.
Worth wiring up while you are here:
- Validation errors. Outgoing documents are always validated. A
success: falseresponse witherrorskeyed by field path is a document the recipient would have rejected. Surface it wherever the data was typed. - Email fallback. Pass
email.towithwhen: "on_peppol_failure"to fall back to email when a recipient turns out not to be reachable over Peppol, or send withrecipient: nullfor email-only delivery. See email delivery and notifications. - PDFs.
pdfGeneration.enabledattaches a generated PDF of the document. You can also attach an existing PDF (or other files) viaattachments; see adding attachments.
For a full field reference, see sending invoices and sending credit notes.
Sending without writing code
The same send is available two other ways, and they mix freely with the API:
- From the dashboard. Send document takes the recipient and the invoice lines, previews what the recipient will get, and remembers your usual settings. You can also drop an existing UBL or CII XML file into the upload zone if your software already produces one.
- From your accounting or invoicing software. If you use one of the supported tools, let it do the work: your invoices flow to Recommand and out over Peppol without retyping. See integrations for the current list, including Microsoft Business Central, Exact Online, Yuki, ClearFacts, ERPNext and Harvest.
Every outgoing document is validated
Whichever route you use, Recommand validates a document before it leaves. If a field is missing or malformed you get a clear error instead of a rejection from the recipient days later. See the troubleshooting guide for the errors you are most likely to run into.
French e-reporting
French e-invoicing covers invoices between businesses established in France. Everything else a French company sells still has to reach the tax administration: sales to private individuals, and invoices to businesses outside France. That is e-reporting. You send Recommand the figures, and Recommand files them on the company's behalf. You never build a regulatory file yourself.
B2C reports contain daily totals. Cross-border reports describe an individual invoice or credit note, or a payment received on an invoice.
| Report | Endpoint (under /api/v1) | type | Scope |
|---|---|---|---|
| B2C sales | POST /:companyId/reporting/fr/b2c | sales | Sales for one day, category and currency |
| B2C payments | POST /:companyId/reporting/fr/b2c | payments | Payments received for one day and currency, grouped by VAT rate |
| Cross-border invoice | POST /:companyId/reporting/fr/b2bi | invoice | One invoice or credit note issued to a business outside France |
| Cross-border payment | POST /:companyId/reporting/fr/b2bi | payment | A payment received on a previously reported invoice |
All reports are submitted per company, through the API only. Every accepted report is stored with the company's other documents and counts towards the document quota.
Register the company first
E-reporting has to be switched on per company, because the tax administration
needs to know two things about the taxpayer before its first report: its VAT
regime, which sets how often reports are filed, and whether its VAT becomes due
on invoicing or on payment. Register the company once through
PUT /:companyId/reporting/fr/declarant,
or from the company page in the dashboard.
{
"vatRegime": "REEL_NORMAL_MENSUEL",
"vatExigibility": "DEBITS"
}| Field | Values |
|---|---|
vatRegime | REEL_NORMAL_MENSUEL (régime réel normal), REEL_SIMPLIFIE (régime réel simplifié), FRANCHISE_EN_BASE (franchise en base de TVA) |
vatExigibility | DEBITS (VAT due on invoicing, typical for goods), ENCAISSEMENTS (VAT due on payment, typical for services) |
The company must be registered in France with a valid SIREN or SIRET, and it must be verified with a signed French mandate whose annex covers e-reporting. That annex is what entitles Recommand to report for the SIREN. A company that was verified without one is refused with a 400; contact support@recommand.eu to have e-reporting enabled for it.
The response carries a state. Reports are accepted once it is registered;
pending means the registration is still being completed in the background, and
blocked means support has to intervene, for example because the company is
already registered for e-reporting through another platform.
It also carries enabled. A suspended registration keeps its registered
state but refuses every report with a 400 until support switches it back on, so
check both fields when reports start being refused.
Registration starts the clock
Registering makes the company's reporting periods due. Only register companies that will submit reports, and submit each day's figures promptly rather than at month end. Changing the VAT regime later can leave the open period unfiled, so coordinate such a change with support.
Report B2C sales
Submit one sales report per day, per category and per currency through
POST /:companyId/reporting/fr/b2c,
regardless of when customers pay.
{
"reference": "B2C-SALES-2026-08-17-GOODS",
"type": "sales",
"date": "2026-08-17",
"category": "goods",
"currency": "EUR",
"taxExclusiveAmount": "10000.00",
"taxAmount": "2000.00",
"transactionCount": 42,
"vatBreakdown": [
{ "percentage": "20.00", "taxableAmount": "10000.00", "taxAmount": "2000.00" }
]
}categoryisgoodsorservices; use a separate report when both were sold on the same day. Only taxable goods and taxable services are supported today, so exempt B2C sales have no report type yet.- Amounts are strings with two decimals and are never negative. VAT amounts are always in EUR, even when the sales currency is different.
transactionCountis the number of individual sales in the total. It is at least 1: a day without sales is not reported at all.
Report B2C payments
For service payments where VAT becomes due on payment, submit the daily amounts
received through the same B2C endpoint with type: "payments". Group the amounts
including VAT by VAT rate. Submit the sales report as usual as well.
{
"reference": "B2C-PAYMENTS-2026-08-17-EUR",
"type": "payments",
"date": "2026-08-17",
"currency": "EUR",
"vatBreakdown": [
{ "percentage": "20.00", "amount": "1200.00" }
]
}Payment reports are only accepted for companies registered with VAT due on
payment (ENCAISSEMENTS).
Report cross-border invoices
Submit every invoice or credit note issued to a business outside France
through
POST /:companyId/reporting/fr/b2bi.
An invoice to a French buyer is exchanged over the e-invoicing network instead
and is refused here.
Set documentType to invoice or creditNote to say which of the two you are
reporting. It defaults to invoice, so you only have to name it for credit
notes.
The reporting company must carry its own French VAT number as well as its SIREN: a cross-border report identifies the seller by both. Add the VAT number to the company before its first cross-border report.
{
"reference": "EREPORT-INV-2026-000431",
"type": "invoice",
"documentNumber": "INV-2026-000431",
"issueDate": "2026-01-15",
"currency": "EUR",
"buyer": {
"name": "Rossi Forniture S.r.l.",
"country": "IT",
"vatNumber": "IT00987654321"
},
"taxExclusiveAmount": "10000.00",
"taxAmount": "0.00",
"vatBreakdown": [
{
"percentage": "0.00",
"taxableAmount": "10000.00",
"taxAmount": "0.00",
"category": "K",
"exemptionReasonCode": "VATEX-EU-IC"
}
]
}The buyer is identified the way the tax administration identifies foreign businesses:
- In the European Union: by its intra-community VAT number, which is required.
- Outside the European Union: by its country and name; no VAT number is needed.
- In Nouvelle-Calédonie or Polynésie française: by its local registration
number (RIDET or TAHITI), in
enterpriseNumber.
Cross-border operations are usually exempt or reverse charged rather than
taxed. When a VAT breakdown entry uses an exempt category, name why: give
exemptionReason, exemptionReasonCode, or both. A breakdown that leaves both
off on an exempt category is refused.
Report a cross-border payment
Submit a payment received on a previously reported invoice through the same
cross-border endpoint with type: "payment". Set invoiceNumber to the original
report's documentNumber and issueDate to the invoice date. The date field
is the day the payment was received.
For a payment of EUR 10,000 on the invoice above:
{
"reference": "EREPORT-PAYMENT-2026-000431-1",
"type": "payment",
"invoiceNumber": "INV-2026-000431",
"issueDate": "2026-01-15",
"date": "2026-02-10",
"currency": "EUR",
"vatBreakdown": [
{ "percentage": "0.00", "amount": "10000.00" }
]
}Amounts include VAT and are grouped by VAT rate. As with B2C payments, payment
reports are only accepted for companies registered with VAT due on payment
(ENCAISSEMENTS).
References, retries, corrections
Every report needs its own reference, at most 128 characters. It is your
idempotency key: retrying the exact same request with the same reference
returns the report filed the first time, with duplicate: true, and files
nothing again. Use this after a timeout or a 502.
To change a report you already filed, send a new report with a new
reference and the action field:
action: "correct"replaces the earlier report. It is matched on the data that identifies the report: the day, category and currency of a B2C sales report, the day of a B2C payment report, or the document number of a cross-border invoice.action: "cancel"withdraws it, matched the same way.
Reusing the original reference for a correction would be treated as a retry of the original report, and nothing would change.
When a report is refused
Submitting a report can fail for reasons that have nothing to do with the figures, so handle each status separately rather than treating any non-200 as bad data.
| Status | What happened | What to do |
|---|---|---|
| 400 | The company is not registered for e-reporting, its registration is still pending or blocked, or it is suspended (enabled: false) | Register it, or wait for the state to become registered. A blocked or suspended registration needs support |
| 400 | The reporting service refused the report; the reason is in the message | Fix what the message names and submit again under a new reference |
| 400 | A payment report was sent for a company whose VAT is due on invoicing (DEBITS), or a cross-border report named a French buyer | Neither is reportable. A French buyer is invoiced over the e-invoicing network instead |
| 409 | The report conflicts with what was already filed, for example a correction of something that was never reported | Look at what is on file before resubmitting |
| 502 | The reporting service could not be reached | Retry later with the same reference. The reference is the idempotency key, so a retry cannot file the report twice |
The 502 case is the one worth building for: it is the only status where reusing the reference is right. Every other failure needs a fresh reference once you have fixed the cause.
Follow the report until it is filed
Accepting a report is not filing it. The tax administration receives a filing
per reporting period, assembled after the period ends, and can still reject
it. Every report you submit therefore carries a reporting block in the
documents API, which Recommand keeps up
to date:
reportingStatus | Meaning |
|---|---|
accepted | On file, inside its reporting period. Not yet filed. |
pending_rectificative | Arrived after its period was already filed; it will be carried by a corrective filing. |
filed | Reported to the tax administration within its own period. |
filed_rectificative | Reported by a corrective filing, because it arrived late. |
superseded | Replaced by a later correction, or cancelled. |
rejected | The tax administration rejected the filing carrying it; see outcomeCode. |
The block also names the reporting period (periodStart, periodEnd), the
filing the report was carried on (submissionId) and when the status was last
checked. Every change fires a document.reporting_status_changed webhook
event, so you can route rejections to whoever handles them.
Playground and test network
Reports from playground teams and teams on the test network are validated,
recorded and shown exactly like real ones, but they are never filed with the
tax administration. Their status stays accepted and is marked as simulated.
Use them to build the integration; use a production team to file.
Registration is immediate there: it comes back registered straight away
rather than going through pending, so you can submit reports as soon as you
have registered. Registrations are also kept per environment. A team on the
test network registers in TEST, a production team in PROD, and the two are
separate registrations for the same company. The environment field on the
registration response says which one you are looking at.
Going live
A short list before you start sending or receiving real invoices:
- A valid subscription, so sending is not blocked. Playgrounds skip that check; production does not.
- The company verified, with
isVerifiedtrue. Until then it cannot exchange documents. - Errors surfaced, not swallowed. Validation errors name the field that is wrong; put that in front of whoever can fix it rather than logging it.
- Webhook endpoint hardened, if you took that route: signature verification, a fast 200, retries and idempotency on your side.
- One real document sent and received, ideally between two companies you control, so you have seen both ends.
- Notification addresses set, so incoming documents also reach a mailbox somebody reads.
Tell your customers and suppliers
Once you are live, your Peppol address is public on the network: suppliers can find and reach you without any action from you. Ask customers who still email PDFs to switch, and let your accountant know where the documents now land.
Before you go live in France
France adds a few checks to the list above, all of them things that only show up once real documents move:
- The mandate is accepted.
isVerifiedistrue, which for a French company means the signed mandate cleared its review. Plan this in: it is the one step that is not instant. - The company carries the SIREN under scheme
0002. Both the documents you send and the mandate itself are built from the company's own identifiers, so a SIRET or a missing scheme surfaces as rejected documents rather than as a registration error. - You know which side of the perimeter you are on. Regulated is the default; transactions outside it have to say so explicitly, and the counterparty has to be registered for the process you use.
If the company sends documents, two more:
- The format and process are what you meant. Check one document before the
first real send: the preview in the dashboard, or
generatefrom the API, shows the resolveddoctypeIdandprocessId. - Invoices are in EUR, with the billing mode and the three mandatory statements filled in.
Selling to consumers or abroad as well?
B2B invoices are only half of the French obligation. If the company also sells to private individuals, or invoices businesses outside France, those operations have to be reported to the tax administration separately. Register the company for e-reporting and submit the reports through the API, as described in the e-reporting section of the French sending guides.
Where to get help
- Troubleshooting. Common rejections, delivery failures and validation errors are collected in the troubleshooting guide.
- Questions. The FAQ covers Peppol, addressing, VAT and billing.
- Email. support@recommand.eu:include the company ID and, for a delivery problem, the document ID.
- Discord. Join the server for release announcements and quick questions.
- Keep track of changes. New endpoints and behaviour are recorded in the changelog.
Other guides for France
- Sending Peppol documents in France for the companies you onboard
- Receiving Peppol documents in France for the companies you onboard
- Sending and receiving Peppol documents in France for the companies you onboard
- Receiving Peppol documents in France for your own company
- Sending and receiving Peppol documents in France for your own company