wozapi 1.0.0__py3-none-any.whl

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.
@@ -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
@@ -0,0 +1,4 @@
1
+ wozapi.py,sha256=4_N_CBZzSyQgkkzORhP9YpSPBJg29d-YWhsbd3o2bWY,4726
2
+ wozapi-1.0.0.dist-info/METADATA,sha256=Pc_yNNgoimmXeFkc8hAWwu-jN4MPg_qtVCdNs2E80Vc,2774
3
+ wozapi-1.0.0.dist-info/WHEEL,sha256=THafob7ofN-NsuMN7Mg4qZyHaQI7KkD-QlcQatYhXPo,87
4
+ wozapi-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.3
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
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