# AutoSugges — GET /v1/query — the autocomplete endpoint

## How do I call the AutoSugges autocomplete endpoint?

Send GET /v1/query with your publishable key as the key query parameter and the typed text as q, once the input reaches the list's minQueryChars and settles for debounceMs, both read from /v1/bootstrap. The response holds a pre-ranked items array answered from the edge, with a typed code for every failure.

You are integrating AutoSugges, a hosted autocomplete and list-of-values service. Everything you need is in this message; do not guess at anything it does not state, and do not fetch documentation to fill a gap — ask instead.

## Objective
A correct raw HTTP call to GET /v1/query: the right key placement, a normalized query, the real response shape, and every error code this route can return handled by its code, not by guessing at a message.

## Environment
- Target framework/runtime: HTTP API.
- SDK package: `@autosugges/client`.
- Runtime HTTP API version: `v1`.
- Install: No install: this is a plain HTTP GET. Any HTTP client works, including curl.

## Prerequisites
- An AutoSugges list that has been published at least once — an unpublished list returns `list_not_published`.
- The publishable key issued for the application that will call this endpoint.
- The runtime base URL for the environment you are targeting — the AutoSugges dashboard's integration panel shows it.

## Values you must supply
- `baseUrl` (required, public by design) — placeholder `YOUR_RUNTIME_BASE_URL`. The origin of the AutoSugges runtime — scheme and host, no trailing slash and no path. The SDK appends `/v1/...` itself. Source: The AutoSugges dashboard's integration panel, for the environment you are deploying to.
- `publishableKey` (required, public by design) — placeholder `YOUR_PUBLISHABLE_KEY`. Identifies the consumer, the application, the subscription, the canonical list and the query policy in a single server-side lookup. The client never supplies a list id, tenant id or version hash — if a generated integration is passing one of those, it is wrong. Source: The AutoSugges dashboard, under the application that will make the queries.
- `accessToken` (optional, SECRET — server-side only) — placeholder `YOUR_SERVER_MINTED_ACCESS_TOKEN`. Only for a list whose policy requires a token. Short-lived, sent as `authorization: Bearer <token>`, and never minted, stored or hardcoded in client code. Source: Your own backend, which mints it from your AutoSugges credentials.
- `q` (required, public by design) — placeholder `<text the user typed>`. Below the list's minQueryChars (from bootstrap) the server returns query_too_short at HTTP 200 with no items and does not bill it — do not issue the request at all until the input reaches that length. Above 255 characters it returns query_too_long at HTTP 400. Source: The user’s input, normalized (trimmed, lower-cased) before you send it.
- `locale` (optional, public by design) — placeholder `<BCP-47 tag, e.g. en-US>`. Optional. An unsupported locale is not an error — the server falls back to the list's default locale and serves that instead. Source: The list's localePolicy.supportedLocales, from bootstrap.
- The base URL below is still the literal placeholder `YOUR_RUNTIME_BASE_URL`. Ask the developer for their environment's runtime origin and substitute it; do not invent an autosugges.com hostname.

## Request contract
The publishable key travels as a query parameter (or, for selection reports, a JSON body field) — NOT as an Authorization header. The Authorization header is reserved for the optional access token of a protected list.
- `GET /v1/bootstrap?key=<publishable key>` — Resolves the list identity, the active version hash and the effective query policy for this key. Call once per session before querying. Key placement: `key` query parameter. Headers: `x-request-id`: a per-request correlation id (the SDK mints one automatically); `authorization: Bearer <access token>`: optional, and only for a list whose policy requires a token.
- `GET /v1/query?key=<publishable key>&q=<text>&locale=<optional BCP-47 tag>` — Returns the pre-ranked suggestions for one query. Key placement: `key` query parameter. Headers: `x-request-id`: a per-request correlation id; `authorization: Bearer <access token>`: optional, as above.
- `POST /v1/selection` — Reports which suggestion the user chose, so ranking can improve. Optional: skipping it degrades ranking quality and nothing else. Key placement: `key` field of the JSON body, alongside `selectionId`, `queryRequestId`, `listId`, `itemId`, `query` and `position`. Headers: `content-type: application/json`; `x-request-id`.

