Search

App Search is in beta with design partners. Endpoints roll out per tenant.

All search routes take a search key, or a scoped key on an index with per-record access control. They return the same response shape: hits, total, facets and timing.

RouteUse it for
POST /v1/indexes/{index}/searchA search submitted with Enter or a button.
POST /v1/indexes/{index}/typeaheadResults while the user types, one request per keystroke.
POST /v1/indexes/{index}/browseCategory and listing pages: filters, sort and facets with no query text.
POST /v1/indexes/{index}/similar”More like this” for one record.
POST /v1/multi_searchUp to 10 searches in one request, across indexes.

Typeahead

Send the text typed so far. Captain answers each keystroke with spelling correction and prefix matching.

curl -X POST "https://acme.captain.dev/v1/indexes/products/typeahead" \
-H "Authorization: Bearer $CAPTAIN_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "waterpr",
"k": 3
}'
Example: (200 OK)
{
"hits": [
{
"id": "sku-10482",
"title": "Moab 3 Mid Waterproof Hiking Boot",
"brand": "Merrell",
"category": "Hiking Boots",
"price": 139.0,
"rating": 4.6,
"image_url": "https://cdn.acme.example/img/sku-10482.jpg",
"score": 1.42
},
{
"id": "sku-11020",
"title": "Targhee III Waterproof Mid Boot",
"brand": "KEEN",
"category": "Hiking Boots",
"price": 150.0,
"rating": 4.4,
"image_url": "https://cdn.acme.example/img/sku-11020.jpg",
"score": 1.18
},
{
"id": "sku-10517",
"title": "X Ultra 4 Mid GTX Hiking Boot",
"brand": "Salomon",
"category": "Hiking Boots",
"price": 165.0,
"rating": 4.5,
"image_url": "https://cdn.acme.example/img/sku-10517.jpg",
"score": 0.97
}
],
"total": 57,
"query_id": "e41b7c9a2d5f4a86b03e7d1c9f2a6b58",
"query_understanding": {
"completions": [
"waterproof",
"waterproofing"
],
"partial": "waterpr"
},
"request": {
"mode": "instant",
"lanes": [
"lex",
"splade",
"dense"
],
"build": "b20260928201247"
},
"timing": {
"engine_ms": 8.7,
"stages": {
"understand": 0.3,
"embed": 2.9,
"qdrant": 3.6,
"fuse": 0.2,
"payload": 0.8
}
}
}

Cancel the previous request when a new keystroke arrives, and draw only the reply to the latest one.

Filters, sort and pages

filter takes an expression over the fields returned by List Filters, which also gives the operators each field accepts:

status IN ["open", "pending"] AND filed_at >= 2024-01-01 AND price <= 150

Operators: =, !=, <, <=, >, >=, IN, NOT IN, BETWEEN, EXISTS(field), combined with AND, OR, NOT and parentheses.

An expression that names an unknown field, or uses an operator the field does not support, returns 400 FILTER_INVALID with the position of the problem and what could come there.

  • sort: order by one sortable field, {"field": "price", "order": "asc"}, instead of relevance.
  • page and per_page: page through results, from page 0.
  • prefer: lift records that match a condition without removing the others.
  • group_by: one hit per value of a field, such as one product per variant family.

Browse

