Hybrid Search (embed_and_search)
One call does what the hosted search page does: the query is cleaned and embedded with the e5 model, then run against your index as a hybrid keyword + vector query using the field weights, boosts and freshness settings saved under Search Tuning for that index. You get back ranked documents with highlighting, facets, spellcheck and the query embedding itself. This is the retrieval step used by langchain-opensolr, llama-index-opensolr, opensolr-haystack, the MCP server and the Laravel Scout driver.
Endpoint
GET or POST https://api.opensolr.com/solr_manager/api/embed_and_search
api.opensolr.com, not on opensolr.com. It works on indexes that hold vector embeddings (Web Crawler, Data Ingestion, or the CMS integrations) and counts as one request against your monthly AI cap.Parameters
| Parameter | Status | Description |
|---|---|---|
email | Required | Your Opensolr registration email address |
api_key | Required | Your Opensolr API key (master key, or a scoped key that allows this endpoint) |
index_name | Required | The index to search |
q | Required | The user query, plain text |
rows / start | Optional | Page size and offset (default 10 / 0) |
in | Optional | Content scope: web (crawled HTML pages), media (documents/files), or all. Use all for indexes filled by the Data Ingestion API |
fresh | Optional | yes to boost recent documents, no for pure relevance (default follows your Search Tuning) |
clean_q | Optional | Provide your own cleaned/stop-worded query and skip the server-side cleaning |
fw_title, fw_description, fw_text, fw_uri | Optional | Per-request field weights, overriding the saved Search Tuning |
lexical_weight, vector_weight, vector_topk, search_mode, mm, quality_boost, min_score | Optional | Hybrid tuning overrides — same knobs as the Search Tuning tab; omit to use the index defaults |
How It Works
- The query is normalised (stop words, accents, punctuation) unless you pass
clean_q. - It is embedded into a 1024-dimension vector with the same model that embedded your documents.
- Solr receives a hybrid request: BM25 keyword matching over the weighted fields plus a k-nearest-neighbour vector match, fused with your saved lexical/vector weights, boosts, freshness and quality settings.
- The response is assembled with highlights, facets and spellcheck exactly as the hosted search page renders them.
Because the index’s own tuning is applied server-side, an application using this endpoint returns the same results as the Opensolr search UI for that index — no query DSL to maintain. When you need raw Solr control instead, query the index directly (parameters explained) and embed with embed.
Response
| Key | Type | Description |
|---|---|---|
status | bool | true on success; errors come as {"status":false,"msg":"ERROR_..."} |
results.docs | array | Ranked documents with all stored fields (id, uri, title, description, text, meta_*, …) |
results.num | int | Total matches |
results.hl | object | Highlight snippets per document id |
results.facets / facet_pivot / stats | object | Facet counts as configured for the index |
results.spellcheck | object | Did-you-mean suggestions |
results.qtime / params / debug | mixed | Solr timing, the effective parameters and debug info |
embeddings | string | JSON-encoded 1024-float vector of the query — reuse it for your own KNN queries |
Code Examples
cURL
curl -s -G "https://api.opensolr.com/solr_manager/api/embed_and_search" \ --data-urlencode "email=YOUR_EMAIL" --data-urlencode "api_key=YOUR_API_KEY" \ --data-urlencode "index_name=my_index" --data-urlencode "q=how do I reset my password" \ --data-urlencode "rows=5" --data-urlencode "in=all" --data-urlencode "fresh=no"
PHP
$q = http_build_query(['email' => 'YOUR_EMAIL', 'api_key' => 'YOUR_API_KEY', 'index_name' => 'my_index', 'q' => 'how do I reset my password', 'rows' => 5, 'in' => 'all', 'fresh' => 'no']); $r = json_decode(file_get_contents("https://api.opensolr.com/solr_manager/api/embed_and_search?{$q}"), true); foreach ($r['results']['docs'] as $doc) { echo $doc['title'], ' — ', $doc['uri'], "\n"; }
Python
import requests r = requests.post("https://api.opensolr.com/solr_manager/api/embed_and_search", data={ "email": "YOUR_EMAIL", "api_key": "YOUR_API_KEY", "index_name": "my_index", "q": "how do I reset my password", "rows": 5, "in": "all", "fresh": "no"}, timeout=60) for doc in r.json()["results"]["docs"]: print(doc["title"], doc["uri"])
Example Response
{ "status": true, "results": { "docs": [ {"id": "1b2b982f2b606ff5207066fa65c92c8f", "uri": "https://example.com/help/reset-password", "title": "Reset your password", "description": "...", "text": "...", "content_type": "text/html"} ], "num": 12, "hl": {"1b2b982f2b606ff5207066fa65c92c8f": {"text": ["... <em>reset</em> your <em>password</em> ..."]}}, "facets": {}, "facet_pivot": {}, "stats": {}, "spellcheck": {}, "qtime": 41, "params": {}, "debug": {} }, "embeddings": "[0.0384618304669857, 0.031014347448945045, ...]" }
Use Cases
- Retrieval for RAG: take the top 3–4
docsas context for ai_summary - A headless search UI (mobile app, SPA) that must rank exactly like the hosted search page
- Semantic search inside your own product without running any embedding model
Related Documentation
Building RAG or semantic search on Opensolr? We are here to help.
Contact SupportTry it right now, without an account. There is a public demo account: email mcp@opensolr.com, API key 420b8b23e7b12dc8ab838932145a5065. The index mcp_demo_d1__dense is preloaded with 300 news articles, so search and grounded answers work the moment you connect, and you can create your own indexes on the account.
Anything you create there is deleted after 3 days. The account is shared with everyone — other people can change or delete your index, and you can do the same to theirs, so never put anything real in it. The limits are per index and deliberately small: 200 MB of bandwidth and 50 MB of disk. For an index that is private and stays put, create a free account — free forever, no card — and swap in your own two values.