> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gabin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Zones and addresses

> Geocode French addresses, find named places, browse cities, districts and departments, and read market figures and boundaries of a zone.

This guide covers the endpoints that turn something a user types (an address, a place name, a city) into ids you can use elsewhere in the API: a building id, an INSEE city code, an IRIS district code.

Two French codes appear throughout:

* **INSEE code**: the official 5-character code of a city (`69266` is Villeurbanne). It is not the postal code: one postal code can cover several cities, and one city several postal codes. Paris, Lyon and Marseille arrondissements have their own INSEE codes (`69382` is Lyon 2e).
* **IRIS code**: the 9-character code of an INSEE statistical district. It starts with the INSEE code of its city (`692660101` is in Villeurbanne). Gabin groups IRIS into **districts** with a readable name; a district is identified by its first IRIS code.

## Geocode an address

`GET /v1/geocode` geocodes a French address with the Base Adresse Nationale (BAN, the national address database) and returns the normalized address, its point and, for a house-number match, the BDNB building at that point (inside it, or within 30 m).

**q** `string` *required*

Address, free text, 3 to 200 characters.

**limit** `integer` (default: 5)

Results, 1 to 10.

```bash curl theme={null}
curl "https://api.gabin.ai/v1/geocode?q=40%20rue%20de%20Bruxelles%20Villeurbanne&limit=1" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```javascript JavaScript theme={null}
const params = new URLSearchParams({ q: "40 rue de Bruxelles Villeurbanne", limit: "1" });
const res = await fetch(`https://api.gabin.ai/v1/geocode?${params}`, {
  headers: { Authorization: `Bearer ${process.env.GABIN_API_KEY}` },
});
const { data: results } = await res.json();
```

```python Python theme={null}
import os
import requests

res = requests.get(
    "https://api.gabin.ai/v1/geocode",
    params={"q": "40 rue de Bruxelles Villeurbanne", "limit": 1},
    headers={"Authorization": f"Bearer {os.environ['GABIN_API_KEY']}"},
)
results = res.json()["data"]
```

```json theme={null}
{
  "data": [
    {
      "label": "40 Rue de Bruxelles 69100 Villeurbanne",
      "name": "40 Rue de Bruxelles",
      "postal_code": "69100",
      "city": "Villeurbanne",
      "insee": "69266",
      "precision": "housenumber",
      "score": 0.9748290909090908,
      "location": [4.871472, 45.777186],
      "building": {
        "id": "bdnb-bg-LPHZ-UF68-3D9D",
        "address": "40 Rue de Bruxelles",
        "name": null,
        "gabin_url": "https://gabin.ai/batiment/40-rue-de-bruxelles-69100-villeurbanne-bdnb-bg-LPHZ-UF68-3D9D"
      }
    }
  ],
  "meta": { "page": { "next_cursor": null, "limit": 1 }, "total": 1, "total_kind": "exact" }
}
```

* `precision` is the level matched: `housenumber`, `street`, `locality` or `municipality`.
* `score` is the BAN match score, from 0 to 1.
* `location` is `[lon, lat]` in WGS84.
* `building` is filled only for a `housenumber` match, and `null` otherwise. Open it with `GET /v1/buildings/{id}` (see [buildings](https://docs.gabin.ai/guides/buildings.md)).

> [!TIP]
>
> Check `precision` before you trust `building`. A query such as "rue de la République Lyon" returns `street` matches without a building; ask the user for a house number.

## Find a named place

`GET /v1/places` finds named places (residences, hospitals, schools, care homes, hotels…) by name, from the BD TOPO (the national topographic database), the condominium register and other public sources. Each result carries its building.

**q** `string` *required*

Name of the place, 4 to 120 characters. A city at the end narrows the search: `orangerie ecully`.

**limit** `integer` (default: 5)

Results, 1 to 10.

```bash theme={null}
curl "https://api.gabin.ai/v1/places?q=hopital%20edouard%20herriot%20lyon&limit=3" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "name": "Hôpital Édouard Herriot",
      "category": "sante",
      "building_id": "bdnb-bg-4UCU-P29X-1AD4",
      "city": "Lyon 3e Arrondissement",
      "location": [4.882230655839228, 45.74241094731325]
    }
  ],
  "meta": { "page": { "next_cursor": null, "limit": 3 }, "total": 1, "total_kind": "exact" }
}
```

`category` is a French slug (`residence`, `sante`, `enseignement`, `ehpad`, `hotel`, `commerce`…) or `null`. Next: `GET /v1/buildings/{building_id}`.

## Cities

### Search cities

`GET /v1/zones/cities?q=` finds cities and arrondissements by name prefix, postal code or INSEE code. It returns up to 8 results. `q` takes 2 to 60 characters.

```bash theme={null}
curl "https://api.gabin.ai/v1/zones/cities?q=villeurb" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "insee": "69266",
      "name": "Villeurbanne",
      "department": "69",
      "postal_code": "69100",
      "population": 163684,
      "center": [4.881457939641974, 45.771955482561225]
    }
  ],
  "meta": { "page": { "next_cursor": null, "limit": 1 }, "total": 1, "total_kind": "exact" }
}
```

### Get a city

`GET /v1/zones/cities/{insee}` returns the same object for one city or arrondissement: name, department, main postal code, population and center.

```bash theme={null}
curl "https://api.gabin.ai/v1/zones/cities/69266" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