curl -X POST "https://acme.captain.dev/v1/indexes/products/browse" \
-H "Authorization: Bearer $CAPTAIN_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": "category = \"Hiking Boots\"",
"sort": [
{
"field": "price",
"order": "asc"
}
],
"k": 3,
"facet_keys": [
"brand"
]
}'
Example: (200 OK)
{
"hits": [
{
"id": "sku-10482",
"title": "Moab 3 Mid Waterproof Hiking Boot",
"brand": "Merrell",
"category": "Hiking Boots",
"price": 139.0,
"rating": 4.6,
"image_url": "https://cdn.acme.example/img/sku-10482.jpg"
},
{
"id": "sku-11020",
"title": "Targhee III Waterproof Mid Boot",
"brand": "KEEN",
"category": "Hiking Boots",
"price": 150.0,
"rating": 4.4,
"image_url": "https://cdn.acme.example/img/sku-11020.jpg"
},
{
"id": "sku-10517",
"title": "X Ultra 4 Mid GTX Hiking Boot",
"brand": "Salomon",
"category": "Hiking Boots",
"price": 165.0,
"rating": 4.5,
"image_url": "https://cdn.acme.example/img/sku-10517.jpg"
}
],
"total": 42,
"facets": {
"brand": [
{
"value": "Merrell",
"count": 14
},
{
"value": "Salomon",
"count": 11
},
{
"value": "KEEN",
"count": 9
},
{
"value": "Columbia",
"count": 8
}
]
},
"facets_exact": true,
"timing": {
"engine_ms": 6.2,
"stages": {
"qdrant": 4.1,
"facets": 1.3,
"payload": 0.6
}
}
}

Similar records

curl -X POST "https://acme.captain.dev/v1/indexes/products/similar" \
-H "Authorization: Bearer $CAPTAIN_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "sku-10482",
"k": 2
}'
Example: (200 OK)
{
"hits": [
{
"id": "sku-11020",
"title": "Targhee III Waterproof Mid Boot",
"brand": "KEEN",
"category": "Hiking Boots",
"price": 150.0,
"rating": 4.4,
"image_url": "https://cdn.acme.example/img/sku-11020.jpg",
"score": 0.884
},
{
"id": "sku-10517",
"title": "X Ultra 4 Mid GTX Hiking Boot",
"brand": "Salomon",
"category": "Hiking Boots",
"price": 165.0,
"rating": 4.5,
"image_url": "https://cdn.acme.example/img/sku-10517.jpg",
"score": 0.861
}
],
"total": 2,
"timing": {
"engine_ms": 5.8,
"stages": {
"qdrant_dense": 4.3,
"payload": 0.7
}
}
}

Multiple searches

Each entry names an index, a route (search, typeahead or browse, default search) and that route’s body.

curl -X POST "https://acme.captain.dev/v1/multi_search" \
-H "Authorization: Bearer $CAPTAIN_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{
"searches": [
{
"index": "products",
"query": "rain jacket",
"k": 2
},
{
"index": "articles",
"query": "rain jacket care",
"k": 1
}
]
}'
Example: (200 OK)
{
"results": [
{
"index": "products",
"route": "search",
"status": 200,
"result": {
"hits": [
{
"id": "sku-20311",
"title": "Torrentshell 3L Rain Jacket",
"brand": "Patagonia",
"category": "Rain Jackets",
"price": 179.0,
"rating": 4.7,
"image_url": "https://cdn.acme.example/img/sku-20311.jpg",
"score": 0.931
},
{
"id": "sku-20402",
"title": "Resolve 2 Rain Jacket",
"brand": "The North Face",
"category": "Rain Jackets",
"price": 110.0,
"rating": 4.5,
"image_url": "https://cdn.acme.example/img/sku-20402.jpg",
"score": 0.902
}
],
"total": 18,
"query_id": "5d9e2b7a1c4f4380b6a2e8f37c1d9a04"
}
},
{
"index": "articles",
"route": "search",
"status": 200,
"result": {
"hits": [
{
"id": "art-0147",
"title": "How to wash and re-waterproof a rain jacket",
"category": "Care guides",
"score": 0.887
}
],
"total": 6,
"query_id": "a0c3f6e91b2d47c58e4a7b96d3f21c08"
}
}
]
}

Per-record access control

When records carry access lists, searches use scoped keys. A scoped key is minted for one end user and returns only the records that user may see. Suggestions and facet counts respect the same rule. Scores are never returned to a scoped key.

A write key can set a record’s access list, including making it public. Check the access fields in the integration before going live.

© 2026 Captain