Boundaries

Boundaries part-of

Returns the boundaries (administrative, postal, timezone, protected areas and more) that contain a point or a known place.

Signed in? Open this endpoint in the dashboard playground, which uses your organization automatically. Signed out, use Try in Playground below with your API key.

GET
/boundaries/part-of

Authorization

queryapiKey<token>

Your API key from the dashboard, sent as ?apiKey=<key>.

Query Parameters

id?string

Deviation (unsupported): Geoapify hex place IDs are not accepted by this service; gp:addr, gp:tz and gp:iso IDs return an empty result (gp:tz:<tzid> is returned as place_id on timezone features but does not resolve as an id).

Length3 <= length <= 2048
lat?number

Latitude of the place. Alternative to id; provide together with lon.

Range-90 <= value <= 90
lon?number

Longitude of the place. Alternative to id; provide together with lat.

Range-180 <= value <= 180
osm_id?integer

Numeric OpenStreetMap object identifier. Alternative to id; use together with osm_type.

Range1 <= value
osm_type?string

OpenStreetMap object type used with osm_id: n for node, w for way, or r for relation (case-insensitive).

Value in"r""w""n"
boundaries?array<|string|>

Boundary types to return. Multiple values are comma-separated; duplicates are collapsed and there is no cap on the number of types. Defaults to administrative when omitted. The special value all (not an enum item) expands to every type below, including the types without a data layer.

Deviation (extra): protected_area, national_park, aboriginal_lands, census, school_district, forest, hazard and regional_park are our additions, and all is ours; Geoapify caps the list at 10 types.

Deviation (empty): religious, municipality, barony, town, health and historic:administrative are accepted but have no data layer (layer: false in the response layers).

Items1 <= items
geometry?string

Geometry representation for returned boundaries. point returns representative points and is the default. The geometry_* values return simplified Polygon or MultiPolygon geometry at the specified accuracy in meters.

Deviation (approximated): simplification uses PostGIS ST_SimplifyPreserveTopology with a tolerance of N meters converted to degrees (N / 111320), so accuracy differs slightly from Geoapify's.

Default"point"
Value in"point""geometry_1000""geometry_5000""geometry_10000"
lang?string

Language used for boundary names and address fields (ISO 639-1). Uses the OSM name:<lang> tag and falls back to the default name when a boundary has no translation.

Default"en"
Value in"ab""aa""af""ak""sq""am""ar""an""hy""as""av""ae""ay""az""bm""ba""eu""be""bn""bh""bi""bs""br""bg""my""ca""ch""ce""ny""zh""cv""kw""co""cr""hr""cs""da""dv""nl""en""eo""et""ee""fo""fj""fi""fr""ff""gl""ka""de""el""gn""gu""ht""ha""he""hz""hi""ho""hu""ia""id""ie""ga""ig""ik""io""is""it""iu""ja""jv""kl""kn""kr""ks""kk""km""ki""rw""ky""kv""kg""ko""ku""kj""la""lb""lg""li""ln""lo""lt""lu""lv""gv""mk""mg""ms""ml""mt""mi""mr""mh""mn""na""nv""nb""nd""ne""ng""nn""no""ii""nr""oc""oj""cu""om""or""os""pa""pi""fa""pl""ps""pt""qu""rm""rn""ro""ru""sa""sc""sd""se""sm""sg""sr""gd""sn""si""sk""sl""so""st""es""su""sw""ss""sv""ta""te""tg""th""ti""bo""tk""tl""tn""to""tr""ts""tt""tw""ty""ug""uk""ur""uz""ve""vi""vo""wa""cy""wo""fy""xh""yi""yo""za"

Response Body

Boundaries containing the requested place (possibly an empty FeatureCollection).

application/json
  1. response

GeoJSON FeatureCollection of the boundaries that contain the requested place, smallest first (administrative), then postal codes. Empty features when nothing matches, every requested type has no data layer, or the Place ID has no boundary geometry.

type*unknown
features*array<>
layers?array<>

One entry per requested type: layer = a data layer exists; within = how many of its boundaries contain the point.