Use the INSEE code as `insee` in `GET /v1/buildings` and `GET /v1/companies`.

### Cities of a department

`GET /v1/zones/departments/{code}/cities` lists every city of a department by name. The arrondissements of Paris, Lyon and Marseille are listed next to their city, with `arrondissement: true`. The list is not paginated.

```bash theme={null}
curl "https://api.gabin.ai/v1/zones/departments/69/cities" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```json theme={null}
{
  "data": [
    { "insee": "69001", "name": "Affoux", "postal_code": "69170", "population": 398, "arrondissement": false },
    { "insee": "69002", "name": "Aigueperse", "postal_code": "69790", "population": 235, "arrondissement": false },
    …
    { "insee": "69123", "name": "Lyon", "postal_code": "", "population": 519127, "arrondissement": false },
    { "insee": "69381", "name": "Lyon 1er Arrondissement", "postal_code": "69001", "population": 28717, "arrondissement": true },
    { "insee": "69382", "name": "Lyon 2e Arrondissement", "postal_code": "69002", "population": 29981, "arrondissement": true },
    …
  ],
  "meta": { "page": { "next_cursor": null, "limit": 275 }, "total": 275, "total_kind": "exact" }
}
```

Department codes are 2 or 3 characters: `69`, `2A` (Corse-du-Sud), `974` (La Réunion).

## Districts

`GET /v1/zones/cities/{insee}/districts` lists the districts of a city, by name. A district is one or several merged IRIS with a readable name.

```bash theme={null}
curl "https://api.gabin.ai/v1/zones/cities/69266/districts" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```json theme={null}
{
  "data": [
    { "iris": "692660202", "name": "11 Novembre", "insee": "69266" },
    { "iris": "692661202", "name": "Albert Thomas", "insee": "69266" },
    …
    { "iris": "692660101", "name": "Charmettes", "insee": "69266" },
    …
  ],
  "meta": { "page": { "next_cursor": null, "limit": 48 }, "total": 48, "total_kind": "exact" }
}
```

`GET /v1/zones/districts/{iris}` returns one district:

```json theme={null}
{
  "data": { "iris": "692660101", "name": "Charmettes", "insee": "69266" },
  "meta": {}
}
```

Use the `iris` code in `GET /v1/buildings?iris=`, `GET /v1/companies?iris=` or the market and boundary endpoints below.

## Market figures

`GET /v1/zones/{level}/{code}/market` returns the market and territory figures of a zone, at every level containing it.

| `level` | `code` | Example |
| - | - | - |
| `region` | Region code | `84` (Auvergne-Rhône-Alpes) |
| `department` | Department code | `69` |
| `city` | INSEE code, arrondissements included | `69266` |
| `district` | IRIS code | `692660101` |

> [!WARNING]
>
> The level in this path is singular (`city`, `district`), while the collection paths above are plural (`/zones/cities/{insee}`, `/zones/districts/{iris}`). `GET /v1/zones/city/69266/market` is correct.

