API Reference
POST /search
Search a menu using natural language. Understands synonyms, misspellings, abstract concepts ("something sweet", "healthy lunch"), and cross-lingual queries. Returns results ranked by relevance.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query (1-500 chars). Natural language or menu item name. |
corpus | string[] | Yes | Menu items to search over. 1-512 items, max 500 chars each. |
top_k | int | No | Maximum results to return. Default: 10, max: 1000. |
corpus_embeddings | float[][] or null | No | Pre-computed embeddings for corpus items (from /embed). Skips corpus encoding for faster search. Length must match corpus. |
{
"query": "spicy chicken",
"corpus": ["Chicken 65", "Chicken Tikka", "Paneer Tikka", "Veg Manchurian", "Chilli Chicken"],
"top_k": 3
}
Response
| Field | Type | Description |
|---|---|---|
results | object[] | Up to top_k results sorted by relevance. May be fewer if weak matches are filtered out. |
query_preprocessed | string | Query after noise removal |
Each result:
| Field | Type | Description |
|---|---|---|
text | string | Matched menu item (from corpus) |
score | float | Cosine similarity to query (0-1) |
reranker_score | float or null | Relevance score from search reranker, null if reranker not loaded |
is_fallback | bool | True if the result came from category-aware fallback (no high-confidence semantic match found) |
{
"results": [
{"text": "Chicken 65", "score": 0.87, "reranker_score": 0.94, "is_fallback": false},
{"text": "Chilli Chicken", "score": 0.84, "reranker_score": 0.91, "is_fallback": false},
{"text": "Chicken Tikka", "score": 0.81, "reranker_score": 0.85, "is_fallback": false}
],
"query_preprocessed": "spicy chicken"
}
Example
import requests
# Basic search
response = requests.post("https://embed.statode.com/search",
headers={"X-API-Key": "YOUR_KEY", "Content-Type": "application/json"},
json={
"query": "something sweet",
"corpus": ["Gulab Jamun", "Chicken Biryani", "Rasmalai", "Masala Dosa", "Brownie"],
"top_k": 3
}
)
# Returns: Gulab Jamun, Rasmalai, Brownie
# Faster repeated search with pre-computed embeddings
embed_resp = requests.post("https://embed.statode.com/embed",
headers={"X-API-Key": "YOUR_KEY", "Content-Type": "application/json"},
json={"items": menu_items, "dimension": 384}
).json()
search_resp = requests.post("https://embed.statode.com/search",
headers={"X-API-Key": "YOUR_KEY", "Content-Type": "application/json"},
json={
"query": "cold coffee",
"corpus": menu_items,
"corpus_embeddings": embed_resp["embeddings"],
"top_k": 5
}
)
Cost
0.05 credits per corpus item.
Notes
- When
corpus_embeddingsis provided, the server skips corpus encoding entirely. Use this for repeated searches against the same menu to save latency. - The search reranker uses a dual-gate filter: results must clear both an absolute relevance floor and stay within range of the top result. This prevents low-quality tail results from appearing.
- Abstract concept queries ("comfort food", "party snacks", "healthy options") are supported through concept centroid blending.
is_fallback=trueresults appear when no high-confidence semantic match is found. Fallback applies category-aware filtering (food queries get food items, beverage queries get beverages).