# Autocomplete

The autocomplete helper turns a partial UK address into suggestions as the user types, then turns the chosen suggestion into a full address. It debounces keystrokes, drops stale requests and caches recent suggestions.

autocomplete.tsts

```ts
import { createIdpcClient } from "@ideal-postcodes/sdk";
import { createAutocomplete } from "@ideal-postcodes/sdk/autocomplete";

const client = createIdpcClient({ apiKey: "ak_test" });
const autocomplete = createAutocomplete({ client });

const suggest = async (query: string) => {
  const hits = await autocomplete.find({ query });
  if (!hits) return; // superseded by a newer find, or cancelled
  const hit = hits[0];
  if (!hit) return; // no matches
  const address = await autocomplete.resolve({ hit });
  console.log(address.line_1);
};

await suggest("9 Malyons Road");

// Call when the input is removed or the component unmounts.
autocomplete.cancel();
```

## Find suggestions

Call `find` with the partial address as `query`. It waits for typing to pause, then resolves to an array of hits. An empty array means nothing matched.

`find` also takes any other [`findAddress`](/docs/sdks/typescript/endpoints/find-address.md) parameter in the same object, such as `limit`, `context` or a filter. See [filter and bias](/docs/sdks/typescript/filter-and-bias.md) to restrict or rank suggestions by postcode, post town or location.

A newer `find` resolves the previous pending call with `undefined` and aborts its request. `cancel()` does the same without starting another. Superseded calls never reject, so check for `undefined` and return early.

## Switch country

Load the countries your key can search with [`keyAvailability`](/docs/sdks/typescript/endpoints/key-availability.md), show them in a picker, then pass the chosen code as `context`. A key can be licensed for several countries, such as the UK (`GBR`) and Ireland (`IRL`). The check needs only the API key, so it can run in the browser.

country-switch.tsts

```ts
import { createIdpcClient, keyAvailability } from "@ideal-postcodes/sdk";
import { createAutocomplete } from "@ideal-postcodes/sdk/autocomplete";

const apiKey = "ak_test";
const client = createIdpcClient({ apiKey });
const autocomplete = createAutocomplete({ client });

const { data } = await keyAvailability({ client, path: { key: apiKey } });
const { contexts, context } = data.result;
for (const country of contexts) console.log(country.emoji, country.description, country.iso_3);

// Start with the country that matches the user's IP address, if any.
let country = context || contexts[0]?.iso_3;
await autocomplete.find({ query: "9 Malyons Road", context: country });

// When the user picks another country, search again with its code.
country = "IRL";
await autocomplete.find({ query: "1 Main Street, Dublin", context: country });
```

Each entry in `contexts` has `iso_3` (the `context` code), `iso_2`, `description` and `emoji`. `context` is the licensed country that best matches the caller's IP address, or an empty string when none does.

## Resolve a suggestion

Pass the hit to `resolve`. It requests the full address from [`resolveAddress`](/docs/sdks/typescript/endpoints/resolve-address.md) at once, without a debounce.

`resolve` returns the flat `Address` model. Use `native` for dataset-specific fields and narrow the union before accessing them. See the [API reference](https://openapi.ideal-postcodes.co.uk) for field definitions.

## Cost

Suggestions are free. Each `resolve` costs one lookup. The API rate limits, then suspends, integrations that request suggestions without resolving any. The default limit is 3,000 suggestion requests per 5 minutes for each key and IP address.

## Options

| Option       | Default                      | Effect                                                          |
| ------------ | ---------------------------- | --------------------------------------------------------------- |
| `debounceMs` | `100`                        | Milliseconds of quiet before `find` sends a request             |
| `cache`      | `{ max: 50, ttlMs: 60_000 }` | Size and lifetime of the suggestions cache. `false` disables it |

The cache belongs to one helper instance. Create a new client and helper when credentials change.

## Exported types

`@ideal-postcodes/sdk/autocomplete` exports `CreateAutocompleteOptions`, `Autocomplete`, `Hit`, `ResolvedAddress`, `FindInput` and `ResolveInput` for typing your own wrappers.

## Errors

HTTP errors reject with [`ApiError`](/docs/sdks/typescript/errors.md). Network failures reject with the runtime's native error. The helper does not cache failed requests. Pass `signal` to `find` or `resolve` to abort a request yourself, and the call rejects with `AbortError`.

React and Preact apps can use [TanStack Query](/docs/sdks/typescript/react.md#tanstack-query) for query caching instead.

## Try it

Select **Find** to run the search. Edit the query in the code to try another.

Loading...

```
<button>Find</button>
<pre></pre>
```

```

import { createIdpcClient } from "@ideal-postcodes/sdk";
import { createAutocomplete } from "@ideal-postcodes/sdk/autocomplete";

const apiKey = "ak_test"; // Replace with your own API key
const client = createIdpcClient({ apiKey });
const autocomplete = createAutocomplete({ client });

document.querySelector("button").addEventListener("click", async () => {
  const hits = await autocomplete.find({ query: "9 Malyons Road" });
  document.querySelector("pre").textContent = JSON.stringify(hits, null, 2);
});
```
