Structured geocoding and place lookup
If your addresses already live in columns (a CRM export, a checkout form, a CSV with street, city, zip), don’t glue them back into one string. Send the fields. Plaza skips address parsing entirely, so the same input always gives the same answer, and each field is matched against the column it belongs to.
Endpoint
Section titled “Endpoint”POST /api/v1/geocode/structuredRequest body
Section titled “Request body”At least one of address, locality, region or postalcode is required.
| Field | Type | Default | Description |
|---|---|---|---|
address | string | — | House number and street. Both 1600 Pennsylvania Ave and Rue de Rivoli 99 work. Without a number it’s treated as a street. |
neighbourhood | string | — | Neighbourhood or suburb. |
locality | string | — | City, town or village. |
county | string | — | County or district. |
region | string | — | State, province or region. |
postalcode | string | — | Postal or ZIP code. Spaces and case are ignored. |
country | string | — | ISO 3166-1 alpha-2 code (US) or country name. |
focus | object | — | GeoJSON Point. Nearer results rank higher. Anything that isn’t a valid Point is a 400. |
country_code | string | — | ISO 3166-1 alpha-2 code. Only return results in this country, at every fallback step. country is a field to match; country_code is a hard filter. |
bbox | object | — | GeoJSON Polygon. Results must fall inside its bounding box. A value that isn’t a valid Polygon is a 400. |
layers | string or array | — | Only return these layers. layer works as an alias. |
boundary_gid | string | — | Only return results inside this way or relation polygon. See restricting to a boundary. |
limit | int | 10 | Max results (1–50). |
lang | string | — | BCP 47 language tag for result names. |
datasets | string or array | — | Also match features of these datasets against the most specific field you send (address, then neighbourhood, locality and so on). See geocoding with datasets. |
dataset_name_field | string | — | Dataset property to match instead of properties.name. |
Basic request
Section titled “Basic request”curl -X POST https://plaza.fyi/api/v1/geocode/structured \ -H "Content-Type: application/json" \ -H "x-api-key: $PLAZA_API_KEY" \ -d '{ "address": "1600 Pennsylvania Avenue NW", "locality": "Washington", "region": "DC", "postalcode": "20500", "country": "US" }'{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-77.0365, 38.8977] }, "properties": { "gid": "osm:way:238241022", "display_name": "1600 Pennsylvania Avenue NW, Washington, DC 20500", "house_number": "1600", "street": "Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "postcode": "20500", "layer": "address", "match_type": "exact", "confidence": 1.0, "accuracy": "point", "source": "structured" } } ]}The response is the same GeoJSON as forward geocoding, with the same confidence, match_type, accuracy, layer and gid fields, and the same format options (geojson, csv, ndjson).
How matching works
Section titled “How matching works”| Field | Matched against |
|---|---|
address | House number exactly; street by normalized name (“Ave” = “Avenue”) or trigram similarity |
locality | City, exact or trigram (so “Pariss” still finds Paris) |
region | State, exact or trigram |
postalcode | Postcode, ignoring spaces and case |
country | ISO code or country name |
Results rank by how many of your fields they match exactly. An address that matches street, city, state and ZIP beats one that matches only street and city. A hit that needed a typo-tolerant match comes back as match_type: "fuzzy" with lower confidence.
neighbourhood and county aren’t stored on addresses. They narrow the admin-area steps below.
Partial input
Section titled “Partial input”You don’t need a street. Plaza returns the most specific thing you described:
{"locality": "Springfield", "region": "Illinois"}returns Springfield, Illinois itself (layer: "locality"), not every address in it.{"postalcode": "20500"}returns the center of that postal code (layer: "postalcode",accuracy: "centroid").
Those are match_type: "exact", because that’s what you asked for. Coarser fields constrain finer ones: locality: "Paris", country: "FR" only accepts a Paris inside France. Admin names match exactly and ignore case, so pass full names (“Illinois”, not “IL”).
Fallback
Section titled “Fallback”If the address doesn’t exist, Plaza tries the street, then the postal code, then each admin field you gave, most specific first. Those results are match_type: "fallback" and never score above 0.5 confidence.
{"address": "999 Nowhere Road", "locality": "Springfield", "region": "Illinois"}returns Springfield, Illinois with "match_type": "fallback". Check match_type before you put a delivery pin on it.
Place lookup
Section titled “Place lookup”Every geocoding result has a gid. Fetch up to 50 places by GID in one call:
GET /api/v1/place?ids=osm:node:21154906,osm:relation:62422curl "https://plaza.fyi/api/v1/place?ids=osm:node:21154906,osm:relation:62422" \ -H "x-api-key: $PLAZA_API_KEY"Features come back in the order you asked for them, with id set to the GID, plus categories and the admin areas that contain the place:
{ "type": "Feature", "id": "osm:node:21154906", "geometry": { "type": "Point", "coordinates": [13.3777, 52.5163] }, "properties": { "gid": "osm:node:21154906", "display_name": "Brandenburger Tor", "layer": "poi", "category": "entertainment", "subcategory": "attraction", "categories": ["entertainment", "entertainment:attraction"], "match_type": "exact", "confidence": 1.0, "accuracy": "point", "admin_hierarchy": [ { "admin_level": 2, "name": "Deutschland", "name_en": "Germany", "country_code": "DE", "type": "country" }, { "admin_level": 4, "name": "Berlin", "name_en": "Berlin", "country_code": null, "type": "state" } ] }}| Parameter | Description |
|---|---|
ids | Required. Comma-separated GIDs, at most 50. |
lang | BCP 47 language tag for names. |
format | json (default), geojson, csv, ndjson. |
GIDs look like osm:{node|way|relation}:{osm_id}. Plaza’s own address and place rows also have osm:address:{id} and osm:place:{id}, but those IDs change when the data is re-imported, so store element GIDs.
GIDs that match nothing are left out. If none match you get a 404. A malformed GID, or more than 50, is a 400.
PlazaQL
Section titled “PlazaQL”Leave out the query text and pass fields as keywords:
geocode( address: "1600 Pennsylvania Ave", locality: "Washington", region: "DC", postalcode: "20500", country: "US");Place lookup is place_lookup(), with GIDs as positional strings or ids: [...]:
place_lookup("osm:node:21154906", "osm:relation:62422");Both return point sets, so you can search around them:
$gate = place_lookup("osm:node:21154906");search(node, amenity: "cafe").around(300, $gate).limit(10);Billing
Section titled “Billing”Structured geocoding and place lookup are standard requests, like forward geocoding. One call is one request, however many fields, GIDs or datasets you send.