Public-registry enrichment
Public-registry enrichment
Fills the gaps in a list (phone, email and website) by matching each business against official public registries loaded locally. No crawling, no AI, no network call at job time: the answer is either in the registry or it is not.
Purpose
Most enrichment modules read a business website, so a list without websites is a dead end. This
module works the other way round: it identifies the business (company ID, or name plus postcode)
and returns the contact details published in open government registries. It is the natural step
right after sirene, which returns official company records but never contact details.
Matching is deterministic and ordered from safest to loosest: company ID (SIRET), then parent company ID (SIREN), then normalised name + postcode, then normalised name + town. When two same-name records in the same town disagree, nothing is filled: a blank is better than a wrong number.
Registries covered
| Registry | What it covers | What it brings |
|---|---|---|
| Annuaire Santé (RPPS) | Doctors, dentists, pharmacists, midwives | Phone, email |
| DATAtourisme | Hotels, restaurants, campsites, venues and activities | Website |
| Public administration directory (DILA) | Town halls, prefectures, public bodies | Phone, email, website |
| FINESS | Hospitals, clinics, care homes, social care | Phone |
| Education directory | Schools and high schools | Phone, website |
| ADEME, RGE companies | Construction and energy retrofit | Phone, email, website |
| Agence Bio | Organic producers, processors and distributors | Phone, website |
| Atout France, classified accommodation | Hotels, campsites, tourist residences | Website |
| Vehicle inspection centres | Automotive | Phone, website |
| Qualité Tourisme and Tourisme et Handicap (DGE) | Certified tourism businesses | Phone, email, website |
| OpenStreetMap, shops and craftspeople | Bakeries, hairdressers, garages, offices, local shops | Phone, email, website |
| OpenStreetMap, food service | Restaurants, cafés, bars | Phone, website |
| OpenStreetMap, healthcare, public services and accommodation | Practices, public facilities, hotels and guesthouses | Phone, email, website |
That is roughly 1,160,000 establishments, of which 854,000 have a phone number, 287,000 an email and 570,000 a website. Coverage is nationwide (France) and the registries are refreshed every month, with nothing to do on your side.
Licensing and attribution
The State registries are published under the Licence Ouverte. The last three come from
OpenStreetMap and are published under the ODbL, which requires attribution and share-alike. That is
what the opendata_source column is for: every value written names the registry it came from. If
you redistribute a file containing this data, keep that column.
Inputs
| Field | Required | Notes |
|---|---|---|
nom |
yes (unless siret/siren) |
Business name. Aliases accepted (name, raison sociale, entreprise…). |
siret |
no | 14 digits. Best match key: used first when present. |
siren |
no | 9 digits. Used when no SIRET matches. |
code_postal |
no | Strongly recommended: without a postcode or town, name-based matching is skipped. |
commune |
no | Fallback when there is no postcode. |
This is the only enrichment module that accepts rows with no contact detail at all: finding one is its job. Rows without a name and without a company ID are kept in the output file untouched.
Outputs
| Column | Type | Description |
|---|---|---|
site_web |
string | Filled only if empty in the input. |
telephone |
string | Filled only if empty in the input. National format. |
email |
string | Filled only if empty in the input. Generic institutional mailboxes are excluded. |
opendata_champs |
string | Which columns this module filled, |-separated. Empty when nothing was filled. |
opendata_match |
string | How the row was matched: siret, siren, nom+cp or nom+commune. Empty when no match. |
opendata_source |
string | Human-readable registry the values came from (attribution required by the open licence). |
An existing value is never overwritten. An empty opendata_champs means the module ran and found
nothing usable for that row, never that the row was dropped.
Lifecycle
Standard job lifecycle, see Jobs lifecycle. Progress is reported
in businesses and final volume in rows completed.
Pipeline
opendata is an enrichment module: it augments an existing list rather than generating one.
needs: poi_list
produces: enriched_list
Typical chain:
sirene → opendata → emails → verify_emails → filter
Placing it right after sirene is what makes the rest of the chain possible: modules such as
emails, socials, legal_mentions and techstack all require site_web.
Endpoints
POST /api/jobs/opendata
| Field | Type | Required | Description |
|---|---|---|---|
items |
array of objects | no | Rows to enrich, max 10000. Optional when source_job_id is set. |
source_job_id |
string | no | Reuse the rows of one of your completed jobs instead of resending them. |
Response: the standard JobPublic envelope.
Example:
POST /api/jobs/opendata
{ "items": [ { "nom": "Dupont Couverture", "code_postal": "35000", "siret": "48123456700019" } ] }
{ "id": "6b1f…", "job_type": "opendata", "status": "pending", "results_count": 0 }
Global quotas and per-job ceilings: see Limits.
Errors
| Condition | Response |
|---|---|
| No row has a name, a SIRET or a SIREN | 400 with the exact composition of the list submitted |
| More than 10000 rows | 422 validation error |
source_job_id unknown, not yours, unfinished or over 10000 rows |
400 |
What's next
- Find the website: for the rows left without a website.
- Company data: legal form, headcount, directors, financials.
- Emails: becomes possible on every row where a website was just filled.
- Extra phones: additional numbers found on the website itself.