Adresdata uit de BAG

Adres- en postcode-API voor Nederland

Postcode en huisnummer erin, straat, plaats, gemeente, provincie en coördinaten eruit. Eigen databron, negen endpoints en een response die veld voor veld gelijk is aan die van postcodeapi.nu, tegen een lager tarief.

  • 500 gratis calls per maand
  • Sandbox altijd gratis
  • Geen creditcard nodig
  • Servers in Nederland

In drie regels werkend

Plakken en draaien, zonder account

De sleutel hieronder is onze publieke sandboxsleutel: hij werkt meteen, kent de vaste testadressen en telt nooit mee voor een bundel.

https://sandbox.locatieapi.nl
curl -sS -H "X-Api-Key: lat_test_demo_publiek_locatieapi_sandbox" \
  https://sandbox.locatieapi.nl/v3/lookup/1021JT/19

Zelf proberen

Test de API

Vul een postcode en huisnummer in. Links zie je het adres, rechts het volledige verzoek en de ruwe response met statuscode en responstijd.

Volledige testpagina
Omgeving
Probeer:

Vul je een toevoeging in, dan schakelt het voorbeeld naar /v1/addresses; /v3/lookup accepteert alleen een geheel huisnummer.

Straat
Hamerstraat 19
Postcode
1021JT
Plaats
Amsterdam
Gemeente
Amsterdam
Provincie
Noord-Holland
Coördinaten
52.38488658, 4.92204151
console
bezig… 200 OK 0.02 ms
GET https://sandbox.locatieapi.nl/v3/lookup/1021JT/19
X-Api-Key: lat_test_demo_publiek_locatieapi_sandbox
Accept: application/json
← HTTP 200 OK
Content-Type: application/json
X-RateLimit-Limit: 40
X-RateLimit-Remaining: 39
X-RateLimit-Reset: 60
X-Quota-Limit: 500
X-Quota-Remaining: 500
X-Quota-Reset: 1788220800
X-Request-Id: a830b4a3-9ca8-484b-ad0f-66b91cea1821
Cache-Control: public, max-age=86400

{
    "postcode": "1021JT",
    "number": 19,
    "street": "Hamerstraat",
    "city": "Amsterdam",
    "municipality": "Amsterdam",
    "province": "Noord-Holland",
    "location": {
        "type": "Point",
        "coordinates": [
            4.92204151,
            52.38488658
        ]
    }
}

Dit voorbeeld draait op de proefsleutel van deze pagina en is beperkt tot 40 aanvragen per minuut per IP-adres. De limiet- en bundelheaders horen bij die sleutel; met je eigen sleutel zie je hier de limieten van jouw plan.

De bron

Waarom onze data klopt

We zijn zelf de databron. Er zit geen doorverkoper tussen ons en het Kadaster, dus we kunnen precies vertellen waar elk veld vandaan komt.

Rechtstreeks uit de BAG

Ongeveer 9,7 miljoen adressen uit de Basisregistratie Adressen en Gebouwen van het Kadaster. Elk adres draagt zijn BAG-nummeraanduiding mee, dus je kunt altijd terug naar de bron.

Dagelijks bijgewerkt

We lezen de dagelijkse mutatielevering in. Nieuwbouw, gewijzigde straatnamen en samengevoegde gemeenten staan binnen een dag in de API.

Postbussen erbij

Postbusreeksen staan niet in de BAG. Wij houden ze apart bij, zodat een postbusadres een nette 200 geeft met street: "Postbus" in plaats van een 404.

Coördinaten in WGS84 en RD

Elk adres heeft een lengte- en breedtegraad voor kaarten en de rijksdriehoeksmeting voor Nederlandse GIS-toepassingen.

Bouwjaar, oppervlakte en gebruik

Op de v1-endpoints krijg je ook oppervlakte, bouwjaar en gebruiksdoel mee. Handig voor verzekeraars, makelaars en energieadviseurs.

In Nederland gehost

De API en de logbestanden draaien op Nederlandse servers. Ruwe verzoeklogs bewaren we 90 dagen, daarna alleen nog geaggregeerde aantallen.

Voor je codeerassistent

Laat je AI het werk doen

Eén knop zet een volledige instructie op je klembord: de basis-URL's, de header, alle endpoints met parameters en voorbeeldresponses, de foutcodes en de valkuilen, plus de opdracht om er in jouw project een adresopzoeker mee te bouwen. Plak hem in Claude Code, Cursor, Copilot of ChatGPT.

2.524 tokens, ongeveer

Variant: Algemeen

Bekijk de instructie voor Algemeen
Je gaat LocatieAPI in mijn project inbouwen. LocatieAPI is een Nederlandse
adres- en postcode-API: je geeft een postcode en huisnummer en krijgt straat,
plaats, gemeente, provincie en coördinaten terug. De data komt uit de BAG van
het Kadaster. Hieronder staat de volledige specificatie. Lees hem helemaal
voordat je code schrijft.

