France — PPF central directory
The Public Invoicing Portal central directory is the single resolution service letting any issuing PDP find the relevant receiving PDP, its preferred format, and its signing certificate, given a SIREN/SIRET.
Role of the central directory
The central directory is the critical element of the French decentralised 5-corner model (see the CTC 5-corner page). It combines the role of a PEPPOL SMP+SML and of a business registry:
- Recipient PDP resolution: for a given SIREN/SIRET, returns the registered PDP identifier, its AS4 endpoint, and the recipient's preferred invoicing format.
- Official business registry: holds administrative information about an in-scope business (legal name, address, NAF code, intra-Community VAT number, active/deregistered status) consolidated from INSEE's SIRENE base and enriched with invoicing data.
- Certificate registry: stores the signing certificate of the receiving PDP, letting the issuing PDP verify AS4 acknowledgements without relying on a third-party CA.
- Source of in-scope checks: a French economic
actor not present in the directory (or with
EXEMPTstatus) means out of scope — the issuing PDP must fall back to e-reporting (declaration instead of inter-PDP invoice).
Data model
A partner record is a versioned JSON object identified by SIREN.
Full example payload returned by
GET /v1/partner/802145795:
{
"siren": "802145795",
"siret": "80214579500024",
"denomination": "Atelier Numerique SAS",
"address": {
"street": "12 rue de la Faisanderie",
"postalCode": "75116",
"city": "Paris",
"countryCode": "FR"
},
"ape": "6201Z",
"tvaIntracom": "FR62802145795",
"registeredPdp": {
"pdpId": "PDP-FR-007",
"name": "Plateforme Demat Acme",
"endpoint": "https://pdp-acme.fr/as4/inbox",
"as4PartyType": "iso6523-actorid-upis",
"as4PartyId": "0009:80214579500024"
},
"acceptedFormats": [
"urn:cen.eu:en16931:2017",
"urn:factur-x.eu:1p0:en16931",
"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100",
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
],
"preferredFormat": "urn:factur-x.eu:1p0:en16931",
"signingCertificate": {
"issuer": "CN=PPF Issuer CA, O=AIFE, C=FR",
"serial": "0A:1B:2C:3D:4E:5F",
"notAfter": "2027-12-31T23:59:59Z"
},
"lifecycle": {
"createdAt": "2026-06-15T09:22:11Z",
"updatedAt": "2026-08-30T17:45:00Z",
"status": "ACTIVE"
}
} | Field | Type | Description | Required |
|---|---|---|---|
siren | string(9) | 9-digit SIREN, legal entity identifier | Yes |
siret | string(14) | 14-digit SIRET, primary establishment identifier | Yes |
denomination | string | Official legal name (SIRENE source) | Yes |
address | object | Headquarters postal address (street, ZIP, city, ISO 3166-1 country) | Yes |
ape | string(5) | NAF rev. 2 code (Main Activity Exercised) | Recommended |
tvaIntracom | string | Intra-Community VAT number, FR + key + SIREN | If liable for VAT |
registeredPdp | object | Default registered PDP (id, name, AS4 endpoint, party type/id) | Yes (for inbound) |
acceptedFormats | array | List of accepted profile URNs (EN 16931, Factur-X EN16931, CII, UBL) | Yes |
preferredFormat | string | URN of the preferred format to optimise recipient experience | Recommended |
signingCertificate | object | X.509 certificate of the receiving PDP (issuer, serial, notAfter) | Yes (for inbound) |
lifecycle.status | enum | ACTIVE, SUSPENDED, EXEMPT, RADIATED | Yes |
Onboarding and self-registration
Two registration channels are defined by the AIFE specifications:
- Self-registration via the PPF web portal: the business logs into impots.gouv.fr with its pro-account credentials, picks its destination PDP, declares accepted formats, and electronically signs the record. Ideal for an SME or micro-business without PDP integration on the IT side.
- Registration via API from an accredited PDP:
the PDP submits a
POST /v1/partneron the business's behalf with a proof of mandate (OAuth token delegated by the business via the FranceConnect+ Pro procedure). Ideal for mid-caps and large enterprises managed industrially by their PDP.
In both cases, registration is validated by a DGFiP workflow
(real-time SIRENE verification + anti-duplicate check) and
activated typically after 30 seconds to 2 minutes. The intermediate
status is PENDING_VALIDATION.
REST API + OAuth 2.0
The API exposes 8 main endpoints. Every call requires an OAuth 2.0 access token issued via the client_credentials flow (PDPs are the only OAuth clients; ERPs go through their PDP).
Authentication — obtain an access token
curl -X POST https://annuaire.ppf.gouv.fr/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=PDP-FR-007" \
-d "client_secret=$PPF_CLIENT_SECRET" \
-d "scope=annuaire.read annuaire.subscribe"
# Response:
# {
# "access_token": "eyJhbGciOi...",
# "token_type": "Bearer",
# "expires_in": 3600,
# "scope": "annuaire.read annuaire.subscribe"
# }
Typical scopes: annuaire.read (read partners),
annuaire.write (registration, PDP only),
annuaire.subscribe (webhook subscriptions).
GET /v1/partner/<siren>
curl -X GET "https://annuaire.ppf.gouv.fr/v1/partner/802145795" \
-H "Authorization: Bearer $PPF_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "If-None-Match: \"v3-1730289302\""
# Possible responses:
# 200 OK -> partner body + ETag, Cache-Control: max-age=86400
# 304 Not Modified -> local cache still valid, do not refetch
# 404 Not Found -> business not registered or not in scope
# 410 Gone -> business deregistered, do not route to this address
The If-None-Match header with the ETag returned by a
previous call enables 304 Not Modified responses:
this is the lazy-invalidation mechanism complementing webhooks.
GET /v1/partner — paginated search
curl -X GET "https://annuaire.ppf.gouv.fr/v1/partner?denomination=cooperative&cursor=eyJpZCI6MTAwfQ&limit=100" \
-H "Authorization: Bearer $PPF_ACCESS_TOKEN"
# Response:
# {
# "results": [ { "siren": "521452014", ... }, ... ],
# "pageInfo": {
# "hasNextPage": true,
# "endCursor": "eyJpZCI6MjAwfQ",
# "pageSize": 100
# }
# }
Pagination is opaque cursor-based: the client reuses the
endCursor returned by the previous page as-is. This
avoids inconsistent page jumps if the dataset changes concurrently
(business deregistered during pagination, for instance).
Cache, TTL and invalidation webhooks
AIFE specifications prescribe a local cache on the PDP side with a default TTL of 24h. The risk without a cache is twofold: central API saturation (multiplied by the number of invoices) and an RTT latency hop per invoice (harmful to the contractual client SLA).
Cache invalidation is event-driven via the PPF webhook system. A
PDP subscribes via POST /v1/subscriptions with an
HTTPS callback endpoint and a shared HMAC secret. Emitted events
include partner.created,
partner.updated, partner.suspended,
partner.radiated. Example received event:
{
"eventType": "partner.updated",
"eventTimestamp": "2026-09-12T11:04:23Z",
"eventId": "evt_2026091200004523",
"schemaVersion": "PPF-1.2",
"subject": {
"siren": "802145795",
"siret": "80214579500024"
},
"changes": [
"registeredPdp.endpoint",
"preferredFormat"
],
"newVersion": "v4-1731060123",
"ttlInvalidate": true
} - HMAC-SHA256 signature: every webhook is signed via the
X-PPF-Signatureheader. A PDP that does not verify the signature accepts forged invalidations. - Idempotence: each event carries an opaque
eventId. PPF may re-emit events on timeout: handle them idempotently (deduplicate byeventId). - Propagation delay: the AIFE target is under 60 seconds between the directory change and reception by every subscribed PDP.
- Callback failure handling: exponential backoff up to 24h, then automatic unsubscribe and operator notification. The PDP must manually re-subscribe after recovery.
Cross-links
- France — Mandate overview 2026/2027.
- France — CTC 5-corner model — role of the directory in the architecture.
- France — Factur-X FNFE-MPE specification.
- France — Chorus Pro and PPF transition.
- Standards — PEPPOL (SMP/SML for comparison).
- Sources: AIFE — External PPF API specifications, INSEE — SIRENE base, Decree 2024-266 of 25 March 2024, RFC 6749 OAuth 2.0, RFC 6585 HTTP 429 Too Many Requests.