---
title: "Address suggestions (autocomplete)"
method: GET
path: "/suggest"
tags: ["Suggest"]
---

# Address suggestions (autocomplete)

`GET /suggest`

## Request

- Base URL: `https://api.acuris-geo.com`
- URL: `https://api.acuris-geo.com/suggest`
- Auth: one of:
  - API key in header `X-Acuris-Key`
  - HTTP bearer
  - API key in header `X-API-Key`

Autocomplete/typeahead. Returns ranked standardized addresses (with
`formatted_address`, and `lat`/`lng` whenever the reference row carries
a coordinate — never invented) for the partial input `q` (or `prefix`)
and `country`.

**Authentication is required — there is no anonymous access.** A caller
must present *either*:
  - a paid API key (Stripe `X-Acuris-Key` / `Authorization: Bearer`,
    `X-API-Key`, or RapidAPI gateway) — full access, billed against the
    key's own transaction pool; or
  - a short-lived **widget token** (`X-Acuris-Widget-Token` header, or
    `?t=`) minted by `/widget/token` — origin-locked to `acuris-geo.com`
    pages, so not usable by third-party integrations (partners use API
    keys). Widget callers are capped at 15 results and a per-token call
    quota.

Requests with neither are rejected: `403` (no widget origin / no token)
or `401` (token invalid, expired, or quota exhausted).

**Metering here depends on the `AV_GEO_REQUIRE_SIGNUP` launch flag** (see **Free tier
(verified account)** above for the full explanation — this endpoint never draws from the
UK daily cap described there, on either side of the flag, and draws from the 1,000/day
free-tier allowance only once the flag is on):
  - **As of this writing, flag off in production:** a genuinely valid API key is
    completely exempt from metering. Anonymous widget-token callers are bounded only by a
    per-IP flask-limiter soft cap of **5/second, 60/minute, 500/day** (per gunicorn
    worker — a first-line burst backstop, not an authoritative cross-fleet limit); the
    handler does not authenticate against a quota pool or decrement one in this state.
  - **Once the flag is on:** a registered key (any class except the policy-exempt
    `stripe`/`integration`/`partner`) draws from the same shared recurring
    **1,000/day** allowance as `/validate`/`/geocode`/`/reverse` (`free_limit_reached`, `403`, once exhausted); anonymous callers are capped at
    **40/day per IP** instead (`rate_limit_exceeded`, `429`, once exhausted), and the
    flask-limiter decorator's daily figure drops from 500 to 40 at the same moment as a
    redundant first-line backstop.
`country: "gbr"` requests carry one further, independent per-IP velocity cap
(`PAF_SUGGEST_IP_RPM`, **600/minute** by default — 10x that for a genuinely valid, non-test
API key; allowlisted keys exempt), which degrades to an empty result set
(`{"suggestions": [], "limit": "reached"}`) rather than an error, on either side of the flag.

**UK note:** `country: "gbr"` is served exclusively from
`https://paf.acuris-geo.com` (identical path, parameters, and auth).
Requests for `gbr` sent to `api.acuris-geo.com` return **400**
`{"error": "country_not_served_by_this_endpoint", "country": "gbr",
"use_instead": "https://paf.acuris-geo.com"}`.

**Postcode-first input:** the query may lead with (or be) a postal
code. GBR: a full or partial postcode returns every delivery point at
that postcode, each labelled with `building_name` /
`organisation_name` / `department`; a premise name may precede the
postcode (`Gate House DL12 0NQ`). DEU / FIN / SWE / NLD / CAN: a
leading postcode scopes the street search (`67549 Eckenbert`,
`M5V 3L9`). JPN: a postcode returns chōme suggestions; then pass
`zip`, `oaza`, `chome` with the house-number keystrokes to get
banchi-gō lot suggestions.

Suggestions do not carry `udprn` / `uprn` / `county`. To obtain the
Royal Mail / OS identifiers for a chosen suggestion, submit it to
`/validate` (returns `uprn`, `udprn`) or use `/postcode-lookup`.

Suggestion `lat`/`lng` are the reference row's own point, unrefined.
`/validate` may refine that point for the same address (France: a
point lying just outside its building is moved onto the building
footprint, by at most 8 m, and the response carries
`coord_snapped: true`). List rows never carry that refinement; for
the refined point, submit the chosen suggestion to `/validate`.

Typeahead is tuned and verified for **19 countries** today — GBR, USA,
CAN, DEU, AUT, CHE, FRA, BEL, NLD, LUX, DNK, SWE, FIN, IRL, PRT, ESP,
SGP, JPN, HKG. Any `/geocode` country code is accepted; countries
outside this set may return empty results.

## Query parameters

- `q` string
- `prefix` string
- `country` string, required
- `limit` integer
- `state` string
- `lat` number
- `lng` number
- `zip` string
- `oaza` string
- `chome` string

