Kody pocztowe w API
Trzy tryby wyszukiwania: po kodzie lub prefiksie (q=), kody obsługujące jedną miejscowość (locality=SYM) i najbliższe kody dla współrzędnych (lat+lon). Każdy wiersz niesie hierarchię TERC, a gdy rozwiąże się do jednej miejscowości — jej SYM, rodzaj i ludność.
Karta /v1/postal-codes/{code} dokłada agregaty PRG (GUGiK): liczbę punktów adresowych, ulice przy budynkach i środek obszaru. POST /v1/postal-codes/bulk przyjmuje do 100 kodów naraz — czyszczenie danych bez festiwalu round-tripów.
GET /v1/postal-codes
Cyfry i myślniki są wymienne („00-950”, „00950”, prefiks „00-9”). format=geojson zwraca punkty PRG.
Sprawdź na żywo: /v1/postal-codes?q=00-002
| Nazwa | Wymagany | Opis |
|---|---|---|
q | — | Postal code in any form: '00-950', '00950', or a prefix of either ('00-9', '009'); non-digits are ignored. Required unless locality or lat+lon is given. |
locality | — | Locality SYM (7 digits, as returned by /v1/localities): the postal codes serving it — PRG official set first, then the PNA name ladder; one row per code, named for the requested locality (synthesized from the registry when GeoNames never paired it). Mutually exclusive with q and lat+lon; sym/type/population always describe the requested locality. |
lat | — | WGS84 latitude (-90..90). Together with lon triggers nearest mode: the codes whose official PRG centroids are closest, distance-sorted (each with distanceKm, centroidLat/centroidLon, addressCount, streetCount). Mutually exclusive with q and locality. A blank value ('?lat=') is treated as absent — it does not trigger the mode. |
lon | — | WGS84 longitude (-180..180). Must be given together with lat. |
limit | — | Maximum results (1–50). |
offset | — | Skip the first N results (0-based, max 10000) to page past the limit. |
format | — | 'geojson' answers an RFC 7946 FeatureCollection (row points — the PRG centroids in nearest mode — in [lon,lat] order) instead of the JSON envelope. |
Przykład
Wyszukiwanie po kodzie (q=)
curl "https://teryt24.pl/v1/postal-codes?q=00-002"Odpowiedź:
{
"postalCodes": [
{ "code": "00-002", "city": "Warszawa", "province": "MAZOWIECKIE", "county": "Warszawa", "municipality": "Warszawa", "municipalityKind": "gmina miejska, miasto stołeczne", "lat": 52.2358, "lon": 21.0101, "sym": "0988796", "citySlug": null, "type": "95", "typeLabel": "dzielnica m.st. Warszawy", "population": 1702139 }
],
"meta": { "total": 1, "offset": 0, "limit": 10 }
}| Status | Opis |
|---|---|
200 | Successful response — the row shape depends on the mode: the q/locality DTO for prefix and locality lookups, the nearest DTO (code, distanceKm, centroid, counts) for lat+lon. |
400 | Invalid query parameters. |
429 | Rate limit exceeded (60 requests/min/IP) or a plan's monthly quota exhausted. Includes `Retry-After` and `X-RateLimit-*` headers; the body's `code` distinguishes the two kinds. |
500 | Unexpected server failure (e.g. the database is unreachable). The body is deliberately generic — error detail lives in the server logs, never in the response. |
503 | Postal-code dataset not available (generate data/pna CSV via pnpm fetch:pna); the nearest mode additionally requires the PRG ingest. |
GET /v1/postal-codes/{code}
Pełny rekord kodu: wszystkie miejscowości (PNA) plus agregaty PRG — 404 dla kodu spoza rejestru.
Sprawdź na żywo: /v1/postal-codes/00-002
| Nazwa | Wymagany | Opis |
|---|---|---|
code path | ✓ | Postal code in the display ('59-700') or digits ('59700') form. |
Przykład
Kod 00-002 (Warszawa)
curl "https://teryt24.pl/v1/postal-codes/00-002"Odpowiedź:
{
"code": "00-002",
"rows": [
{ "code": "00-002", "city": "Warszawa", "province": "MAZOWIECKIE", "county": "Warszawa", "municipality": "Warszawa", "municipalityKind": "gmina miejska, miasto stołeczne", "lat": 52.2358, "lon": 21.0101, "sym": "0988796", "citySlug": null, "type": "95", "typeLabel": "dzielnica m.st. Warszawy", "population": 1702139 }
],
"prg": { "addressCount": 1, "streetCount": 1, "centroidLat": 52.23579285110347, "centroidLon": 21.010129613434586, "streets": ["ul. Świętokrzyska"] }
}| Status | Opis |
|---|---|
200 | Successful response. |
400 | Invalid query parameters. |
404 | Unknown postal code. |
429 | Rate limit exceeded (60 requests/min/IP) or a plan's monthly quota exhausted. Includes `Retry-After` and `X-RateLimit-*` headers; the body's `code` distinguishes the two kinds. |
500 | Unexpected server failure (e.g. the database is unreachable). The body is deliberately generic — error detail lives in the server logs, never in the response. |
503 | Postal-code dataset not available (generate data/pna CSV via pnpm fetch:pna). |
POST /v1/postal-codes/bulk
Wiersz bulk jest bajt-w-bajt odpowiedzią pojedynczego GET /v1/postal-codes/{code}; nieznany kod wraca jako wiersz status:error z kodem HTTP, który dostałby pojedynczy GET.
Treść żądania (JSON)
| Nazwa | Wymagany/typ | Opis |
|---|---|---|
codes | array (1–100) | Kody w formacie wyświetlanym („59-700”) albo cyfrowym („59700”). |
Przykład
Dwa kody jednym żądaniem
curl -X POST "https://teryt24.pl/v1/postal-codes/bulk" \
-H "Content-Type: application/json" \
-d '{"codes":["00-002","59-700"]}'{"codes":["00-002","59-700"]}Odpowiedź (skrócona — pokazano pierwsze wiersze):
{
"results": [
{ "code": "00-002", "status": "ok", "rows": [ { "code": "00-002", "city": "Warszawa", "province": "MAZOWIECKIE", "county": "Warszawa", "municipality": "Warszawa", "municipalityKind": "gmina miejska, miasto stołeczne", "lat": 52.2358, "lon": 21.0101, "sym": "0988796", "citySlug": null, "type": "95", "typeLabel": "dzielnica m.st. Warszawy", "population": 1702139 } ], "prg": { "addressCount": 1, "streetCount": 1, "centroidLat": 52.23579285110347, "centroidLon": 21.010129613434586, "streets": ["ul. Świętokrzyska"] } },
{ "code": "59-700", "status": "ok", "rows": [ { "code": "59-700", "city": "Bolesławice", "province": "DOLNOŚLĄSKIE", "county": "bolesławiecki", "municipality": "Bolesławiec", "municipalityKind": "gmina wiejska", "lat": 51.2798, "lon": 15.5485, "sym": "0188937", "citySlug": null, "type": "01", "typeLabel": "wieś", "population": 876 } ] }
]
}| Status | Opis |
|---|---|
200 | Per-code results in request order: `status:"ok"` rows carry the detail endpoint's body (code, rows, prg); `status:"error"` rows carry the error the single GET would have answered with. |
400 | Invalid query parameters. |
429 | Rate limit exceeded (60 requests/min/IP) or a plan's monthly quota exhausted. Includes `Retry-After` and `X-RateLimit-*` headers; the body's `code` distinguishes the two kinds. |
500 | Unexpected server failure (e.g. the database is unreachable). The body is deliberately generic — error detail lives in the server logs, never in the response. |
Przeglądaj dane
Każdy kod pocztowy ma stronę informacyjną z listą miejscowości i danymi PRG:
Wszystkie endpointy /v1 zwracają JSON, obsługują CORS i są objęte dokumentem openapi.json. Interaktywna wersja tej referencji: /docs.
Limity: 60 zapytań/min na IP bez klucza; klucz API (nagłówek X-API-Key) dostaje własny kubełek. Po przekroczeniu endpointy odpowiadają HTTP 429 z nagłówkiem Retry-After. Szczegóły: limity i klucze · zasady użycia.
Dane: GUS TERYT, punkty adresowe PRG (GUGiK), kody pocztowe GeoNames — przez teryt24.pl z linkiem do zasad użycia. Użycie wyłącznie po stronie serwera jest zwolnione.