Count and search weigh 5: each call counts five times against your per-minute rate and daily quota. See limits.
A typical flow is: read the catalog once, build a request, count it while you refine the conditions, then list the results.
Read the field catalog
GET /v1/search/fields returns every filterable field. Add ?target=buildings or ?target=companies to get only the fields of one target. The catalog does not touch the database, so you can cache it in your application.
label, description and value labels are in French. id and value codes are stable: use them in your requests. description states what the data means and its limits (here, 31 % of diagnosed buildings have no class), which helps an AI agent pick the right field.
What you can filter on
The catalog has 59 fields at the time of writing, grouped byobject:
Read the catalog for the full list: it is the source of truth.
Build a request
A request has a target, a zone, conditions that all apply, and optional OR groups.string
required
buildings returns BDNB buildings. companies returns registered offices.object
required
The area searched.
array
Conditions that all apply (AND). Empty: everything in the zone.
array
OR groups:
[{ "conditions": [ … ] }]. At least one condition of each group applies. Up to 4 groups, 2 to 6 conditions per group.integer
default:"20"
POST /v1/search only. Results per page, 1 to 100.string
POST /v1/search only. meta.page.next_cursor of the previous page.Conditions
Each condition names a fieldid and gives either values or min/max, according to the field’s operator:
A field that does not apply to the target is refused with
400 INVALID:
The zone is required
A search without a zone would scan tens of millions of rows. The API refuses it withZONE_REQUIRED:
GET /v1/zones/departments/{code}/cities (see zones and addresses), keeping your daily quota in mind.
Example: pre-1975 apartment buildings rated F or G
This request looks for apartment buildings in Villeurbanne built in 1974 or earlier, with an energy class of F or G (commonly called passoires thermiques), that have either a professional condominium manager or an identified corporate owner. Those are the two counterparts a renovation company would contact.1
Count the matches
total_kind is lower_bound. breakdowns is null when the breakdowns took too long.2
List the first page
Send the same body to Results come in a stable order. While pages remain,
POST /v1/search, with a limit:meta.total is a lower bound (here, “at least 4”): the exact total is the one POST /v1/search/count returned.3
Follow the cursor
Send the same body again with Each page weighs 5. With
cursor set to meta.page.next_cursor. Keep the same target, zone and conditions: the cursor is bound to them. The page size stays the one of the first page.JavaScript
limit: 100, the 150 buildings of this example cost two pages, 10 units. A query reaches at most 10,000 results by following cursors. See pagination.GET /v1/buildings/{id}, and its /condominium and /owners sections, as shown in buildings.
Search companies
Withtarget: "companies", the search returns registered offices. This request lists real-estate holding companies (NAF 68.20B) created in 2024 or later with their registered office in the 69002 postal code:
headquarters_building_id is the BDNB building of the registered office, when matched. Next: GET /v1/companies/{siren}.
Result rows
Each row has atype:
building:id,address,city,usage,construction_year,housing_units,dpe_class,gabin_url.company:siren,name,naf_code,naf_label,city,headcount_range,headquarters_building_id,gabin_url.
In search rows,
usage is the BDNB label in French ("Résidentiel collectif"), the same codes as the batiment.usage field. GET /v1/buildings uses English values (residential, tertiary, industrial, mixed) instead.