Search As You Type
Authentication
A search key, issued by Captain. Sent as Authorization: Bearer <key>.
A scoped key for one end user, minted from an issuer key that Captain issues. Sent as Authorization: Bearer <key>.
Path parameters
Request
results to return, up to 1,000. The first 100 are the full ranking; 101-1,000 continue it (the rest of the blended ranking, then keyword order), the same list for every page of a query. sort, a geo sort and strict order or filter the top 1,000 relevant records; prefer re-orders the top 100 and leaves 101-1,000 in rank order; with group_by, k counts groups, formed from the top 1,000
field -> value (exact), or list (any of). Also price_min, price_max, rating_min, t_<field>min / t<field>_max for typed numbers (flexible schema), attributes.<key> for attribute values. A filterable field is named as the settings name it: a value or a list of values, or, on a number or date field, a range {gte, gt, lte, lt}. A bare date as lte covers that whole day (lte 2003-12-31 keeps filings made on the 31st). The filter expression (filter) says the same and more
rule contexts (Algolia ruleContexts): a rule whose condition has a context fires only when the search sends it
Search Records counts facets unless this is false. The counts cover the most relevant results, up to 2,000, not every match, so facets_exact is false. Search As You Type counts facets only when this is true or facet_keys names some.
the facets to count, by field name (as the answer names them). A date facet, a facet with more than 1,000 distinct values at build, or a field that is not a facet with more than 500, has no value counts and is refused (400); capabilities.fields.facet_counts lists the facets that count
Search Records only. Answer as total the number the Algolia host answers as nbHits for the same query: the hits it can page through while under 1,000 (total_basis pageable), else every record that contains every query word, never below 1,000 (all_matches; at the 1,000 floor total_exact is false, paging_limit). Count the facets in facet_keys over every record that contains every query word. Bounded so a search never waits long: when the count is busy or over its time budget, total stays the candidate count and total_basis says why. Off by default: on a large index a common word makes the count cost more than the search
Search As You Type only: the id of the hit you showed first after the previous keystroke. If that record is now second or third, it moves back to first and the rest keep their order, so the top suggestion doesn’t jump while the shopper types.
search exactly what was typed (“Search instead for walnutt”): no spelling correction, no word split or join, no glued codes, no synonym expansion. Identifier matching, filters and meaning-based matching are unchanged: they find records, they don’t rewrite the query. query_understanding.as_typed says it applied
false: this search is not logged for analytics (no search log row, no query_id, so it never counts in search counts, the no-result rate or a test’s readout); for your own previews, evals and relevance checks. Any key. An A/B assignment still routes it. The answer carries analytics: false. Default true
a filter expression (strict), e.g. status IN [“open”, “pending”] AND filed_at >= 2024-01-01 AND office WITHIN 25 km OF (40.71, -74.00). The Search guide’s Filters section lists the syntax
soft constraints: reorder, never remove
strict: quantities parsed from the query (under 5 lb) must hold on the record’s typed fields; soft: they only rank
a sortable field; search sorts the relevant set (the top 1,000 relevant records)
one hit per value of a field (product variants: Algolia’s distinct), with up to size - 1 more members: today’s ranking, deduplicated. k counts groups. Search only. false: no grouping, whatever the index’s default
search: which page, from 0, of per_page hits. Pages cut the final ranking (after filter, prefer, strict, sort and group_by) within the top 1,000 relevant records, the same list on every page; a page past that is 400 PAGE_TOO_DEEP. To walk every match, browse with a filter, sort, k and page
search: hits per page (default k)
search inside one facet’s values (Algolia searchForFacetValues): the values whose text, or any of whose words, starts with prefix (case and accents folded), with their counts over the same set as facets
min and max of each number and date facet (Algolia facets_stats; no average: it would need every match’s value). Search: over the relevance set, up to 1,000 distinct values, and exhaustive says whether that covered every one. Browse: exact over every record the filter matches and the key may see
per hit _explain: its rank and score in keyword and in meaning-based matching, identifier match, matched words per field
per hit _citations: the best passages (and child records) with character offsets. Best effort, not a guarantee: on CUAD contracts (CUAD dev, 469 queries, os-generalize’s labels as of 2026-09-27 10:36Z), when the right contract ranks first, one of its 3 cited passages holds the annotated clause 64.6% of the time (the first citation 45.7%)
per hit fields: the typed values (dates as ISO 8601). Access lists are never returned
Response headers
the last update seq search had applied when this request started; the answer reflects at least that much (GET …/updates applied_seq). Not on 401 or 403, nor for an index this server does not have
the index’s incarnation, an opaque string: it changes only when the index is deleted and created again (whose seqs start again at 1), or restored from a backup (whose seqs continue from the backup’s). Sent with X-Captain-Applied-Seq
Response
search: the number of candidates the search ranked (an estimate, not a count of every match) unless the search asked exact_total, when it is the number the Algolia host answers as nbHits (see total_basis). Page with page.has_more, not total. Browse: every record the filter keeps. With group_by too: records, not groups
true when total is an exact number (search with exact_total: total_basis pageable or all_matches). False: an estimate (candidates) or the 1,000 floor (paging_limit)
what total is: pageable (exact: the hits the search can page through, under 1,000), all_matches (exact: every record that contains every query word, 1,000 or more), paging_limit (1,000, a floor: more may match), candidates (exact_total not asked, or type-ahead), or why an asked-for exact count fell back: busy, time_budget, error, no_required_words (no query word is required, so every record would match)
per facet in facets: basis all_matches (counted over every match, exact true) or relevant_results (counted over the relevance-cut set, exact false, with the reason when an asked-for exact count fell back)
present when results are grouped: the ranking, collapsed by the field’s value. A grouped search reads the 100 most relevant records, and further down the top 1,000 when k x size x 4 needs more; depth says how many it read
true only when every facet was counted over every matching record (browse). Search counts facets over the relevance-cut set (the most relevant results, up to 2,000): false
only on a search of a catalog with an assignment that sent a user_token: the shopper’s group, and the index that served it
false when the request sent analytics: false (not logged, no query_id); absent otherwise
what the engine understood. Keys appear only when they apply; keys not listed here are diagnostics and may change
the userData of each rule applied to this search, in rule order (at most 10). Absent when no applied rule has any
how a page orders facets and their values (Algolia renderingContent.facetOrdering, snake_case). Returned on search and browse when the index or an applied rule sets one; the client orders with it
an applied rule’s redirect (the first in rule order): the page to send the shopper to instead of showing these results. Absent when no applied rule redirects
constraints: strict: hits removed because a parsed quantity failed. hits [] with this > 0 means nothing meets the query’s quantities
search with sort: which field and over what set
search with page or per_page