## Basis

- Live: `https://api.locatieapi.nl`
- Sandbox: `https://sandbox.locatieapi.nl`, gratis, vaste testset, telt niet mee voor de bundel
- Altijd werkende terugval op hetzelfde pad: `https://locatieapi.nl/api`
- Authenticatie: stuur de header `X-Api-Key: lat_test_demo_publiek_locatieapi_sandbox`. Er is geen andere methode, geen OAuth en geen sleutel in de querystring.
- Alle responses zijn JSON. Foutresponses van v3 hebben `Content-Type: application/problem+json`.

## Endpoints

### GET /v3/lookup/{postcode}/{number}

Eén adres op postcode en huisnummer. Response-compatibel met postcodeapi.nu.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `postcode` | string | ja | P6 zonder spatie, hoofdletters of kleine letters. Patroon `^[0-9]{4}[a-zA-Z]{2}$`. |
| `number` | integer | ja | Huisnummer als geheel getal. Een toevoeging in het pad geeft `400`, geen `404`. |

Voorbeeldresponse:

```json
{
  "postcode": "1021JT",
  "number": 19,
  "street": "Hamerstraat",
  "city": "Amsterdam",
  "municipality": "Amsterdam",
  "province": "Noord-Holland",
  "location": {
    "type": "Point",
    "coordinates": [4.92204151, 52.38488658]
  }
}
```

### GET /v1/addresses

Alle treffers op een postcode en huisnummer, inclusief letters en toevoegingen.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `postcode` | string | ja | P6 zonder spatie. |
| `number` | integer | nee | Huisnummer. Zonder nummer krijg je de hele postcode terug. |
| `letter` | string | nee | Huisletter, één teken. |
| `addition` | string | nee | Huisnummertoevoeging. |

Voorbeeldresponse:

```json
{
  "data": [
    {
      "id": "0363200012101386",
      "postcode": "1021JT",
      "number": 19,
      "letter": null,
      "addition": null,
      "street": "Hamerstraat",
      "city": "Amsterdam",
      "municipality": "Amsterdam",
      "province": "Noord-Holland",
      "location": { "type": "Point", "coordinates": [4.92204151, 52.38488658] },
      "purposes": ["woonfunctie"],
      "surface": 98,
      "constructionYear": 1930,
      "type": "verblijfsobject"
    }
  ]
}
```

### GET /v1/addresses/{bagId}

Eén adres op het BAG-nummeraanduidingsnummer.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `bagId` | string | ja | BAG-nummeraanduiding, zestien cijfers. |

### GET /v1/postcodes/{postcode}

Samenvatting per P6: straat, plaats, gemeente, provincie, zwaartepunt en aantal adressen.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `postcode` | string | ja | P6 zonder spatie. |

Voorbeeldresponse:

```json
{
  "postcode": "1021JT",
  "street": "Hamerstraat",
  "city": "Amsterdam",
  "municipality": "Amsterdam",
  "province": "Noord-Holland",
  "location": { "type": "Point", "coordinates": [4.92204151, 52.38488658] },
  "addressCount": 64,
  "numberMin": 1,
  "numberMax": 121
}
```

### GET /v1/autocomplete

Type-ahead op adres, straat of plaats. Bedoeld voor een checkout of zoekveld.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `q` | string | ja | Zoekterm, minimaal twee tekens. |
| `type` | string | nee | `address`, `street` of `city`. Standaard `address`. |
| `limit` | integer | nee | Aantal suggesties, 1 tot 25. Standaard 10. |

Voorbeeldresponse:

```json
{
  "data": [
    {
      "label": "Hamerstraat 19, 1021 JT Amsterdam",
      "type": "address",
      "postcode": "1021JT",
      "number": 19,
      "street": "Hamerstraat",
      "city": "Amsterdam"
    }
  ]
}
```

### POST /v1/bulk/lookup

Maximaal 1.000 combinaties in één verzoek. Elke regel telt als één call.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `addresses` | array | ja | Lijst van objecten met `postcode` en `number`. |

Voorbeeldresponse:

```json
{
  "data": [
    {
      "postcode": "1021JT",
      "number": 19,
      "status": 200,
      "address": {
        "street": "Hamerstraat",
        "city": "Amsterdam",
        "municipality": "Amsterdam",
        "province": "Noord-Holland",
        "location": { "type": "Point", "coordinates": [4.92204151, 52.38488658] }
      }
    },
    {
      "postcode": "6545CA",
      "number": 299,
      "status": 404,
      "address": null
    }
  ]
}
```

### POST /v1/validate