## Policy that arrives from bootstrap — never hardcode these
- `requestId` (string) — Correlation id for this bootstrap call.
- `list.id` (string (UUID)) — The canonical list this key resolves to. Never supplied by the client.
- `activeVersionHash` (string) — The published version currently serving. Compare it to a stored hash to decide whether a cached local copy is stale.
- `queryPolicy.minQueryChars` (number) — Minimum characters before a query is legal. Never below 2, and never hardcoded — a shorter query is rejected and not billed.
- `queryPolicy.debounceMs` (number) — How long to wait after the last keystroke before issuing a query.
- `queryPolicy.defaultResultLimit` (number) — How many suggestions a list returns by default. Informational: the server already returns its ranked set, so the client does not send this back.
- `queryPolicy.rememberLastSelection` (boolean) — Tenant policy for prefilling a previously chosen item. Treat anything other than literal `true` as off.

## What one suggestion looks like
- `itemId` (string) — Stable identifier. Use it as the React/list key.
- `value` (string) — The canonical value — what you store.
- `displayValue` (string) — The locale-resolved label — what you render. Not the same field as `value`.
- `displayOrder` (number) — The owner's configured display order.
- `position` (number) — 1-based position in the returned ranking.
- `ancestors` (array, optional) — The precomputed hierarchy chain, root first, excluding the item itself — `{ itemId, value, displayValue, hierarchyLevel? }`. Use it to auto-fill parent form fields. Absent when the item has no ancestors; never an empty array.

## Implementation steps
1. Bootstrap first — Call GET /v1/bootstrap once per session to learn the real minQueryChars and debounceMs — never hardcode either.
2. Debounce client-side — Wait debounceMs after the last keystroke, and only once the input is at least minQueryChars, before calling /v1/query.
3. Send the key as a query parameter — GET /v1/query?key=<publishable key>&q=<text>&locale=<optional>. The key is never a header.
4. Read the response — items is the pre-ranked suggestion array (10 by default). Render displayValue; store value. ancestors, when present, is the hierarchy chain root-first.
5. Handle every error by code — A non-2xx status, and the 200-status quota_exceeded/query_too_short conditions, all carry a typed code field. Switch on it — never on the message text, which is deliberately generic.

## Code
```bash
curl -sS \
  --get 'YOUR_RUNTIME_BASE_URL/v1/query' \
  --data-urlencode "key=YOUR_PUBLISHABLE_KEY" \
  --data-urlencode "q=par" \
  -H "x-request-id: $(uuidgen)"
```

## Security requirements
- A publishable key is public by design. It is safe in client-side JavaScript, in a mobile bundle, and in a page a search engine can read. It is not a secret and does not need a proxy.
- A publishable key is not a substitute for origin control: keys are bound to an allow-list of origins, and a request from an origin the tenant has not allowed is refused with `origin_not_allowed` and is not billed. Add the deploying site’s origin in the AutoSugges dashboard before going live.
- Never place a secret key, a signing key, a service-role credential or a database URL in client code, in an environment variable prefixed for browser exposure, or in a prompt. Nothing in an AutoSugges browser or mobile integration needs one.
- An access token (`authorization: Bearer …`) is only for a list whose policy requires one. It is short-lived, and it is minted by your own server from your own AutoSugges credentials — never in the browser, never hardcoded, never committed.
- Do not log the raw query text or the response body. Log the typed error `code` and the `requestId`.
- The publishable key travels as a query parameter, never as an Authorization header — that header is reserved for the optional access token of a protected list.
- A publishable key is public by design. It is safe to embed in client code, a mobile bundle or a server-side script committed to a public repository.

## Expected result
A 200 response whose items array holds the pre-ranked suggestions for the query, each with a stable itemId, a value to store and a displayValue to render, served from the edge.

## Validation — do these before reporting success
1. Check 1 — Call with q shorter than minQueryChars and confirm a 200 with code "query_too_short" and an empty (or absent) items array — not an error status.
2. Check 2 — Call with a valid query and confirm exactly one request is needed per settled input — no per-keystroke traffic.
3. Check 3 — Call twice with the identical key, query, locale and list version and confirm the response is byte-identical (cache-key dimensions: owner, list, version, locale, full normalized query).
4. Check 4 — Call with a wrong key and confirm HTTP 401 with code "invalid_key".
5. Check 5 — Call from an origin not on the key’s allow-list (send an Origin header) and confirm HTTP 403 with code "origin_not_allowed".