Example Request
curl -X GET 'https://api.data.graphitelab.ai/v1/boundaries/part-of?id=gp%3Aosm%3Ar161816&lat=39.7684&lon=-86.1581&osm_id=161816&osm_type=r&boundaries=administrative%2Cpostal_code&geometry=point&lang=en'
Example Response
{  "type": "FeatureCollection",  "features": [    {      "type": "Feature",      "properties": {        "name": "Indianapolis",        "country": "United States",        "continent": "North America",        "country_code": "us",        "state": "Indiana",        "state_code": "IN",        "iso3166_2": "US-IN",        "county": "Marion County",        "county_district": "Center Township",        "city": "Indianapolis",        "lon": -86.0932472869693,        "lat": 39.7798447,        "place_id": "gp:osm:r18438530",        "datasource": {          "sourcename": "openstreetmap",          "attribution": "© OpenStreetMap contributors",          "license": "Open Database License",          "url": "https://www.openstreetmap.org/copyright",          "raw": {            "osm_id": 18438530,            "osm_type": "r",            "admin_level": 8,            "wikidata": "Q6346",            "wikipedia": "en:Indianapolis"          }        }      },      "geometry": {        "type": "Point",        "coordinates": [          -86.093247,          39.779845        ]      },      "bbox": [        -86.3281207,        39.6321626,        -85.9380401,        39.9275253      ]    },    {      "type": "Feature",      "properties": {        "name": "Center Township",        "country": "United States",        "continent": "North America",        "country_code": "us",        "state": "Indiana",        "state_code": "IN",        "iso3166_2": "US-IN",        "county": "Marion County",        "county_district": "Center Township",        "lon": -86.13982193886923,        "lat": 39.75229160000001,        "place_id": "gp:osm:r21364355",        "datasource": {          "sourcename": "openstreetmap",          "attribution": "© OpenStreetMap contributors",          "license": "Open Database License",          "url": "https://www.openstreetmap.org/copyright",          "raw": {            "osm_id": 21364355,            "osm_type": "r",            "admin_level": 7,            "wikidata": "Q5059398",            "wikipedia": "en:Center Township, Marion County, Indiana"          }        }      },      "geometry": {        "type": "Point",        "coordinates": [          -86.139822,          39.752292        ]      },      "bbox": [        -86.1973736,        39.7216856,        -86.0824946,        39.8255186      ]    }  ]}

GET /v1/boundaries/part-of answers "what boundaries is this place inside?" Give it a Place ID, a coordinate, or an OSM object, and it returns the containing city, township, county, state and country, plus optionally the ZIP-like postal area, the timezone, or OSM polygons such as a national park. Use it to enrich a location with its jurisdictions, or to fetch a boundary polygon for a map.

How it works

The gateway answers this route directly from PostGIS; no geocoding Engine or Valhalla is involved.

  1. It resolves the lookup to a point. A lat/lon pair is used as is. A gp:osm: Place ID or osm_id/osm_type pair is looked up in the Nominatim placex table and reduced to a representative point on its surface. A gp:pc: Place ID is looked up in the postal polygons.
  2. administrative: every OSM boundary with admin_level 2 to 11 whose polygon covers the point, smallest first. For an administrative Place ID, only that boundary and its ancestors are kept.
  3. postal_code: the Census ZCTA5 (US) or StatCan FSA (Canada) polygon covering the point.
  4. timezone: the timezone-boundary-builder polygon covering the point, with place_id gp:tz:<tzid>.
  5. Other OSM polygon layers (neighborhood, place, region, political, historic, protected_area, national_park, aboriginal_lands, census, school_district, forest, hazard, regional_park, religious_administration, low_emission_zone, public_transport, traditional): every polygon of that type covering the point. protected_area includes leisure=nature_reserve; national_park is boundary=national_park, or a nature reserve named "... National Park".
  6. religious, municipality, barony, town, health and historic:administrative are accepted but have no data layer: they return nothing.
  7. boundaries=all expands to every type, and there is no cap on how many types you list (duplicates are collapsed). The top-level layers array reports each requested type with layer (a data layer exists) and within (how many of its boundaries contain the point).
  8. Names for each feature (state, county, city, ...) come from the chain of containing administrative boundaries.

Data sources: OpenStreetMap (Geofabrik US and Canada extract, imported by Nominatim), Census ZCTA5, StatCan FSA boundaries, and timezone-boundary-builder (ODbL).

Quick start

curl -s "https://api.data.graphitelab.ai/v1/boundaries/part-of?lat=39.7684&lon=-86.1581&apiKey=$GRAPHITE_API_KEY"

Response (trimmed to the first feature; the full response also has Center Township, Marion County, Indiana and the United States):

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Indianapolis",
        "country": "United States",
        "country_code": "us",
        "state": "Indiana",
        "state_code": "IN",
        "iso3166_2": "US-IN",
        "county": "Marion County",
        "county_district": "Center Township",
        "city": "Indianapolis",
        "lon": -86.0932472869693,
        "lat": 39.7798447,
        "place_id": "gp:osm:r18438530",
        "datasource": {
          "sourcename": "openstreetmap",
          "attribution": "© OpenStreetMap contributors",
          "license": "Open Database License",
          "url": "https://www.openstreetmap.org/copyright",
          "raw": { "osm_id": 18438530, "osm_type": "r", "admin_level": 8 }
        }
      },
      "geometry": { "type": "Point", "coordinates": [-86.093247, 39.779845] },
      "bbox": [-86.3281207, 39.6321626, -85.9380401, 39.9275253]
    }
  ]
}

Parameters

Use exactly one lookup method: id, lat with lon, or osm_id with osm_type.