```bash curl theme={null}
curl "https://api.gabin.ai/v1/zones/district/692660101/market" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```javascript JavaScript theme={null}
const res = await fetch("https://api.gabin.ai/v1/zones/district/692660101/market", {
  headers: { Authorization: `Bearer ${process.env.GABIN_API_KEY}` },
});
const { data: market } = await res.json();
```

```python Python theme={null}
res = requests.get(
    "https://api.gabin.ai/v1/zones/district/692660101/market",
    headers={"Authorization": f"Bearer {os.environ['GABIN_API_KEY']}"},
)
market = res.json()["data"]
```

```json theme={null}
{
  "data": {
    "level": "district",
    "code": "692660101",
    "name": "Charmettes",
    "parents": {
      "city": { "insee": "69266", "name": "Villeurbanne" },
      "district": { "iris": "692660101", "name": "Charmettes" },
      "department": { "code": "69", "name": "Rhône" },
      "region": { "code": "84", "name": "Auvergne-Rhône-Alpes" }
    },
    "prices": [
      {
        "level": "district",
        "code": "692660101",
        "name": "Charmettes",
        "series": [
          {
            "year": 2026,
            "month": 0,
            "segment": "appartement",
            "window_years": 1,
            "median_m2": 4215,
            "p25_m2": 3584,
            "p75_m2": 4792,
            "sales": 34,
            "reliability": "haute"
          },
          …
        ]
      },
      { "level": "city", "code": "69266", "name": "Villeurbanne", "series": [ … ] },
      { "level": "department", "code": "69", "name": "Rhône", "series": [ … ] },
      { "level": "region", "code": "84", "name": "Auvergne-Rhône-Alpes", "series": [ … ] }
    ],
    "top_streets": [
      { "street": "CRS DE LA REPUBLIQUE", "median_m2": 4185, "sales": 19, "year": 2026 },
      { "street": "RUE ANTONIN PERRIN", "median_m2": 4034, "sales": 16, "year": 2026 },
      …
    ],
    "rents": [
      {
        "level": "city",
        "code": "69266",
        "name": "Villeurbanne",
        "series": [
          {
            "year": 2025,
            "property_type": "appart",
            "reference_area_m2": 52,
            "rent_m2": 15.63,
            "rent_m2_low": 12.52,
            "rent_m2_high": 19.51,
            "model_level": "commune"
          },
          …
        ]
      },
      …
    ],
    "demography": [ … ],
    "income": [
      {
        "level": "district",
        "code": "692660101",
        "name": "Charmettes",
        "series": [
          {
            "year": 2021,
            "median_declared": 23670,
            "median_disposable": 23610,
            "disposable_q1": 15920,
            "disposable_q3": 32150,
            "poverty_rate_pct": 18,
            "taxable_households_pct": 57,
            "gini": 0.319,
            …
          },
          …
        ]
      },
      …
    ]
  },
  "meta": {}
}
```

Each family (`prices`, `rents`, `demography`, `income`) is a list with one entry per level containing the zone, from the requested level up to the region, each with yearly `series`. Compare a district with its city by reading two entries of the same list.

| Family | Source | Series fields |
| - | - | - |
| `prices` | DVF sales | `segment` (`appartement`, `maison`, `residentiel` for both, `terrain`, `local` for commercial), median and quartiles per m², `sales`, `window_years` (years pooled), `reliability` |
| `top_streets` | DVF sales | Most active streets of the city, by median price |
| `rents` | ANIL rent estimates | `property_type` (`appart`, `appart_t1t2`, `appart_t3plus`, `maison`), rent per m² per month charges included, prediction interval |
| `demography` | INSEE census | Population by age band and by occupation (aged 15 and over) |
| `income` | INSEE FiLoSoFi | Median declared and disposable income per consumption unit, quartiles, poverty rate, Gini index, income shares |

A family missing for a zone comes back as an empty list. In the example, `rents` starts at the city level: rent estimates exist for the city, not the district.

For a single building, `GET /v1/buildings/{id}/market` returns a short summary of its city and district. See [buildings](https://docs.gabin.ai/guides/buildings.md#building-sections).

## Boundaries

`GET /v1/zones/{level}/{code}/boundary` returns the simplified boundary of a region, department, city or district as a GeoJSON `Polygon` or `MultiPolygon` in WGS84. Use it to draw a zone on a map, or to derive a bounding box.

```bash theme={null}
curl "https://api.gabin.ai/v1/zones/city/69266/boundary" \
  -H "Authorization: Bearer $GABIN_API_KEY"
```

```json theme={null}
{
  "data": {
    "type": "Polygon",
    "coordinates": [
      [
        [4.876350831, 45.756900107],
        [4.876574044, 45.758168242],
        [4.873784667, 45.75875056],
        …
      ]
    ]
  },
  "meta": {}
}
```

> [!NOTE]
>
> `GET /v1/buildings` accepts a bounding box of 4 km² at most. A city is usually larger: query it with `insee` instead, or split its bounding box into tiles of 2 km × 2 km.

## Next steps

> [card] [Buildings](https://docs.gabin.ai/guides/buildings.md)
>
> Open the building found at an address and list the companies in it.

> [card] [Advanced search](https://docs.gabin.ai/guides/advanced-search.md)
>
> Search a city, district or postal code with combined conditions.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.