## Error codes you must handle
Every failure arrives as a typed code in the response body (and, through the SDK, as an `AutosuggesError` with that `code`). Switch on the code; never match on a message string. The codes most likely on this surface are: `invalid_key`, `origin_not_allowed`, `query_too_short`, `query_too_long`, `quota_exceeded`, `list_not_published`, `artifact_unavailable`. The complete vocabulary:
- `invalid_key` (HTTP 401, not retryable) — The publishable key is wrong, revoked or rotated. Check the key in the AutoSugges dashboard. Do not retry with the same key.
- `origin_not_allowed` (HTTP 403, not retryable) — The requesting origin is not on this key's allow-list. Add the origin in the dashboard. Not billed.
- `invalid_list` (HTTP 404, not retryable) — The key resolves to no list, or the list was deleted. Nothing to retry.
- `subscription_required` (HTTP 403, not retryable) — The list is shared and this consumer has no active subscription to it. Subscribe, or use a list you own.
- `list_not_published` (HTTP 409, not retryable) — The list exists but has never been published, so there is no artifact to serve. Publish it once from the dashboard.
- `token_expired` (HTTP 401, not retryable) — The access token is past its expiry. Mint a fresh one on your server and retry once. Never extend expiry on the client.
- `invalid_token` (HTTP 401, not retryable) — The access token failed signature or scope verification. Mint a new one; do not retry the same token.
- `quota_exceeded` (HTTP 200, not retryable) — The allowance for this billing scope is spent. `details.scope` says which allowance — `subscription` or `key`. The response carries no items at all, real or synthetic: render an upgrade path, and do not feed it into selection analytics. It clears at the next billing period.
- `query_too_short` (HTTP 200, not retryable) — The query is below the list's `minQueryChars` (`details.minQueryChars`). Do not issue the request at all until the input reaches it. Not billed.
- `query_too_long` (HTTP 400, not retryable) — The query exceeds the server maximum (`details.maxQueryChars`). Trim the input before sending; this is a malformed request, not something a user types.
- `invalid_request` (HTTP 400, not retryable) — The request is malformed — a missing parameter or an unusable value. `details` names what. Fix the call; retrying unchanged cannot help.
- `rate_limited` (HTTP 429, retryable) — Too many requests for this key, subscription or IP. Honour the `retryAfter` seconds in the body before retrying, and check that the input is actually debounced.
- `challenge_failed` (HTTP 403, not retryable) — A bot challenge was not satisfied on a session-establishing surface. Re-present the challenge. Not billed.
- `publish_validation_failed` (HTTP 422, not retryable) — A publish was rejected by validation (duplicates, an unresolved parent, a hierarchy cycle). The previously active version keeps serving. Fix the data and publish again.
- `compile_failed` (HTTP 500, retryable) — Compilation of a new version failed. The previously active version keeps serving; nothing at runtime changed. Retry the publish after fixing the reported cause.
- `artifact_unavailable` (HTTP 503, retryable) — A published artifact could not be read at this edge, usually mid-propagation. Retryable: wait the `retryAfter` seconds and retry once. Do not render a partial or stale result set alongside a fresh one.
- `resource_removed` (HTTP 404, not retryable) — The resource was deleted. Stop requesting it; there is nothing to retry.
- `invalid_domain` (HTTP 400, not retryable) — The submitted domain or slug is not valid or is reserved. Choose another.
- `domain_validation_failed` (HTTP 409, not retryable) — A custom-domain DNS or TLS validation did not complete. Re-check the DNS records shown in the dashboard, then revalidate.
- `forbidden` (HTTP 403, not retryable) — Your account is signed in but your workspace role does not permit this action. Ask an owner or admin to change your role, or use an account that has it.
- `internal_error` (HTTP 500, retryable) — An unexpected server-side failure. Report the `requestId` from the response. Retry at most once, with backoff.

## Notes
- A long query is still served correctly: the server matches it against your full query text, so send the whole typed text.
- An item can match through an alias/synonym defined on the list, not only through its own label — do not assume every returned item’s displayValue literally contains what was typed.

## Reference
- Bootstrap endpoint: https://docs.autosugges.com/api-reference/bootstrap
- Error codes: https://docs.autosugges.com/api-reference/errors
- API reference index: https://docs.autosugges.com/api-reference

---
Canonical page: https://docs.autosugges.com/api-reference/query
