wozapi 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wozapi-1.0.0/.gitignore +5 -0
- wozapi-1.0.0/PKG-INFO +87 -0
- wozapi-1.0.0/README.md +66 -0
- wozapi-1.0.0/pyproject.toml +42 -0
- wozapi-1.0.0/wozapi.py +128 -0
wozapi-1.0.0/.gitignore
ADDED
wozapi-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: wozapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: WOZ-waarde, BAG-adresgegevens en kadastrale percelen van elk Nederlands adres via 1 endpoint. Client voor woz-api.nl.
|
|
5
|
+
Project-URL: Homepage, https://woz-api.nl
|
|
6
|
+
Project-URL: Documentation, https://wozapi.github.io/
|
|
7
|
+
Project-URL: Repository, https://github.com/WozApi/wozapi-clients
|
|
8
|
+
Project-URL: Prijzen, https://woz-api.nl/woz-api-prijs
|
|
9
|
+
Author-email: WozApi <info@woz-api.nl>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: bag,kadaster,nederland,proptech,vastgoed,woz,woz-api,woz-waarde
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Natural Language :: Dutch
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# wozapi (Python)
|
|
23
|
+
|
|
24
|
+
Python-client voor de [WOZ API van woz-api.nl](https://woz-api.nl): de WOZ-waarde,
|
|
25
|
+
BAG-adresgegevens en kadastrale percelen van elk Nederlands adres in 1 JSON-response.
|
|
26
|
+
Geen externe afhankelijkheden, alleen de standaardbibliotheek.
|
|
27
|
+
|
|
28
|
+
## Installeren
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install wozapi
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Nog niet gepubliceerd? Kopieer dan `wozapi.py` naar je project; het bestand staat op zichzelf.
|
|
35
|
+
|
|
36
|
+
## Gebruik
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from wozapi import WozApi, WozApiError
|
|
40
|
+
|
|
41
|
+
client = WozApi("jouw-api-key")
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
adres = client.adres("Spuistraat 36C, 1012 TT Amsterdam")
|
|
45
|
+
for woz in adres["woz"]:
|
|
46
|
+
print(woz["peildatum"], woz["vastgesteldeWaarde"])
|
|
47
|
+
except WozApiError as fout:
|
|
48
|
+
print(fout.status, fout.bericht)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Perceelgrenzen als GeoJSON meesturen:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
adres = client.adres("Spuistraat 36C, 1012 TT Amsterdam", geometrie=True)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Zoeken op BAG-identificatie in plaats van een adrestekst:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
client.nummeraanduiding("0363200000218908")
|
|
61
|
+
client.adresseerbaar_object("0363010000740855")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Creditsaldo opvragen:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
print(client.credits())
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Wat kost het
|
|
71
|
+
|
|
72
|
+
Een gratis account geeft 10 credits. 1 credit is 1 uniek adres, en hetzelfde adres binnen
|
|
73
|
+
7 dagen opnieuw opvragen kost geen extra credit. De prijs per credit begint bij EUR 0,35
|
|
74
|
+
excl. btw en daalt bij grotere afname; zie [de prijzen](https://woz-api.nl/woz-api-prijs).
|
|
75
|
+
|
|
76
|
+
Geen zin in code? Met de [Excel-wizard](https://woz-api.nl/woz-waarden-in-excel) upload je een
|
|
77
|
+
bestand met adressen en krijg je het aangevuld terug.
|
|
78
|
+
|
|
79
|
+
## Documentatie
|
|
80
|
+
|
|
81
|
+
- API-referentie: [woz-api.nl/swagger](https://woz-api.nl/swagger/index.html)
|
|
82
|
+
- Uitleg en achtergrond: [woz-api.nl/artikelen](https://woz-api.nl/artikelen)
|
|
83
|
+
- Ontwikkeling van WOZ-waarden per regio: [woz-api.nl/woz-waarde-ontwikkeling](https://woz-api.nl/woz-waarde-ontwikkeling)
|
|
84
|
+
|
|
85
|
+
## Licentie
|
|
86
|
+
|
|
87
|
+
MIT
|
wozapi-1.0.0/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# wozapi (Python)
|
|
2
|
+
|
|
3
|
+
Python-client voor de [WOZ API van woz-api.nl](https://woz-api.nl): de WOZ-waarde,
|
|
4
|
+
BAG-adresgegevens en kadastrale percelen van elk Nederlands adres in 1 JSON-response.
|
|
5
|
+
Geen externe afhankelijkheden, alleen de standaardbibliotheek.
|
|
6
|
+
|
|
7
|
+
## Installeren
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install wozapi
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Nog niet gepubliceerd? Kopieer dan `wozapi.py` naar je project; het bestand staat op zichzelf.
|
|
14
|
+
|
|
15
|
+
## Gebruik
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from wozapi import WozApi, WozApiError
|
|
19
|
+
|
|
20
|
+
client = WozApi("jouw-api-key")
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
adres = client.adres("Spuistraat 36C, 1012 TT Amsterdam")
|
|
24
|
+
for woz in adres["woz"]:
|
|
25
|
+
print(woz["peildatum"], woz["vastgesteldeWaarde"])
|
|
26
|
+
except WozApiError as fout:
|
|
27
|
+
print(fout.status, fout.bericht)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Perceelgrenzen als GeoJSON meesturen:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
adres = client.adres("Spuistraat 36C, 1012 TT Amsterdam", geometrie=True)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Zoeken op BAG-identificatie in plaats van een adrestekst:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
client.nummeraanduiding("0363200000218908")
|
|
40
|
+
client.adresseerbaar_object("0363010000740855")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Creditsaldo opvragen:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
print(client.credits())
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Wat kost het
|
|
50
|
+
|
|
51
|
+
Een gratis account geeft 10 credits. 1 credit is 1 uniek adres, en hetzelfde adres binnen
|
|
52
|
+
7 dagen opnieuw opvragen kost geen extra credit. De prijs per credit begint bij EUR 0,35
|
|
53
|
+
excl. btw en daalt bij grotere afname; zie [de prijzen](https://woz-api.nl/woz-api-prijs).
|
|
54
|
+
|
|
55
|
+
Geen zin in code? Met de [Excel-wizard](https://woz-api.nl/woz-waarden-in-excel) upload je een
|
|
56
|
+
bestand met adressen en krijg je het aangevuld terug.
|
|
57
|
+
|
|
58
|
+
## Documentatie
|
|
59
|
+
|
|
60
|
+
- API-referentie: [woz-api.nl/swagger](https://woz-api.nl/swagger/index.html)
|
|
61
|
+
- Uitleg en achtergrond: [woz-api.nl/artikelen](https://woz-api.nl/artikelen)
|
|
62
|
+
- Ontwikkeling van WOZ-waarden per regio: [woz-api.nl/woz-waarde-ontwikkeling](https://woz-api.nl/woz-waarde-ontwikkeling)
|
|
63
|
+
|
|
64
|
+
## Licentie
|
|
65
|
+
|
|
66
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wozapi"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "WOZ-waarde, BAG-adresgegevens en kadastrale percelen van elk Nederlands adres via 1 endpoint. Client voor woz-api.nl."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{ name = "WozApi", email = "info@woz-api.nl" }]
|
|
13
|
+
keywords = ["woz", "woz-api", "woz-waarde", "bag", "kadaster", "nederland", "vastgoed", "proptech"]
|
|
14
|
+
|
|
15
|
+
# Bewust geen dependencies: de client gebruikt alleen de standaardbibliotheek, zodat hij in elke
|
|
16
|
+
# omgeving werkt zonder dependency-discussie. Dat is ook de reden dat hij een enkele module is
|
|
17
|
+
# en geen package met submodules.
|
|
18
|
+
dependencies = []
|
|
19
|
+
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 5 - Production/Stable",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Natural Language :: Dutch",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://woz-api.nl"
|
|
32
|
+
Documentation = "https://wozapi.github.io/"
|
|
33
|
+
Repository = "https://github.com/WozApi/wozapi-clients"
|
|
34
|
+
Prijzen = "https://woz-api.nl/woz-api-prijs"
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
# Een enkele module, geen map. Zonder deze regel zoekt hatchling naar een map "wozapi" en faalt.
|
|
38
|
+
only-include = ["wozapi.py"]
|
|
39
|
+
sources = ["."]
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.sdist]
|
|
42
|
+
include = ["wozapi.py", "README.md"]
|
wozapi-1.0.0/wozapi.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WozApi: WOZ-waarde, BAG-adresgegevens en kadastrale percelen van elk Nederlands adres.
|
|
3
|
+
|
|
4
|
+
Dunne wrapper rond https://woz-api.nl zonder externe afhankelijkheden: alleen de
|
|
5
|
+
standaardbibliotheek, zodat deze client in elke omgeving werkt zonder dependency-discussie.
|
|
6
|
+
|
|
7
|
+
Snel starten:
|
|
8
|
+
|
|
9
|
+
from wozapi import WozApi
|
|
10
|
+
|
|
11
|
+
client = WozApi("jouw-api-key")
|
|
12
|
+
adres = client.adres("Spuistraat 36C, 1012 TT Amsterdam")
|
|
13
|
+
print(adres["woz"][0]["vastgesteldeWaarde"])
|
|
14
|
+
|
|
15
|
+
Een gratis account op https://woz-api.nl geeft 10 credits. 1 credit is 1 uniek adres;
|
|
16
|
+
hetzelfde adres binnen 7 dagen opnieuw opvragen kost geen extra credit.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import urllib.error
|
|
23
|
+
import urllib.parse
|
|
24
|
+
import urllib.request
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
__version__ = "1.0.0"
|
|
28
|
+
__all__ = ["WozApi", "WozApiError"]
|
|
29
|
+
|
|
30
|
+
STANDAARD_BASIS_URL = "https://woz-api.nl"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class WozApiError(RuntimeError):
|
|
34
|
+
"""Fout van de WOZ API. Bevat de HTTP-status en, indien aanwezig, de servermelding."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, status: int, bericht: str, body: str | None = None) -> None:
|
|
37
|
+
super().__init__(f"WozApi {status}: {bericht}")
|
|
38
|
+
self.status = status
|
|
39
|
+
self.bericht = bericht
|
|
40
|
+
self.body = body
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class WozApi:
|
|
44
|
+
"""Client voor de WOZ API.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
api_key: je sleutel uit https://woz-api.nl/ApiKeys.
|
|
48
|
+
basis_url: alleen aanpassen voor een testomgeving.
|
|
49
|
+
timeout: seconden voordat een request afbreekt.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
api_key: str,
|
|
55
|
+
basis_url: str = STANDAARD_BASIS_URL,
|
|
56
|
+
timeout: float = 30.0,
|
|
57
|
+
) -> None:
|
|
58
|
+
if not api_key or not api_key.strip():
|
|
59
|
+
raise ValueError("api_key is verplicht; maak er een aan op https://woz-api.nl/ApiKeys")
|
|
60
|
+
self._api_key = api_key.strip()
|
|
61
|
+
self._basis_url = basis_url.rstrip("/")
|
|
62
|
+
self._timeout = timeout
|
|
63
|
+
|
|
64
|
+
def adres(self, adres: str, geometrie: bool = False) -> dict[str, Any]:
|
|
65
|
+
"""Zoekt op een vrij ingevoerd adres, bijvoorbeeld "Spuistraat 36C, 1012 TT Amsterdam".
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
adres: het adres als tekst.
|
|
69
|
+
geometrie: ook perceelgrenzen als GeoJSON meesturen. Standaard uit, want dat
|
|
70
|
+
maakt de respons fors groter.
|
|
71
|
+
"""
|
|
72
|
+
return self._get("/Api/Adres", {"adres": adres, "geometrie": geometrie})
|
|
73
|
+
|
|
74
|
+
def nummeraanduiding(self, nummeraanduiding_id: str, geometrie: bool = False) -> dict[str, Any]:
|
|
75
|
+
"""Zoekt op een BAG-nummeraanduiding-id."""
|
|
76
|
+
pad = f"/Api/Nummeraanduiding/{urllib.parse.quote(str(nummeraanduiding_id))}"
|
|
77
|
+
return self._get(pad, {"geometrie": geometrie})
|
|
78
|
+
|
|
79
|
+
def adresseerbaar_object(self, object_id: str, geometrie: bool = False) -> dict[str, Any]:
|
|
80
|
+
"""Zoekt op een BAG-adresseerbaarobject-id (verblijfsobject, ligplaats, standplaats)."""
|
|
81
|
+
pad = f"/Api/AdresseerbaarObject/{urllib.parse.quote(str(object_id))}"
|
|
82
|
+
return self._get(pad, {"geometrie": geometrie})
|
|
83
|
+
|
|
84
|
+
def credits(self) -> dict[str, Any]:
|
|
85
|
+
"""Het resterende creditsaldo van deze sleutel."""
|
|
86
|
+
return self._get("/Api/Credits", {})
|
|
87
|
+
|
|
88
|
+
def _get(self, pad: str, parameters: dict[str, Any]) -> dict[str, Any]:
|
|
89
|
+
schoon = {
|
|
90
|
+
sleutel: ("true" if waarde is True else "false" if waarde is False else str(waarde))
|
|
91
|
+
for sleutel, waarde in parameters.items()
|
|
92
|
+
if waarde is not None
|
|
93
|
+
}
|
|
94
|
+
url = f"{self._basis_url}{pad}"
|
|
95
|
+
if schoon:
|
|
96
|
+
url = f"{url}?{urllib.parse.urlencode(schoon)}"
|
|
97
|
+
|
|
98
|
+
verzoek = urllib.request.Request(
|
|
99
|
+
url,
|
|
100
|
+
headers={
|
|
101
|
+
"X-Api-Key": self._api_key,
|
|
102
|
+
"Accept": "application/json",
|
|
103
|
+
"User-Agent": f"wozapi-python/{__version__}",
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
with urllib.request.urlopen(verzoek, timeout=self._timeout) as antwoord:
|
|
109
|
+
return json.loads(antwoord.read().decode("utf-8"))
|
|
110
|
+
except urllib.error.HTTPError as fout:
|
|
111
|
+
body = fout.read().decode("utf-8", errors="replace")
|
|
112
|
+
raise WozApiError(fout.code, _melding(body, fout.reason), body) from fout
|
|
113
|
+
except urllib.error.URLError as fout:
|
|
114
|
+
raise WozApiError(0, f"netwerkfout: {fout.reason}") from fout
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _melding(body: str, standaard: str) -> str:
|
|
118
|
+
"""Haalt de servermelding uit een JSON-foutbody; valt terug op de HTTP-reden."""
|
|
119
|
+
try:
|
|
120
|
+
data = json.loads(body)
|
|
121
|
+
except (ValueError, TypeError):
|
|
122
|
+
return standaard
|
|
123
|
+
if isinstance(data, dict):
|
|
124
|
+
for sleutel in ("message", "error", "title", "detail"):
|
|
125
|
+
waarde = data.get(sleutel)
|
|
126
|
+
if isinstance(waarde, str) and waarde.strip():
|
|
127
|
+
return waarde
|
|
128
|
+
return standaard
|