## Response `200`

Ranked list of address suggestions matching the partial input.

- object
  - `suggestions` SuggestItem[]
    - `street` string
    - `house_number` string
    - `city` string: Spain (`/suggest`): for the officially bilingual municipalities the suggestion prints the Castilian name by default (`Alicante`, `Elche`, `San Sebastián`, `Castellón de la Plana`, `Valencia`); if your query already spells the regional form (`Alacant`, `Elx`, `Donostia`, `València`) that spelling is kept. Postcode and coordinates are the same either way, and submitting the suggestion to `/validate` matches the same address. `/validate` itself echoes the spelling you sent. Sweden, city + postcode without a street (`/validate`, `/geocode`): the stored spelling of the locality (`Goteborg`, `göteborg` -> `GÖTEBORG`), as on full matches; an English or variant name (`Gothenburg`) is returned in the stored spelling too, and `/validate` lists `City` under `corrections`.
    - `state` string: Present for countries with regions (e.g. USA, CAN, AUS, MYS).
    - `postcode` string
    - `postcode_formatted` string: The postcode as it is written on a letter, in a field of its own, for integrations that look the postcode up elsewhere. Sweden: `412 50` (`postcode` stays `41250`). Where no written form differs, it equals `postcode`. `postcode` itself is unchanged. Returned by `/validate`.
    - `country` string
    - `formatted_address` string: Country-specific pretty-printed form, multi-line.
    - `street_type` string: The thoroughfare type as its own element, where the reference data carries it separately: Malaysia (`street_type: "Jalan"`, `street: "Melor 1"`), and Canada / France where the split comes straight from the reference columns (France is type-first — `street_type: "Place"`, `street_name: "de la Comédie"`). NOT emitted for the USA, which would need a USPS-suffix parse, nor for German, Dutch, Danish, Swedish or Swiss addresses, where the type is fused into the word (*Eckenbertstraße*) and splitting it is a morphological judgement rather than a field read.
    - `street_name` string: Canada and France: the bare street name with the type and any directional removed. Companion to `street_type` / `street_suffix`; `street` always holds the full form.
    - `street_suffix` string: Canada: the directional element (N, SW, …) as its own field.
    - `street_id` string: France: the reference data's stable identifier for the thoroughfare.
    - `building_name` string: UK postcode-mode: labels each delivery point at the postcode.
    - `level_number` string: Denmark (`etage`) and Hong Kong (floor). Same unambiguity rule as `building_name`, and additionally requires a confirmed house number.
    - `unit_identifier` string: Denmark (`dør`), the Netherlands (sub-address) and Hong Kong (flat). Same unambiguity rule as `level_number`.
    - `ine_municipality` string: Spain: the 5-digit INE municipality code of the matched address (leading zeros preserved — always a string).
    - `nis_code` string: Belgium: the NIS municipality code of the matched address.
    - `statistical_sector` string: Belgium: the 9-character Statbel statistical sector of the matched address (the trailing hyphen is part of the code, e.g. `"41002A00-"`). This is the key the Belgian enrichment joins on.
    - `county` string: UK only (`country: "gbr"`). Traditional/postal county, derived from the Royal Mail PAF postcode → county map.
    - `udprn` string: UK only. Royal Mail Unique Delivery Point Reference Number (PAF) — stable identifier for the delivery point.
    - `uprn` string: UK only. Ordnance Survey Unique Property Reference Number. Present when the address matches OS Open UPRN.
    - `unit` string: Sub-building unit, echoed from the caller's input (reference rows carry no unit, so this value is never invented). Rendered into `formatted_address` per country convention (e.g. Canada Post `23-4 Vata Crt`). When the reference data cannot confirm the unit at the matched premise, the response lists `"unit"` in the top-level `unverified_fields` array — the premise match itself still stands. Spain: staircase / floor / door in any common spelling (`ESC.1-PISO 1, PTA.B`, `1º B`, `3º izq`, `bajo`) are normalised to one form, e.g. `Esc. 1, 1º B`; see `unit_verified` / `unit_check`. Latvia: the flat (dzīvoklis) in any common spelling (`Brīvības iela 100 - 5`, `100-5`, `100 dz. 5`, `100 kv. 5`) is returned as the flat number, e.g. `5`, and rendered as `Brīvības iela 100 - 5`; a korpuss (`10k2`, `10 k. 2`) is part of the house number (`10 k-2`), never a unit.
    - `suburb` string: New Zealand. The NZ Post suburb line between street and post town (`68 Rintoul Street / Newtown / Wellington 6021`). Filled from the matched reference row — including when the caller typed only the city. A suburb typed in the city slot is a verified match, never a `City` correction.
    - `district` string: Neighborhood / sub-locality where the country convention carries one (e.g. the Turkish mahalle, Austrian Bezirk sublocality). Enriched from the reference row even when the caller omitted it.
    - `province` string: Italy only. Two-letter province sigla (MI, RM, …) for the mandatory Poste Italiane locality line (`20067 PAULLO MI`).
    - `dependent_street` string: UK only (Royal Mail PAF dependent thoroughfare). The minor road the house number is addressed on (`18 Latium Close, Holywell Hill`); the parent thoroughfare stays in `street`.
    - `dependent_locality` string: UK (Royal Mail PAF): village / dependent locality printed between the thoroughfare and the post town. Malaysia: the Taman / Kampung sub-locality line, printed above the postcode line.
    - `double_dependent_locality` string: UK only (PAF). Sub-locality below `dependent_locality`.
    - `administrative_county` string: UK only. PAF Administrative County (local authority). Present when extended UK fields are enabled; on some postcodes it is the only county held (`county` blank).
    - `welsh` object: UK only, Wales. The Welsh-language form of the SAME delivery point (Royal Mail ships Welsh addresses bilingually): `street`, `city` (post town, e.g. CAERDYDD for CARDIFF) and, where they exist, translated `dependent_locality` / `double_dependent_locality` / `dependent_street`. Present on an English-form match when a Welsh counterpart exists. Typing the Welsh form is a verified match, never a `Street`/`City` correction.
    - `english` object: UK only, Wales. Mirror of `welsh`: the English-language form, present when the matched row is the Welsh one. At most one of `welsh`/`english` appears.
    - `lat` number: Omitted when the reference row carries no coordinate — never invented.
    - `lng` number: Omitted when the reference row carries no coordinate — never invented.
    - `count` integer: Number of reference premises merged into this row; present when more than one. Germany (`deu`): when the query carries no house number, the printed `formatted_address` of such a row is street-level (street, postcode and town, no house number) once the street-level label is enabled; `house_number` and the coordinates (v=1) are those of one representative premise, and `GET /suggest/expand` lists the street's premises, up to 50 per page (`offset` selects the next page; `has_more` / `next_offset` in the answer), up to 400 per street.
    - `locality` string: Secondary locality, for countries whose reference data carries no postal code column (e.g. IRL).
    - `organisation_name` string: UK postcode-mode: organisation at the delivery point.
    - `department` string: UK postcode-mode: department within the organisation.
    - `city_kanji` string: JPN: kanji display form of `city`.
    - `state_kanji` string: JPN: kanji display form of `state`.
    - `street_kanji` string: JPN: kanji display form of `street`.
    - `jpn_zip` string: JPN: feed back as the `zip` parameter for the stage-2 banchi-gō lookup.
    - `jpn_oaza_norm` string: JPN: feed back as the `oaza` parameter for the stage-2 lookup.
    - `jpn_chome` string: JPN: feed back as the `chome` parameter for the stage-2 lookup.
    - `building` string: SGP: the building name of the suggested premise. When the query matched a building name, this is the name that was matched (a building known under more than one name shows the one you typed). Never part of `formatted_address`. Also returned on `v=2` list rows.
    - `tenant` string: SGP: when the query matched the name of a business at the premise (e.g. `mcdonalds`), that name as listed. A business with several outlets returns up to five of its premises, each with its own `building`. Never part of `formatted_address`. Also returned on `v=2` list rows.
  - `hint` string: Optional guidance shown when `suggestions` is empty (e.g. the caller typed only a house number). For a country where autocomplete is not available yet, an empty list carries a hint saying so (e.g. "Address autocomplete is not available for Vietnam yet. Address validation (/validate) is supported.").
  - `autocomplete_supported` boolean: Present (and `false`) only on an empty answer for a country where address autocomplete is not available yet; use `POST /validate` for that country instead. Absent on every other response. The status stays 200 and any rows the engine does find are still returned.
  - `limit` string: Set to `"reached"` when a velocity/abuse cap emptied the result set; back off and retry after ~60s.

## Other responses

- `400`: Unsupported country — body `{"error": "Unsupported country"}`. Also returned for `country: gbr` on this host (body: `country_not_served_by_this_endpoint` with `use_instead` — see the UK note above).
- `401`: Widget token invalid, expired, or quota exhausted.
- `403`: No paid key and no valid widget token / non-widget origin. Key-level 403s: `{"error": "key_blocked", "message"}` when the API key has been blocked (the `message` says why), and `{"error": "ip_not_allowed", "message", "ip"}` when the key is restricted to approved source IP addresses and this request came from another one (`ip` is the address we saw). Source-IP restriction is optional and set up per key on request via support.
- `429`: Too many requests (anonymous limit or WAF/limiter)

---

[API](https://skmtc.dev/acuris-geo/apis/acuris-geo-api.md) · [All operations](https://skmtc.dev/acuris-geo/apis/acuris-geo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/acuris-geo/apis/acuris-geo-api/revisions/8547b31dd96a?raw)
