API kodów pocztowych, TERYT i PRG
Darmowe REST API do danych adresowych Polski. Kody pocztowe, TERYT SIMC/ULIC, punkty adresowe PRG (GUGiK), geokodowanie WGS84, dopasowywanie i walidacja adresów. Odpowiedzi w JSON, bez rejestracji dla limitów testowych, klucz API dla produkcji.
Quickstart — pierwszy request w 30 sekund
Wszystkie endpointy są pod https://api.adresy.app/api/v1. Odpowiedzi to JSON kodowany UTF-8. Metoda GET dla odczytu, POST dla operacji wsadowych i dopasowywania.
curl -s "https://api.adresy.app/api/v1/match?q=Rynek+1,+Wrocław"
Przykładowa odpowiedź:
{
"results": [
{
"input": "Rynek 1, Wrocław",
"status": "found",
"match": {
"miejscowosc": "Wrocław",
"ulica_norm": "Rynek",
"nr_budynku": "1",
"kod_pocztowy": "50-106",
"teryt_simc": "0986283",
"teryt_ulic": "19357",
"gmina": "Wrocław",
"powiat": "Wrocław",
"wojewodztwo": "DOLNOŚLĄSKIE",
"lat": 51.10893,
"lon": 17.03262,
"score": 0.98
}
}
]
}
Najprostszy sposób — GET /api/v1/match?q= — przyjmuje dowolny „brudny" adres w jednym parametrze i zwraca dopasowanie z rejestru PRG.
Przykładowa odpowiedź (skrócona):
{
"kod": "50-079",
"found": true,
"total": 412,
"ulic": 7,
"results": [
{
"miejscowosc": "Wrocław",
"ulica": "Ruska",
"teryt_simc": "0986283",
"teryt_ulic": "18834",
"gmina": "Wrocław",
"powiat": "Wrocław",
"wojewodztwo": "dolnośląskie",
"liczba_adresow": 58,
"numery_przyklad": ["11","13","15","17","19","21","23","25","27","29"]
}
]
}
Uwierzytelnianie i limity
- Bez klucza API
- 3 zapytania / minutę (na IP). Wystarczające do szybkich testów.
- Klucz API (Free)
- 30 zapytań / minutę, 3 000 / miesiąc. Darmowe konto + klucz API.
- Klucz API (Business)
- 600 zapytań / minutę, 10 mln / miesiąc, SLA 99,9%.
- Enterprise
- Dedykowana infrastruktura, webhooki PRG, on-premise.
curl -s "https://api.adresy.app/api/v1/lookup/kod-pocztowy?kod=00-001" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxx"
Limit przekroczony? Odpowiedź 429 Too Many Requests z nagłówkiem Retry-After w sekundach. Szczegóły w artykule o limitach.
1. Wyszukiwanie po kodzie pocztowym
GET /api/v1/lookup/kod-pocztowy
Zwraca wszystkie ulice i grupy numerów budynków przypisane do danego kodu pocztowego. Dane pochodzą z rejestru PRG (GUGiK), agregowane per ulica.
Parametry
| Nazwa | Typ | Wymagane | Opis |
|---|---|---|---|
kod | string | tak | Kod pocztowy w formacie NN-NNN, np. 50-079. |
limit | int | nie | Maksymalna liczba ulic w odpowiedzi. Domyślnie 200, maksymalnie 500. |
Przykład — curl
curl -s "https://api.adresy.app/api/v1/lookup/kod-pocztowy?kod=00-001&limit=50"
Przykład — Python
import httpx
r = httpx.get(
"https://api.adresy.app/api/v1/lookup/kod-pocztowy",
params={"kod": "00-001"},
headers={"X-API-Key": "sk_live_xxx"},
timeout=10,
)
data = r.json()
print(f"Znaleziono {data['total']} adresów na {data['ulic']} ulicach")
Przykład — JavaScript (fetch)
const res = await fetch(
"https://api.adresy.app/api/v1/lookup/kod-pocztowy?kod=00-001",
{ headers: { "X-API-Key": "sk_live_xxx" } }
);
const data = await res.json();
2. Kod pocztowy dla adresu
GET /api/v1/lookup/kod-dla-adresu
Odwrotne zapytanie — podaj miejscowość, ulicę i numer, otrzymasz kod pocztowy (lub zakres kodów, jeśli ulica obejmuje kilka). Idealne do walidacji formularzy e-commerce.
curl -s "https://api.adresy.app/api/v1/lookup/kod-dla-adresu" \
--data-urlencode "miejscowosc=Wrocław" \
--data-urlencode "ulica=Rynek" \
--data-urlencode "nr=1" \
-G
{
"found": true,
"kod_pocztowy": "50-106",
"miejscowosc": "Wrocław",
"ulica": "Rynek",
"nr": "1",
"teryt_simc": "0986283",
"teryt_ulic": "19357"
}
3. TERYT — SIMC i ULIC
GET /api/v1/lookup/teryt
Zwraca kody TERYT (SIMC dla miejscowości, ULIC dla ulic) wraz z przynależnością administracyjną: gmina, powiat, województwo. Obsługuje wyszukiwanie po nazwie miejscowości, nazwie ulicy lub bezpośrednio po kodzie SIMC.
curl -s "https://api.adresy.app/api/v1/lookup/teryt" \
--data-urlencode "miejscowosc=Kraków" \
--data-urlencode "ulica=Floriańska" -G
{
"found": true,
"results": [{
"simc": "0950463",
"nazwa": "Kraków",
"typ": "miasto",
"gmina": "Kraków",
"powiat": "Kraków",
"wojewodztwo": "małopolskie",
"kody_admin": "12612011",
"ulice": [{
"ulic": "05123",
"cecha": "ul.",
"nazwa_1": "Floriańska",
"nazwa_pelna": "ul. Floriańska"
}]
}]
}
4. Dekodowanie TERYT
GET /api/v1/lookup/teryt/decode
Zamienia kody TERYT na pełne dane adresowe. Obsługuje automatyczną detekcję (SIMC — 7 cyfr, ULIC — 5 cyfr) i format złożony SIMC#ULIC#NR.
# Auto-detect kodu
curl -s "https://api.adresy.app/api/v1/lookup/teryt/decode?kod=0986283"
# Pełny adres
curl -s "https://api.adresy.app/api/v1/lookup/teryt/decode?kod=0986283%2318834%2315"
5. Adresy w pobliżu punktu (geokodowanie odwrotne)
GET /api/v1/lookup/blisko
Zwraca najbliższe punkty adresowe dla podanych współrzędnych WGS84. Silnik: PostGIS, indeks GiST, promień podajesz w metrach.
curl -s "https://api.adresy.app/api/v1/lookup/blisko?lat=51.1089&lon=17.0326&radius=200&limit=5"
{
"found": true,
"count": 5,
"results": [
{
"miejscowosc": "Wrocław",
"ulica": "Rynek",
"nr_budynku": "1",
"kod_pocztowy": "50-106",
"distance_m": 12.4,
"lat": 51.10893,
"lon": 17.03262
}
]
}
5b. Geokodowanie odwrotne — GET /api/v1/reverse
GET /api/v1/reverse
Podaj współrzędne WGS84, otrzymaj jeden najbliższy punkt adresowy PRG z odległością w metrach. Endpoint zoptymalizowany pod wysokie obciążenie: indeks KNN PostGIS, czas odpowiedzi <10 ms. Zasięg: cała Polska (49–54,9°N, 14,1–24,2°E).
Różnica od /lookup/blisko: /reverse zwraca jeden rekord z polem score (1,0 = dokładnie na adresie, 0,0 = na granicy promienia), /lookup/blisko zwraca listę wielu adresów w promieniu bez score.
| Parametr | Typ | Domyślnie | Opis |
|---|---|---|---|
lat | float | — | Szerokość geograficzna WGS84 |
lon | float | — | Długość geograficzna WGS84 |
radius | int | 500 | Promień w metrach (1–5000) |
limit | int | 1 | Liczba wyników (1–10) |
curl -s "https://api.adresy.app/api/v1/reverse?lat=52.2297&lon=21.0122&radius=500"
{
"found": true,
"count": 1,
"results": [
{
"miejscowosc": "Warszawa",
"ulica": "Nowy Świat",
"nr_budynku": "18",
"kod_pocztowy": "00-373",
"powiat": "Warszawa",
"wojewodztwo": "mazowieckie",
"teryt_simc": "0918123",
"dzielnica": "Śródmieście",
"distance_m": 34.2,
"score": 0.93,
"lat": 52.22951,
"lon": 21.01198
}
]
}
Typowe zastosowania: lokalizacja GPS w aplikacji mobilnej → nazwa ulicy, kliknięcie na mapę → pełny adres, geofencing, IoT (czujniki z GPS), walidacja czy punkt jest w zasięgu adresu.
6. Autouzupełnianie formularza — GET /lookup/autofill
GET /api/v1/lookup/autofill
Ostatni krok trójstopniowego autocomplete: po wybraniu przez użytkownika miejscowości (/miejscowosci), ulicy (/ulice) i numeru (/numery) — wywołaj autofill, aby jednym zapytaniem wypełnić wszystkie pozostałe pola formularza: kod pocztowy, gminę, powiat, województwo i współrzędne GPS.
Wymaga klucza API z planem Starter lub wyższym (capability autocomplete).
Parametry
| Parametr | Typ | Opis |
|---|---|---|
sym | string, wymagany | Kod SIMC miejscowości (z /miejscowosci) |
sym_ul | string, opcjonalny | Kod ULIC ulicy (z /ulice); pominąć dla adresów bez nazwy ulicy |
nr | string, wymagany | Numer budynku (z /numery) |
curl -s "https://api.adresy.app/api/v1/lookup/autofill?sym=0986283&sym_ul=18834&nr=1" \
-H "X-API-Key: twoj-klucz"
{
"found": true,
"miejscowosc": "Wrocław",
"ulica": "Rynek",
"nr_budynku": "1",
"kod_pocztowy": "50-106",
"gmina": "Wrocław",
"powiat": "Wrocław",
"wojewodztwo": "dolnośląskie",
"teryt_simc": "0986283",
"teryt_ulic": "18834",
"lat": 51.110051,
"lon": 17.031717
}
Gdy adres nie istnieje w PRG:
{ "found": false }
7. Szybkie dopasowanie adresu — GET /match?q=
GET /api/v1/match
Najprostszy endpoint — podaj adres jako tekst w parametrze q, otrzymasz dopasowanie z pełnym TERYT, kodem pocztowym i współrzędnymi. Idealny do integracji formularzy, walidacji adresów w locie i autouzupełniania.
Parametry
| Nazwa | Typ | Wymagane | Opis |
|---|---|---|---|
q | string | tak | Adres do dopasowania, np. Rynek 1, Wrocław lub ul. Marszalkowska 1 Warszawa. |
min_score | float | nie | Minimalny score dopasowania (0-1). Domyślnie 0.6. |
wojewodztwo | string | nie | Ograniczenie do województwa (np. dolnośląskie). |
Przykład — curl
curl -s "https://api.adresy.app/api/v1/match?q=Rynek+1,+Wrocław"
Przykład — JavaScript
const res = await fetch(
"https://api.adresy.app/api/v1/match?q=" + encodeURIComponent("Rynek 1, Wrocław"),
{ headers: { "X-API-Key": "sk_live_xxx" } }
);
const data = await res.json();
console.log(data.results[0].match.kod_pocztowy);
Odpowiedź
{
"results": [
{
"input": "Rynek 1, Wrocław",
"status": "found",
"match": {
"miejscowosc": "Wrocław",
"ulica_norm": "Rynek",
"nr_budynku": "1",
"kod_pocztowy": "50-106",
"teryt_simc": "0986283",
"teryt_ulic": "19357",
"gmina": "Wrocław",
"powiat": "Wrocław",
"wojewodztwo": "DOLNOŚLĄSKIE",
"lat": 51.10893,
"lon": 17.03262,
"score": 0.98,
"match_layer": "EXACT"
}
}
]
}
Pola status: found (jednoznaczne dopasowanie), ambiguous (kilka kandydatów, zwrócony najlepszy), not_found (brak dopasowania).
8. Dopasowywanie adresów — POST /match
POST /api/v1/match
Najmocniejszy endpoint. Bierze „brudny" adres (literówki, skróty, bez kodu) i dopasowuje go do rzeczywistego punktu PRG z pełnym TERYT, kodem pocztowym i współrzędnymi. Używa fuzzy-match (RapidFuzz) + heurystyk skrótów polskich.
curl -s -X POST "https://api.adresy.app/api/v1/match" \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_xxx" \
-d '{
"adres": "ul. Marsz Pilsudskiego 5a, Wroclaw",
"min_score": 80
}'
{
"match": true,
"score": 94,
"result": {
"miejscowosc": "Wrocław",
"ulica_wejsciowa": "Marsz Pilsudskiego",
"ulica_dopasowana": "Marszałka Józefa Piłsudskiego",
"nr_budynku": "5A",
"kod_pocztowy": "50-033",
"teryt_simc": "0986283",
"teryt_ulic": "12873",
"gmina": "Wrocław",
"powiat": "Wrocław",
"wojewodztwo": "dolnośląskie",
"lat": 51.10012,
"lon": 17.03159,
"srid": 4326
},
"candidates": 3
}
9. Walidacja pliku CSV/XLSX
POST /api/v1/match/file
Prześlij plik z listą adresów (kolumny: miejscowosc, ulica, nr, kod), otrzymasz ten sam plik z dopisanymi kolumnami: dopasowanie, TERYT, współrzędne, score. Format wejściowy: CSV (UTF-8) lub XLSX, do 100 tys. wierszy na request.
curl -s -X POST "https://api.adresy.app/api/v1/match/file" \
-H "X-API-Key: sk_live_xxx" \
-F "[email protected]" \
-F "min_score=82" \
-o wynik.csv
Tryb streaming — wyniki lecą NDJSON zanim całość się zakończy:
curl -N -X POST "https://api.adresy.app/api/v1/match/stream" \
-H "X-API-Key: sk_live_xxx" \
-F "[email protected]"
Kody błędów
| Status | Znaczenie | Działanie |
|---|---|---|
200 | OK | — |
400 | Nieprawidłowe parametry | Sprawdź pole detail w JSON. |
401 | Brak / zły klucz API | Nagłówek X-API-Key. |
404 | Nie znaleziono | Pole found: false jest normą, nie błędem. |
429 | Rate limit | Odczytaj Retry-After, zwolnij. |
500 | Błąd serwera | Ponów z backoffem. Zgłoś przez /kontakt/. |
FAQ — najczęstsze pytania developerów
Czy API jest darmowe?
Skąd pochodzą dane adresowe?
Jak często aktualizowane są dane?
Czy mogę używać API komercyjnie?
Jak zbudować autocomplete adresu i autouzupełnianie formularza?
GET /api/v1/miejscowosci?q=wrocł — użytkownik wpisuje miasto, dostajesz listę z kodami SIMC; (2) GET /api/v1/ulice?sym=0986283&q=ryn — po wybraniu miasta pobierasz ulice (kody ULIC); (3) GET /api/v1/numery?sym=0986283&sym_ul=18834 — po wybraniu ulicy pobierasz numery budynków. Na końcu: GET /api/v1/lookup/autofill?sym=0986283&sym_ul=18834&nr=1 — jednym zapytaniem wypełniasz wszystkie pola: kod pocztowy, gmina, powiat, województwo, współrzędne GPS. Wszystkie cztery endpointy wymagają planu Starter+.Jak działa endpoint /match i kiedy go używać?
POST /api/v1/match przyjmuje „brudny" ciąg tekstowy adresu (literówki, polskie skróty typu „ul.", „pl.", brak kodu pocztowego) i dopasowuje go do kanonicznego rekordu PRG. Używa algorytmów fuzzy-match (RapidFuzz, odległość Levenshteina) plus heurystyk dla polskich skrótów. Używaj, gdy masz dane od użytkownika (formularz, import CSV, OCR). Dla czystych danych z wiarygodnego źródła szybszy jest /lookup/kod-dla-adresu.Jakie są limity batcha /match/file?
/api/v1/match/stream (NDJSON, streaming odpowiedzi — klient może przetwarzać wyniki równolegle z uploadem) lub podziel plik. Czas przetwarzania to ~200-500 wierszy na sekundę w zależności od jakości danych wejściowych.Czy zwracacie współrzędne w WGS84?
lat, lon są w układzie WGS84 (EPSG:4326). Wewnętrznie dane PRG przechowywane są w PUWG 1992 (EPSG:2180) i konwertowane w locie przez PyProj. Jeśli potrzebujesz natywnego układu polskiego, dodaj parametr srid=2180.Co zrobić przy 429 Too Many Requests?
Retry-After (liczba sekund), zaczekaj i ponów. Dla klienta produkcyjnego zaimplementuj wykładniczy backoff: 1s, 2s, 4s, 8s, 16s. Jeśli widzisz 429 przy normalnym obciążeniu, zwiększ plan lub rozważ cache lokalny — wiele zapytań o ten sam kod pocztowy można trzymać w Redis/memcached na 24h (dane zmieniają się rzadko).Czy jest OpenAPI / Swagger?
https://api.adresy.app/openapi.json, interaktywny Swagger UI pod /docs, Redoc pod /redoc. Możesz wygenerować klienta w dowolnym języku przez openapi-generator.Czy dane są zgodne z RODO?
Jak dodać obsługę adresów historycznych (np. poprzednie nazwy ulic)?
nazwa_2 w rekordzie ULIC zawiera poprzednią nazwę ulicy (gdy istnieje). Endpoint /lookup/teryt zwraca oba warianty. Aliasy historyczne (Stalingradu → Marszałkowska, etc.) przechowujemy osobno — dostępne w planie Business przez parametr historyczne=true.Mogę hostować API u siebie (on-premise)?
Jaka jest różnica między /api/v1/reverse a /lookup/blisko?
GET /api/v1/reverse to endpoint geokodowania odwrotnego — podaj współrzędne GPS, otrzymaj jeden (lub kilka) najbliższy punkt adresowy PRG z polem score (1,0 = idealnie na adresie, 0,0 = na granicy promienia). Optymalizowany pod wysoką przepustowość: indeks KNN PostGIS, czas odpowiedzi poniżej 10 ms. GET /api/v1/lookup/blisko zwraca listę wszystkich adresów w zadanym promieniu bez scoringu — przydatne gdy potrzebujesz wszystkich sąsiadów punktu. Do geokodowania odwrotnego (GPS → nazwa ulicy) używaj /reverse.Jak zintegrować geokodowanie odwrotne z aplikacją mobilną?
navigator.geolocation.getCurrentPosition() (web) lub CLLocationManager/FusedLocationProvider (iOS/Android), następnie wywołaj GET /api/v1/reverse?lat={lat}&lon={lon}. Endpoint działa w promieniu do 5 km i zwraca adres z dokładnością punktu adresowego PRG (centroid budynku). Czas odpowiedzi <10 ms nadaje się do użycia w pętli odświeżania GPS bez cachowania.Następne kroki
- Przewodnik po API dla początkujących — krok po kroku, Python, Make.com, n8n, Google Sheets.
- Wypróbuj endpoint w aplikacji — interaktywny UI bez pisania kodu.
- Weź klucz API — plan Free bezpłatnie.
- Czym jest PRG? — kontekst danych źródłowych.
- Czym jest TERYT? — SIMC, ULIC, TERC w praktyce.
- Wszystkie narzędzia — wyszukiwarki gotowe do użycia.