teryt24.pl

teryt24.pl · Dokumentacja API

Walidacja adresu w jednym zapytaniu

GET /v1/validate odpowiada na pytanie formularza, nie tylko na pytanie bazy: „co ten adres oznacza, jak pewni jesteśmy i czego jeszcze brakuje?”. Zwraca rozłożony adres (miejscowość, ulica, numer budynku, lokal, kod pocztowy, współrzędne) z identyfikatorami rejestru (SYM, SYM_UL, kody TERC), ocenę dopasowania każdego pola (exact / normalized / partial / ambiguous / not-found), werdykt (valid / corrected / ambiguous / incomplete / invalid) i listę rozbieżności z kodem każdej z nich.

Trzy formy wejścia, jak w GET /v1/geocode: polami (sym + street + number), wg nazwy miejscowości (locality) albo jednym ciągiem (address). Jedna różnica: numer domu jest tu OPCJONALNY — brak numeru to adres NIEKOMPLETNY, a nie błędne zapytanie. Werdykt o budynku pochodzi z tego samego potoku co w /v1/geocode, więc oba endpointy nie mogą się ze sobą rozminąć.

Dwie zasady, których endpoint nie łamie: kod pocztowy jest ZAWSZE kodem dopasowanego punktu adresowego (nigdy zgadywany z miejscowości ani z sąsiedztwa), a składnik, którego rejestry nie zawierają, zostaje null i mówi o tym wprost.

GET /v1/validate

Jedno zapytanie: walidowany adres wraz z oceną dopasowania każdego pola. Kod pocztowy weryfikowany jest wobec punktu adresowego, nigdy nadpisywany.

Sprawdź na żywo: /v1/validate?sym=0965016&street=06114&number=5

Parametry
NazwaWymaganyOpis
address—Free-text Polish address ('Wrocław-Fabryczna, ul. Eugeniusza Horbaczewskiego 35'), parsed into locality/street/number internally and resolved through the same pipeline as GET /v1/geocode. Mutually exclusive with sym, number, street, streetName, locality and postalCode.
sym—Locality SYM (7 digits, from /v1/localities). Required unless `address` or `locality` is given; mutually exclusive with locality. An unknown SYM answers 404.
locality—Locality/city NAME (diacritics-insensitive) instead of a SYM — resolved through the locality index. Several matches → verdict 'ambiguous' with a population-ordered shortlist in `candidates.localities` (capped at 50, `localitiesTruncated` when cut). Mutually exclusive with sym and address.
postalCode—The caller's claim about the postal code. With `locality` it also narrows the candidates (the code's officially served localities); in every form it is VERIFIED against the matched building point's own code — a disagreement is reported as the `postal_code_mismatch` issue and the register's code is returned. Requires sym or locality.
number—House number ('21A'). OPTIONAL here (unlike GET /v1/geocode): a missing number makes the address INCOMPLETE, and the response says so instead of rejecting the request.
street—Street SYM_UL (5 digits, from /v1/streets). Mutually exclusive with streetName.
streetName—Street name prefix (diacritics-insensitive; 'rynek' finds 'ul. Rynek'). A typed 'ul.'/'al.' prefix is stripped before the search and kept as the claimed street type. Several matches → verdict 'ambiguous' with candidates in `candidates.streets`.
limit—Maximum matches (1–50).

Przykład

Adres potwierdzony (polami)

curl "https://teryt24.pl/v1/validate?sym=0965016&street=06114&number=5"

Odpowiedź:

{
  "verdict": "valid",
  "address": {
    "locality": {
      "sym": "0965016", "name": "Opole", "type": "96", "typeLabel": "miasto",
      "province": "OPOLSKIE", "county": "Opole", "municipality": "Opole",
      "provinceCode": "16", "countyCode": "61", "municipalityCode": "01",
      "lat": 50.679359517696255, "lon": 17.917784269176924,
      "coordSource": "prg", "population": 127676, "populationSource": null
    },
    "street": { "id": "06114", "name": "ul. Grobla", "cecha": "ul." },
    "houseNumber": "5", "unit": null, "postalCode": "45-236",
    "lat": 50.69898395560351, "lon": 17.959149341026354
  },
  "match": { "locality": "exact", "street": "exact", "houseNumber": "exact", "postalCode": "exact" },
  "issues": [],
  "sources": { "locality": "teryt", "street": "ulic", "addressPoint": "prg", "postalCode": "prg" }
}