Controleert een ingevoerd adres en geeft een correctievoorstel terug.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `postcode` | string | ja | Postcode zoals ingevoerd, met of zonder spatie. |
| `number` | string | ja | Huisnummer zoals ingevoerd, toevoeging mag erin staan. |
| `street` | string | nee | Straatnaam zoals ingevoerd, voor de vergelijking. |
| `city` | string | nee | Plaats zoals ingevoerd, voor de vergelijking. |

Voorbeeldresponse:

```json
{
  "valid": false,
  "reason": "street_mismatch",
  "suggestion": {
    "postcode": "1021JT",
    "number": 19,
    "letter": null,
    "addition": null,
    "street": "Hamerstraat",
    "city": "Amsterdam"
  }
}
```

### GET /v1/reverse

De dichtstbijzijnde adressen bij een coördinaat, met afstand in meters.

| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
| `lat` | number | ja | Breedtegraad in WGS84. |
| `lon` | number | ja | Lengtegraad in WGS84. |
| `radius` | integer | nee | Zoekstraal in meters, 1 tot 1.000. Standaard 100. |

Voorbeeldresponse:

```json
{
  "data": [
    {
      "distance": 12,
      "postcode": "1021JT",
      "number": 19,
      "street": "Hamerstraat",
      "city": "Amsterdam",
      "location": { "type": "Point", "coordinates": [4.92204151, 52.38488658] }
    }
  ]
}
```

## Foutcodes

| Status | Titel | Wanneer | Body |
|---|---|---|---|
| 400 | Request validation failed | De postcode voldoet niet aan het patroon, of het huisnummer is geen geheel getal. | `{"title":"Request validation failed","invalidParams":[{"name":"number","reason":"should be integer"}]}` |
| 401 | Invalid API key | De header X-Api-Key ontbreekt, is onbekend of is ingetrokken. | `{"title":"Invalid API key"}` |
| 404 | Resource not found | De combinatie bestaat niet in de BAG. | `{"title":"Resource not found"}` |
| 429 | Rate limit exceeded | Je zit boven je calls per seconde of boven je maandbundel. | `{"title":"Rate limit exceeded"}` |

## Responseheaders op elke call

- `X-RateLimit-Limit`: Het aantal calls per seconde dat bij je plan hoort.
- `X-RateLimit-Remaining`: Wat er in het huidige venster van dat aantal over is.
- `X-RateLimit-Reset`: Aantal seconden tot het venster opnieuw begint.
- `X-Quota-Limit`: De maandbundel van je plan in aantal calls.
- `X-Quota-Remaining`: Wat er van die bundel over is in de lopende factuurperiode.
- `X-Quota-Reset`: Unix-tijdstip waarop de volgende factuurperiode begint.
- `X-Request-Id`: Uniek nummer per verzoek. Noem dit bij een supportvraag.
- `Cache-Control`: Bij een 200: `public, max-age=86400`. Adressen veranderen zelden.

## Valkuilen

- **Postcode zonder spatie** De API accepteert `1021JT`, niet `1021 JT`. Haal de spatie er in je eigen code uit voordat je de URL bouwt.
- **Huisnummer als geheel getal** In `/v3/lookup` hoort alleen het cijferdeel. `29a` geeft een `400` en geen `404`.
- **Toevoegingen horen bij /v1/addresses** Wil je huisletters en toevoegingen, gebruik dan `/v1/addresses` met `letter` en `addition`.
- **location is [longitude, latitude]** GeoJSON zet de lengtegraad eerst. Dat is de omgekeerde volgorde van wat de meeste kaartbibliotheken als "lat, lng" tonen.
- **location kan null zijn** Bij een postbus is er geen coördinaat en is `street` letterlijk `Postbus`.
- **Fouten zijn problem+json** Foutresponses van v3 hebben `Content-Type: application/problem+json` en een veld `title`, geen `message`.

## Sandbox

De sandbox draait op `https://sandbox.locatieapi.nl` en kent precies deze gevallen:

| Postcode | Huisnummer | Status | Resultaat |
|---|---|---|---|
| 6545CA | 29 | 200 | Waldeck Pyrmontsingel, Nijmegen, Gelderland |
| 1021JT | 19 | 200 | Hamerstraat, Amsterdam, Noord-Holland |
| 5038EA | 17 | 200 | Stationsstraat, Tilburg, Noord-Brabant |
| 3030AC | 100 | 200 | Postbus, Leusden, Utrecht. location is null |
| 6545CA | 29a | 400 | number should be integer |
| 6545C | 29 | 400 | postcode voldoet niet aan het patroon |
| 6545CA | 299 | 404 | Resource not found |

## Wat ik van je wil

1. Bouw een adresopzoeker in dit project met bovenstaande API.
2. Gebruik de HTTP-client die hier al gebruikt wordt. Voeg geen nieuwe
   afhankelijkheid toe als er al een client aanwezig is.
