IDCanopy Developers
Umbrella APIAddress Autocomplete

Integration guide

The predict and resolve flow, client rules, errors and a minimal client

Flow

user types  ->  POST /predict {input, session?}  ->  {session, suggestions[], attribution}
                (repeat per keystroke, debounced, passing session back)
user picks  ->  POST /resolve {id, session}      ->  {address{...}}
                (the session ends here; start a new one for the next address)

Rules your client must follow

  1. Debounce input, at least 200 ms. Send nothing under the minimum length (3 characters by default); the service returns an empty list anyway.
  2. Keep the session. Take session from the first predict response and send it on every further predict and on the final resolve of that one address entry. Discard it after resolve.
  3. Discard stale responses. If you sent a later predict, ignore the results of earlier ones.
  4. Show attribution next to the suggestion list whenever it is not empty. This is a licence obligation, not a styling choice.
  5. Treat id as opaque. Do not parse it. Do not store or cache suggestion text. If you must keep a reference, keep the id only.
  6. Read address.precision. house means a house number was resolved. street or area means the user must still complete the address.

Authentication and transport

  • Header Authorization: Bearer <token> on every call, the token from POST /auth.
  • Paths are relative to the Umbrella base URL plus /address/autocomplete (pending verification of that sub-path). The route names below are relative to that.
  • JSON in both directions, UTF-8.
  • Calls from a browser need your origin to be on the service's allowed-origin list. The list applies to the whole service, not to a single key. Ask for yours to be added. Pending verification: the process for requesting an origin.

POST /predict

FieldTypeRequiredNotes
inputstring, max 200yesWhat the user has typed so far
sessionstring, max 64noFrom a previous response; omit to start a session. A value that is not letters and digits is silently replaced with a new session, not rejected
countriesarray of ISO 3166-1 alpha-2 codesnoRestricts the results to one or more countries, for example ["DE"] or ["DE", "FR"]. Omitted, null or [] means the deployment's default countries (currently ["DE", "AT"]); a country that is not enabled for the deployment returns 422. See Country and address type
languagestring, BCP 47noDefaults to de
nearobject {lat, lng}noBias results toward a point

The response carries session, up to 5 suggestions and attribution. suggestions is [], not an error, when the input is too short or nothing matches.

POST /resolve

FieldTypeRequiredNotes
idstring, max 512yesA suggestions[].id
sessionstringnoSend it, see rule 2
languagestringnoDefaults to de

The response carries address and verification.

All address string fields are present and can be "". lat and lng can be null.

verification

verification is null unless a second reference source is enabled on the service. It is a service-wide setting, not per key or per account. When it is present:

statusMeaningWhat to do
confirmedA second source agrees on postcode, city, house number and position (within 150 m)Accept
differsIt disagrees on the fields listed in differs: postal_code, city, house_number, locationShow the address and let the user confirm; do not auto-accept
unavailableNo second source answeredTreat as unverified, not as wrong

filled lists fields the first source left empty and the second supplied. They are already merged into address; values from the first source are never overwritten.

Errors

The body always has a detail field, but its shape depends on the error:

  • A string, for example {"detail": "Invalid or missing token."}. This covers 401, 404, 502 and the 422 for a country that is not enabled.
  • A list of objects, for field validation 422 (a field that is too long, a wrong type, a missing field). Each object has loc, msg and type.
StatusMeaningWhat to do
401Missing or invalid bearer tokenFetch a new token from POST /auth
404resolve only: the id is unknown or expiredRun predict again and let the user pick again
422A country that is not enabled (string detail), or field validation (list detail)Fix the request
502The address source is unavailableShow a try-again message. Do not mark the address invalid

Building the entry field

For the full sequence and a worked example, see Build your own UI.

Debounce and minimum length. Wait 200 to 300 ms after the last keystroke before calling predict, and send nothing while the trimmed text is shorter than the service minimum (3 characters by default). Shorter input returns an empty list, so a shorter threshold only wastes calls.