NameTypeRequiredWhat it does
idstring (3 to 2048 chars)One lookup methodPlace ID of an administrative boundary (gp:osm:r161816) or postal boundary (gp:pc:US-46204). Recommended.
latnumber (-90 to 90)With lonLatitude of the place.
lonnumber (-180 to 180)With latLongitude of the place.
osm_idinteger (1 or more)With osm_typeNumeric OpenStreetMap object ID.
osm_typestring: r, w, nWith osm_idOSM object type (case-insensitive).
boundariescomma-separated list, or allNoBoundary types to return, no cap on the count. Defaults to administrative. all expands to every type. Includes our extra types protected_area, national_park, aboriginal_lands, census, school_district, forest, hazard, regional_park. Types without a data layer return nothing.
geometrypoint, geometry_1000, geometry_5000, geometry_10000Nopoint (default) returns a representative point. geometry_N returns a Polygon or MultiPolygon simplified to about N meters.
langISO 639-1 codeNoLanguage for names. Uses the OSM name:<lang> tag, falling back to the default name. Default en.

Full parameter reference

Response

The response is a GeoJSON FeatureCollection with one feature per containing boundary. Administrative features come smallest first (city before county before state before country).

FieldMeaning
layersOne entry per requested type: { type, layer, within }. layer is false for types without a data layer; within is how many of that type's boundaries contain the point.
properties.boundary_typeThe boundary type the feature was returned for. Non-administrative OSM features have no admin_level.
properties.place_idOur Place ID, gp:<kind>:<key>. Administrative boundaries are gp:osm:<n|w|r><osm id>; postal boundaries are gp:pc:<country>-<code>. Pass it as id to this and other endpoints.
properties.nameBoundary name in lang. For postal boundaries, the code itself.
properties.state, county, city, ...Names of the containing boundaries, mapped from OSM admin_level (4 state, 5 or 6 county, 7 county district, 8 city, 9 city district, 10 suburb, 11 neighbourhood).
properties.lon, latA representative point on the boundary surface (not the centroid).
properties.postcode, postal_codePostal boundaries only.
properties.datasourceWhere the boundary came from, with the attribution you must show to end users. openstreetmap, census-zcta5, statcan-fsa or timezone-boundary-builder (raw.tzid). For OSM raw carries admin_level (administrative boundaries only) and, when present, wikidata, wikipedia and ISO3166-2.
geometryA Point by default, or the simplified Polygon or MultiPolygon with geometry_N.
bboxBounding box [min lon, min lat, max lon, max lat].

This endpoint has no rank object, distances or times.

Differences from Geoapify

  • empty: religious, municipality, barony, town, health and historic:administrative are accepted but have no data layer (layer: false in layers). The X-Boundaries-Note header is sent only when at least one requested type has no data layer: "Some requested boundary types have no data layer: see layers in the response (layer: false)."

  • extra: the types protected_area, national_park, aboriginal_lands, census, school_district, forest, hazard and regional_park, the value boundaries=all, no cap on the number of types (Geoapify allows 10), the layers summary and boundary_type.

  • empty: optional descriptive fields (formatted, address_line1, address_line2, categories, name_international, population, the timezone descriptor object, ...) are never returned. A timezone boundary feature is returned when you request boundaries=timezone.

  • unsupported: id resolves only gp:osm: and gp:pc: Place IDs. gp:addr:, gp:tz:, gp:iso: and Geoapify hex IDs return an empty FeatureCollection (gp:tz:<tzid> is a returned place_id on timezone features but is not an input). Malformed gp: IDs return 400.

  • extra: place_id uses our gp:<kind>:<key> format, and datasource describes the OSM, ZCTA5, FSA or timezone-boundary-builder source.

  • approximated: geometry_N simplification uses PostGIS ST_SimplifyPreserveTopology with a tolerance of N / 111320 degrees, so accuracy differs slightly from Geoapify.

US and Canada notes

  • Administrative boundaries are OSM, so levels are sparse and vary by place. Indianapolis returns a city and a township, while the Montreal example returns a city and an urban agglomeration as county.

  • US postal boundaries are Census ZCTA5, which approximate ZIP codes but are not USPS ZIPs. PO-box-only ZIPs have no polygon.

  • Canadian postal boundaries are StatCan FSA (the first three characters, like H3B). Full six-character postal codes have no polygon here.

  • The lang parameter helps in bilingual areas: Canadian boundaries often have name:fr.

More examples

Montreal with administrative and postal boundaries as simplified polygons. The FSA feature has datasource.sourcename statcan-fsa.

curl -s "https://api.data.graphitelab.ai/v1/boundaries/part-of?lat=45.5019&lon=-73.5674&boundaries=administrative,postal_code&geometry=geometry_5000&apiKey=$GRAPHITE_API_KEY"

Errors and limits

StatusMeaning
400Bad request: no lookup method or more than one, osm_id without osm_type, invalid osm_type, unknown boundaries value, out-of-range lat/lon, a malformed gp: ID.
401Missing or invalid API key.
429Rate limited.
500Internal error.

An ID or OSM object that does not resolve, or a point outside any boundary, returns 200 with an empty FeatureCollection, not 404.

Known gateway issue: the sibling endpoint /v1/boundaries/consists-of takes about 11.5 seconds per call because it scans every administrative boundary without a bounding-box prefilter. part-of is not affected. The progress notes also record cold-engine latency outliers of 6 to 13 seconds right after a deploy.

Try in Playground (signed in to your Graphite Lab organization). Signed out, use the paste-your-key widget on the reference page.