3. Zet de sleutel in de omgevingsvariabelen, nooit in de broncode en nooit in
   iets dat naar de browser gaat, tenzij het een sleutel met alleen
   leesrechten is waarop de toegestane origin is ingesteld.
4. Cache elk gevonden adres minstens 24 uur op de sleutel postcode plus
   huisnummer. Adressen veranderen zelden en het scheelt calls uit de bundel.
5. Behandel de statuscodes apart: 400 is een invoerfout die je aan de
   gebruiker toont, 404 betekent onbekend adres, 401 is een sleutelprobleem en
   429 betekent wachten en opnieuw proberen met exponentiële terugval.
6. Val netjes terug op handmatige invoer als de API niet bereikbaar is of
   traag reageert: zet een timeout van 5 seconden, laat de velden voor straat
   en plaats dan gewoon invulbaar en blokkeer het formulier niet.
7. Normaliseer de invoer voordat je de URL bouwt: haal spaties uit de
   postcode, maak hem hoofdletters, en stuur alleen het cijferdeel van het
   huisnummer mee.
8. Schrijf een test die de gelukkige route, de 404 en de 400 afdekt. Gebruik
   daarvoor de sandbox op https://sandbox.locatieapi.nl met de vaste testgevallen.

## Omgeving

Gebruik https://sandbox.locatieapi.nl zolang je aan het bouwen bent en zet hem om naar https://api.locatieapi.nl
als het werkt. De header blijft in beide gevallen X-Api-Key.

Prijzen

Dezelfde staffels, een lager tarief

Onze bundels volgen bewust exact de staffels van postcodeapi.nu, zodat je per staffel kunt vergelijken. Bij elke staffel zitten wij lager in prijs en hoger in snelheidslimiet.

Gratis

€ 0 per maand

500 calls, 3 per seconde

Om te proberen en voor kleine hobbyprojecten.

Starter

€ 4,95 per maand

1.000 calls, 5 per seconde

Voor een formulier of webshop met beperkt verkeer.

Klein

€ 13,95 per maand

5.000 calls, 10 per seconde

Voor een webshop met een lopende checkout.

Standaard

Meest gekozen

€ 34,95 per maand

20.000 calls, 15 per seconde

De meest gekozen bundel voor teams met meerdere omgevingen.

Alle bedragen exclusief 21% btw. Jaarabonnement 10% goedkoper.

Vragen

Veelgestelde vragen

Staat je vraag er niet bij? Mail naar support@locatieapi.nl, we antwoorden op werkdagen binnen een dag.

Waar komt de adresdata vandaan?

Uit de Basisregistratie Adressen en Gebouwen (BAG) van het Kadaster, aangevuld met postbusreeksen die niet in de BAG staan. We nemen de landelijke levering rechtstreeks af en verwerken hem zelf, dus er zit geen tussenpartij tussen de bron en onze API.

Hoe vaak wordt de data bijgewerkt?

De BAG levert dagelijks mutaties. Die verwerken we dagelijks, zodat nieuwbouw en gewijzigde adressen binnen een dag in de API staan. Op de statuspagina zie je wanneer de laatste levering is ingelezen.

Kan ik overstappen van postcodeapi.nu zonder mijn code aan te passen?

Ja, voor de v3-endpoints. De response is veld voor veld gelijk, inclusief de volgorde [longitude, latitude] in location en de foutbodies in problem+json. In de praktijk vervang je alleen de basis-URL en de sleutel. Zie overstappen.

Mag ik de API rechtstreeks vanuit de browser aanroepen?

Ja. Zet de toegestane origins op de sleutel en gebruik een sleutel met alleen leesrechten. Dan kan autocomplete rechtstreeks vanuit je checkout draaien, zonder tussenlaag. Een sleutel zonder ingestelde origin werkt bewust alleen server-side.

Wat gebeurt er als ik over mijn bundel ga?

Betaalde plannen krijgen 10% coulance boven de bundel. Daarboven volgt een 429. Je krijgt een mail bij 80% en bij 100% van de bundel. Het gratis plan stopt hard op 500 calls, zodat je nooit een onverwachte rekening krijgt.

Telt sandboxverkeer mee?

Nee. De sandbox is gratis en onbeperkt, in elk plan. Testen kost je nooit calls uit je bundel.

Is er een verwerkersovereenkomst?

Ja. Adresgegevens die je opzoekt kunnen persoonsgegevens zijn, dus we hebben een standaard verwerkersovereenkomst die je bij het aanmaken van je account kunt accepteren.

Begin met de sandbox, ga live als het werkt

Een account is gratis en levert meteen een live- en een sandboxsleutel op. Je hoeft geen betaalgegevens achter te laten en het gratis plan stopt netjes op zijn bundel.