France - Recipient Identifiers & Routing

Which French identifiers eezi accepts in recipient.taxId and recipient.customInfo.fra, and how the four-step Annuaire lookup resolves the 0225 Peppol endpoint ID.

You can deliver a French invoice to a legal entity, one of its establishments, or a specific service via a routing code (code de routage) or address suffix (suffixe d'adressage). This page covers which identifiers to send and how eezi resolves them.

📘

Short answer

Put whichever identifier your customer gives you (SIREN, SIRET, or VAT number) into recipient.taxId. eezi works out the routing from there. Got more than one identifier, or a routing code or suffix? Put the extras in recipient.customInfo.fra.

🚨

Change — VAT numbers must now be sent explicitly

From the 1 September 2026 go-live, invoices must carry the VAT number of both sender and recipient whenever the recipient is VAT-registered (French Ministry of Finance / DGFiP decree, published August 2026). VAT status is no longer inferred from the Annuaire (the French national e-invoicing directory), so you must capture the recipient's VAT number from your customer:

  • Recipient - send it in recipient.taxId, or in recipient.customInfo.fra.vatNumber if taxId already holds the SIREN or SIRET.
  • Sender - keep your organisation's VAT number on your eezi organisation profile; eezi adds it to every outgoing document.

The three French identifiers

recipient.taxId accepts any of them:

IdentifierFormatIdentifiesExample
SIREN9 digitsThe legal entity123456789
SIRET14 digits (SIREN + a 5-digit establishment number, the NIC)One establishment of that entity12345678901234
VAT numberFR + 2-char key + SIRENThe legal entity, for VATFR32123456789

They all lead back to the same place: the SIREN is the first nine digits of a SIRET and the last nine of a VAT number. Whichever one your customer has on hand works.

Extra identifiers go in recipient.customInfo.fra

taxId holds one identifier. Anything else your customer gives you goes here:

recipient: {
  taxId: string;            // SIREN, SIRET, or FR VAT number
  customInfo?: {
    fra?: {
      siren?: string;       // deprecated — use recipient.taxId
      siret?: string;       // establishment, when taxId holds the SIREN or VAT number
      vatNumber?: string;   // required if VAT-registered and taxId isn't the VAT number
      routingCode?: string; // "code de routage" (Annuaire: identifiantRoutage) — needs a SIRET
      suffix?: string;      // "suffixe d'adressage" (Annuaire: suffixeAdressage) — a billing channel on the SIREN
    };
  };
};

Two rules worth knowing:

  • One SIREN everywhere. Every identifier on a document must point at the same legal entity. If the SIRENs embedded in taxId, customInfo.fra, or an explicit peppolId.endpointId disagree, the document is rejected before any lookup runs.
  • A routing code needs a SIRET. Without one, the routing code can't form a valid address and is ignored. Routing codes and suffixes exist only if the recipient registered them - use one when your customer provides it, never guess.

The 0225 Peppol endpoint ID convention

Behind the scenes, French recipients are addressed with a 0225 Peppol endpoint ID - the address format used on the Peppol delivery network. It has four forms, from an entire legal entity down to a specific service:

TargetFormatExample
Legal entity0225:{SIREN}0225:123456789
Legal entity + suffix0225:{SIREN}_{Suffix}0225:123456789_billing
Establishment0225:{SIREN}_{SIRET}0225:123456789_12345678901234
Establishment + routing code0225:{SIREN}_{SIRET}_{RoutingCode}0225:123456789_12345678901234_service1

The format is unambiguous: the first segment is always the SIREN; a 14-digit second segment is a SIRET, anything else is a suffix; a third segment can only follow a SIRET and is a routing code.

You never need to build this yourself — eezi assembles it from taxId and customInfo.fra. If you do set recipient.peppolId.endpointId, eezi parses it by this convention and uses its values for routing. customInfo.fra.siret, routingCode, and suffix are then ignored, and taxId is still required either way. vatNumber still applies — it carries VAT information, not routing.

How eezi finds the receiving platform

eezi looks the recipient up on the Annuaire, walking a fixed ladder of four lookups. A suffix outranks even an establishment address, because the buyer configured it deliberately as a billing channel. Each step only runs if its identifiers were provided, and the first step with an active registration wins:

StepLookupRuns whenFinds
1{SIREN}_{Suffix}a suffix is providedA billing channel the buyer set up on the SIREN — SIRET and routing code are ignored here
2{SIREN}_{SIRET}_{RoutingCode}a SIRET + routing code are providedA specific service inside the establishment
3{SIREN}_{SIRET}a SIRET is providedThe establishment itself
4{SIREN}alwaysThe legal entity (the catch-all)

A miss on steps 1–3 is never an error, the walk just falls through. A routing error is raised only when step 4 fails: if the SIREN itself isn't on the Annuaire, the company isn't registered to receive electronic invoices and the document can't be delivered.

Common cases

Rows without a vatNumber assume the recipient is not VAT-registered; if they are, add customInfo.fra.vatNumber or use the VAT number as taxId — the lookups don't change.

Your customer gives yourecipient.taxIdrecipient.customInfo.fra
A VAT numberFR32123456789-
A SIRET12345678901234-
A SIREN123456789-
VAT number + SIRETFR32123456789{ "siret": "12345678901234" }
SIRET + routing code12345678901234{ "routingCode": "service1" }
VAT number + suffixFR32123456789{ "suffix": "billing" }
All of the aboveFR32123456789{ "siret": "…", "routingCode": "…", "suffix": "…" }
A full endpoint IDany of the threeset peppolId.endpointId instead

If a document comes back with a routing error, the fix sits with your customer, not your payload: their SIREN is not registered on the Annuaire yet, so they cannot receive electronic invoices at all.


Did this page help you?