France ๐ซ๐ท
Chorus Pro integration and upcoming B2B mandate for France.
Overviewโ
| Aspect | Details |
|---|---|
| B2G Mandate | Required since 2020 (via Chorus Pro) |
| B2B Mandate | 2026-2027 (phased) |
| CIUS | Factur-X (EN16931 hybrid PDF/XML) |
| Primary Scheme | 0009 (SIRET) |
| Government Portal | Chorus Pro |
France is implementing mandatory B2B e-invoicing:
- September 2026: Large enterprises
- September 2027: SMEs and micro-enterprises
All B2B invoices must go through certified platforms (PDP).
Identifier Schemesโ
SIRET (0009) โ Standardโ
The 14-digit establishment identifier:
# Format: 14 digits (SIREN + NIC)
participant = {
"scheme": "0009",
"identifier": "12345678901234",
"name": "Exemple SARL",
"country": "FR"
}
Structure:
- First 9 digits: SIREN (company ID)
- Last 5 digits: NIC (establishment code)
Validation:
def validate_siret(siret: str) -> bool:
"""Validate French SIRET using Luhn algorithm."""
if len(siret) != 14 or not siret.isdigit():
return False
total = 0
for i, digit in enumerate(siret):
d = int(digit)
if i % 2 == 0:
d *= 2
if d > 9:
d -= 9
total += d
return total % 10 == 0
SIREN (0002)โ
The 9-digit company identifier (less common):
participant = {
"scheme": "0002",
"identifier": "123456789",
"name": "Exemple SA",
"country": "FR"
}
VAT Number (9957)โ
For cross-border B2B:
# Format: FR + 2 digits + 9 digits (SIREN)
participant = {
"scheme": "9957",
"identifier": "FR12123456789",
"name": "Exemple SAS",
"country": "FR"
}
Chorus Pro (B2G)โ
Overviewโ
All B2G invoices must go through Chorus Pro:
Supplier โ GoRoute (Peppol) โ AIFE/Chorus Pro โ Government Entity
Chorus Pro Integrationโ
GoRoute connects to Chorus Pro via Peppol for seamless delivery:
# Send to French government
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/documents",
headers={
"X-API-Key": "your_api_key",
"Content-Type": "application/json"
},
json={
"sender_scheme": "0009",
"sender_id": "12345678901234",
"receiver_scheme": "0009",
"receiver_id": "13002526500013", # Example ministry
"document": invoice_xml
}
)
The request body is flat - there are no nested sender or receiver objects - and
document is the UBL XML as a plain string, not base64. sender_scheme and sender_id are
optional and default to your organization. A successful send returns 202 Accepted.
Required Fields for Chorus Proโ
<Invoice>
<!-- Service code (Code Service) - often required -->
<cbc:BuyerReference>CODE_SERVICE_12345</cbc:BuyerReference>
<!-- Engagement juridique (Commitment number) -->
<cac:OrderReference>
<cbc:ID>EJ-2024-00123</cbc:ID>
</cac:OrderReference>
<!-- SIRET of sender -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0009">12345678901234</cbc:EndpointID>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- SIRET of government receiver -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0009">13002526500013</cbc:EndpointID>
</cac:Party>
</cac:AccountingCustomerParty>
</Invoice>
Service Codesโ
Many French public entities require a "Code Service":
<cbc:BuyerReference>SERVICE_COMPTABILITE</cbc:BuyerReference>
Look up valid codes in the Annuaire Chorus Pro.
Factur-X Formatโ
Factur-X is France's hybrid e-invoice format (PDF + embedded XML):
Profilesโ
| Profile | Use Case |
|---|---|
| Minimum | Basic PDF, minimal data |
| Basic WL | Simple invoices |
| Basic | Standard B2B |
| EN16931 | Full EN16931 compliance |
| Extended | Maximum data |
Factur-X and the GoRoute APIโ
Earlier revisions of this page carried a code sample that posted a base64 Factur-X PDF to a
send path directly under /api/v1, using format and profile request fields. That path
has never existed and neither field appears in the send request schema, so the sample has
been removed rather than corrected onto the real endpoint.
What the API accepts today is a UBL document as a string in the document field of
POST /api/v1/documents, described above. Whether a Factur-X PDF can be submitted through
GoRoute, and by what route, is not something the API surface answers, and it is not
documented here until it can be traced to the product.
VAT Requirementsโ
French VAT Formatโ
# French VAT: FR + 2 key digits + 9-digit SIREN
def validate_french_vat(vat: str) -> bool:
if not vat.startswith("FR"):
return False
if len(vat) != 13:
return False
key = vat[2:4]
siren = vat[4:]
if not siren.isdigit():
return False
return True
VAT Ratesโ
| Code | Rate | Description |
|---|---|---|
| S | 20% | Standard rate |
| AA | 10% | Intermediate reduced |
| H | 5.5% | Reduced (essential goods) |
| I | 2.1% | Super-reduced |
| Z | 0% | Zero rate |
| E | 0% | Exempt |
Example Invoiceโ
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>FR-FACT-2024-00123</cbc:ID>
<cbc:IssueDate>2024-01-15</cbc:IssueDate>
<cbc:DueDate>2024-02-15</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<!-- Code Service for Chorus Pro -->
<cbc:BuyerReference>CODE_SERVICE_COMPTABILITE</cbc:BuyerReference>
<!-- French Seller -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0009">12345678901234</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Exemple SARL</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>123 Rue de la Rรฉpublique</cbc:StreetName>
<cbc:CityName>Paris</cbc:CityName>
<cbc:PostalZone>75001</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>FR</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>FR12123456789</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Exemple SARL</cbc:RegistrationName>
<cbc:CompanyID schemeID="0009">12345678901234</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- French Government Buyer -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0009">13002526500013</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Ministรจre de l'รconomie</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>139 Rue de Bercy</cbc:StreetName>
<cbc:CityName>Paris</cbc:CityName>
<cbc:PostalZone>75012</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>FR</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Ministรจre de l'รconomie</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
<cac:PayeeFinancialAccount>
<cbc:ID>FR7630004000031234567890143</cbc:ID>
<cbc:Name>Exemple SARL</cbc:Name>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">20.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">100.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">20.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>20</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">100.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">120.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="EUR">120.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Services de conseil</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>20</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">10.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
B2B Mandate Preparationโ
Certified Platforms (PDP)โ
Starting 2026, B2B invoices must go through:
- Portail Public de Facturation (PPF) - Government platform
- Plateformes de Dรฉmatรฉrialisation Partenaires (PDP) - Certified providers
GoRoute is positioned to integrate with these platforms.
Reporting Requirementsโ
New e-reporting obligations:
- E-invoicing: B2B domestic invoices
- E-reporting: International B2B + B2C summary
Timelineโ
| Date | Requirement |
|---|---|
| Sept 2026 | Large enterprises must send/receive |
| Sept 2027 | All businesses must send/receive |
Resourcesโ
Next Stepsโ
Further readingโ
- The 2026 French mandate
- France overview
- 2026 e-invoicing mandate tracker โ every country, one page
- How to choose a Peppol Access Point
- One API for multi-country e-invoicing
Ready to build? The free developer sandbox gives you test credentials and a registered participant, provisioned within 24 hours on business days. Recorded ERP integration walkthroughs are on the tutorials page.