One session per address. Start without a session, keep the one predict returns, send it on every later predict and on resolve, then drop it. If the user clears the field and starts over, start a new session. A session that is not letters and digits is silently replaced, so a client that sends "session": null or a UUID with dashes gets a fresh session every call without noticing.

Empty results. suggestions: [] is a normal answer. Keep the field editable, show "no suggestions" or nothing, and let the user type the address by hand. Do not treat an empty list as an invalid address.

Retries. Only retry 502, and only a few times with a growing delay. 401 needs a new token, 404 needs a new predict, 422 needs a changed request; retrying any of these unchanged fails again. While a call is pending, new keystrokes should supersede it (rule 3), not queue behind it.

Keep the user's text. Fill the structured fields only after resolve. Until then the typed text is the user's own and must not be overwritten when suggestions arrive.

Privacy

What leaves your system: the text the user has typed so far, the optional countries, language and near position, and the session. The text goes to the service on every keystroke that passes the debounce, and the service passes it on to an upstream address source. Do not put anything into the field that is not an address, and do not send near unless the user has agreed to share a position. The upstream source is chosen on the service and is not part of the contract. Retention and the processing agreement for typed text are pending verification.

Accessibility for a custom UI

The widget follows the ARIA combobox pattern, and a custom field should do the same:

  • role="combobox" on the input, aria-autocomplete="list", aria-expanded kept in step with the list, aria-controls pointing at the list.
  • role="listbox" on the list and role="option" on each item, with aria-selected on the active one and aria-activedescendant on the input.
  • Keys: up and down move through the list, Enter picks the active suggestion, Esc closes the list. Enter with no active suggestion must still submit or move on as the form normally would.
  • Announce the number of suggestions in a polite live region, and render main_text and secondary_text as text, never as HTML.
  • Do not rely on colour alone for the active item, and keep the touch target of a suggestion at least 44 px high.

Mock

Mock data is invented: your own address will not be found. Try Haupt, Bahnhofstr 12 Wien, Schulg, 1010, Gartenweg München or Strasse Muenchen.

Mock answers predict and resolve on this portal at /mock/api/services/address/autocomplete, with no token. It follows the service's behaviour, with these limits:

  • A fixed dataset of about 3,000 invented streets in 67 German and Austrian cities. Mock covers these two countries only; that is the sample, not the coverage of the service. Real city and postcode pairs, invented street names, approximate coordinates. Nothing outside it is found.
  • Matching is case, umlaut and ß tolerant (strasse finds Straße), on street words and city names, and accepts a house number and a postcode: Hauptstr 12 Graz, Haupt 8010.
  • At most 5 suggestions, at least 3 characters, countries limited to DE and AT (the sample's countries), the session round trip, and the 422 shapes from above. id values look like mock:at-2421:12.
  • resolve returns precision: house when the id carries a number, otherwise street, and 404 for an id it does not know. verification is null; add ?scenario=verified for a confirmed result.
  • No bearer check and no rate limit; ?scenario=unauthorized returns the 401 shape. near and language are accepted and ignored. attribution is always empty.
  • The /v1/predict and /v1/resolve forms the widget calls are accepted too.

Minimal client

Plain JavaScript. BASE is the Umbrella base URL plus /address/autocomplete; KEY is your bearer token.

async function post(path, body, key) {
  const r = await fetch(BASE + path, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
    body: JSON.stringify(body),
  });
  if (!r.ok) {
    const { detail } = await r.json();
    throw new Error(typeof detail === 'string' ? detail : JSON.stringify(detail));
  }
  return r.json();
}

let session = null;

async function predict(text) {
  const res = await post('/predict', { input: text, session }, KEY);
  session = res.session;
  return res; // { session, suggestions, attribution }
}

async function resolve(id) {
  const res = await post('/resolve', { id, session }, KEY);
  session = null;
  return res.address;
}

A key used in a browser is visible to anyone on the page. Origin checks stop other sites from using it in a browser, not a script. If that is not acceptable, call the API from your own backend and keep the key there.

On this page