Search
Three search endpoints, all requiring the search scope. None of them use the flat list envelope.
/v1/searchKeyword search across businesses and products. Parameters: `q` (required), `type` = `all` | `business` | `product`, `category_id`, `region_id`, `limit`, `offset`.
{
"query": "teak chair",
"type": "all",
"businesses": { "data": [ /* … */ ], "total": 12 },
"products": { "data": [ /* … */ ], "total": 34 }
}Business results are limited to public listings unless the key has businesses.internal.read; product results to active + public unless it has products.internal.read.
/v1/semantic-searchVector search. Parameters: `q` (required), `types` (comma list of `business,product`, default both), `limit` (1–50, default 10), `threshold` (default 0.3).
Returns 503 { "error": "Semantic search not configured (missing OPENAI_API_KEY)" } when embeddings are not configured. Build a keyword fallback, or use /v1/hybrid-search.
include_internal is hard-forced to false here for every caller, including * keys. Semantic search never returns draft or admin-only records.
/v1/hybrid-searchKeyword-first business search that augments with semantic results when keyword matches are thin. Parameters: `q` (required), `limit` (1–50), `keyword_min` (default 3 — below this many keyword hits, semantic search is added), `category_id`, `region_id`.
The response reports whether the semantic leg actually ran, so you can tell a keyword-only result from an augmented one. Like semantic search, internal records are never included.