Jednym ciągiem — nazwa ulicy znormalizowana

curl "https://teryt24.pl/v1/validate?address=Opole,%20ul.%20Grobla%205"

Odpowiedź (skrócona — pokazano pierwsze wiersze):

{
  "verdict": "corrected",
  "address": {
    "locality": { "sym": "0965016", "name": "Opole", "type": "96", "typeLabel": "miasto" },
    "street": { "id": "06114", "name": "ul. Grobla", "cecha": "ul." },
    "houseNumber": "5", "unit": null, "postalCode": "45-236",
    "lat": 50.69898395560351, "lon": 17.959149341026354
  },
  "match": { "locality": "exact", "street": "normalized", "houseNumber": "exact", "postalCode": "exact" },
  "issues": [
    {
      "code": "street_normalized", "field": "street",
      "message": "The street name was matched after normalization (case, diacritics, punctuation or the street-type prefix).",
      "expected": "ul. Grobla", "actual": "Grobla"
    }
  ],
  "sources": { "locality": "teryt", "street": "ulic", "addressPoint": "prg", "postalCode": "prg" },
  "query": { "city": "Opole", "street": "Grobla", "number": "5", "numbers": ["5"], "range": false, "cityResolved": true }
}

Nazwa miejscowości niejednoznaczna

curl "https://teryt24.pl/v1/validate?locality=Nowa%20Wie%C5%9B&number=5"

Odpowiedź (skrócona — pokazano pierwsze wiersze):

{
  "verdict": "ambiguous",
  "address": { "locality": null, "street": null, "houseNumber": null, "unit": null, "postalCode": null, "lat": null, "lon": null },
  "match": { "locality": "ambiguous", "street": "not-found", "houseNumber": "ambiguous", "postalCode": "not-found" },
  "issues": [
    { "code": "locality_ambiguous", "field": "locality", "message": "Several localities carry that name. Let the user pick one, or narrow the query with the postal code." }
  ],
  "candidates": {
    "localities": [
      { "sym": "0057477", "name": "Nowa Wieś", "type": "01", "typeLabel": "wieś", "province": "MAŁOPOLSKIE", "county": "oświęcimski", "municipality": "Kęty", "provinceCode": "12", "countyCode": "13", "municipalityCode": "04", "population": 3648 },
      { "sym": "0316909", "name": "Nowa Wieś", "type": "01", "typeLabel": "wieś", "province": "MAŁOPOLSKIE", "county": "myślenicki", "municipality": "Dobczyce", "provinceCode": "12", "countyCode": "09", "municipalityCode": "01", "population": 413 }
    ],
    "localitiesTruncated": true
  }
}

Kod pocztowy się nie zgadza

curl "https://teryt24.pl/v1/validate?sym=0965016&street=06114&number=5&postalCode=00-950"

Odpowiedź (skrócona — pokazano pierwsze wiersze):

{
  "verdict": "corrected",
  "address": { "postalCode": "45-236" },
  "match": { "locality": "exact", "street": "exact", "houseNumber": "exact", "postalCode": "partial" },
  "issues": [
    {
      "code": "postal_code_mismatch", "field": "postalCode",
      "message": "The claimed postal code differs from the code the matched building point carries. The register's code is returned.",
      "expected": "45-236", "actual": "00-950"
    }
  ]
}
Odpowiedzi
StatusOpis
200The validation answer: `verdict` (valid | corrected | ambiguous | incomplete | invalid), the structured `address`, the per-field `match` kinds, the `issues` that explain every discrepancy, the `candidates` for an unresolved ambiguity, and `sources` (which dataset each field came from).
400Invalid query parameters.
404Unknown locality SYM.
429Rate 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.
500Unexpected server failure (e.g. the database is unreachable). The body is deliberately generic — error detail lives in the server logs, never in the response.
503Address dataset not available (POST /admin/ingest-prg).

Gotowe do podpięcia wdrożenie całego tego workflow (podpowiedzi miejscowości i ulic, walidacja, przegląd wyniku) znajdziesz jako widget: /assets/address-widget.js — zobacz działające demo.

Przeglądaj dane

Te same dane mają strony w przeglądarce — karty miejscowości, ulic i kodów pocztowych:

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.

Atrybucja jest warunkiem użycia. Wyświetlając wyniki w aplikacji, stronie, mapie lub raporcie, pokaż: 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.