AI-API - Hybrid Search (embed_and_search)

AI API: Vectors, Images & LLM

One call does what the hosted search page does: the question is matched on its words and on its meaning, ranked with the Search Tuning saved for the index, and the results come back with highlights, facets and spelling suggestions. The Opensolr packages for LangChain, LlamaIndex, Haystack, MCP and Laravel Scout search through it.

01 · The request

https://api.opensolr.com/solr_manager/api/embed_and_search

GET or POST, as form fields or as a JSON body.

ParameterDefaultWhat it does
emailrequiredThe email of your Opensolr account.
api_keyrequiredYour API key, or a scoped key that allows embed_and_search: Authentication and keys.
index_namerequiredThe index to search.
qrequiredThe search, as plain text, at least 2 characters.
rows50How many results to return.
start0How many results to skip, for the next page.
freshyesno: results of any date. yes: only documents dated within the last 7 days (the window can be changed with freshness_boost, in days), the newest first among equal scores. positive or negative: only documents with that sentiment, ranked by it.
inwebweb: web pages. media: documents and files. images: pictures. all: everything; use it when the index also holds files, such as PDFs you push with Data Ingestion.
clean_qfrom qYour own version of the search for the words side. By default Opensolr removes the stop words itself; the meaning side always uses q as it is.
Leave out fresh and you get only the documents of the last few days. Send fresh=no unless that is what you want.

Every Search Tuning setting can also be changed for one call: Search Tuning for one call. Search operators (+word, -word) act as filters on the hosted search page; this call does not apply them as filters.

02 · How the results are ranked

The question is turned into a meaning vector, as a search question, and matched on its words in the title, description, address, text and structured data of each document. The Opensolr hybrid parser ranks both in one list: Hybrid search.

The Search Tuning saved for the index applies: the balance between words and meaning, Field Weights, Minimum Match, Search Mode, Vector Candidate Pool, Content Quality Boost and Fresh Results Bias.

Results Per Page and Show Documents Search belong to the hosted search page; here you use rows and in.

03 · The answer

{
  "status": true,
  "results": {
    "docs": [
      {"id": "1b2b982f2b606ff5207066fa65c92c8f", "uri": "https://example.com/help/reset-password",
       "title": "Reset your password", "description": "...", "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": {"mode": "bool", "bool_mode": "union", "requests": 1, "vector_topk": 500}
  },
  "embeddings": [0.0384, 0.0310, -0.0127]
}
FieldWhat it holds
statustrue, or false with a msg that says why.
results.docsThe results, best first, with their stored fields: id, uri, title, description, text and the other fields of your schema.
results.numHow many documents match in all.
results.hlHighlighted snippets, per document id.
results.facets, facet_pivot, statsFacet counts and price statistics, as set up for the index: Facets.
results.spellcheckDid you mean suggestions.
results.qtime, params, debugThe time Solr took, in milliseconds, the parameters the search ran with, and the search mode and vector pool used.
embeddingsThe meaning vector of q: 1,024 numbers (shortened above). Reuse it for your own vector searches.
AnswerWhy
{"status":false,"msg":"Invalid query"} (HTTP 400)q is missing or shorter than 2 characters.
EMBEDDING_FAILEDThe meaning vector could not be made. Nothing was counted; send it again.
VECTOR_NOT_ALLOWED (HTTP 403)AI is switched off on the plan of the account that owns the index.
ERROR_AI_MONTHLY_QUOTA_EXCEEDED (HTTP 429)This month's AI allowance is used up.
ERROR_NOT_CORE_OWNERThe index is not one your account can use.

Authentication, rate limits and a wrong host answer as described in API errors.

04 · What it uses from your plan

Understanding a new search counts as one AI request of the account that owns the index. The same search again uses the vector from cache and costs nothing.

Every plan includes a monthly AI allowance of 500 AI requests; see pricing and API Quota.

05 · Examples

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=YOUR_INDEX" \
  --data-urlencode "q=how do I reset my password" \
  --data-urlencode "rows=5" \
  --data-urlencode "fresh=no" \
  --data-urlencode "in=all"
<?php
$query = http_build_query([
    'email'      => 'YOUR_EMAIL',
    'api_key'    => 'YOUR_API_KEY',
    'index_name' => 'YOUR_INDEX',
    'q'          => 'how do I reset my password',
    'rows'       => 5,
    'fresh'      => 'no',
    'in'         => 'all',
]);
$r = json_decode(file_get_contents('https://api.opensolr.com/solr_manager/api/embed_and_search?' . $query), true);

foreach ($r['results']['docs'] ?? [] as $doc) {
    echo $doc['title'], ' - ', $doc['uri'], PHP_EOL;
}
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": "YOUR_INDEX",
    "q": "how do I reset my password",
    "rows": 5,
    "fresh": "no",
    "in": "all",
}, timeout=60).json()

for doc in r.get("results", {}).get("docs", []):
    print(doc["title"], doc["uri"])

06 · Try it without an account

A public demo account lets you run these examples before you sign up: email mcp@opensolr.com, API key 420b8b23e7b12dc8ab838932145a5065, index mcp_demo_d1__dense, already full of documents. It is shared with everyone, what you create there is deleted after 3 days, and its limits are small on purpose. The rules: Try the API without an account. For an index of your own, register a free account.

07 · Related

Write an answer from the results: RAG in two calls and ai_summary.

A search by photo: turn the picture into words with image_to_text, then search with them here.

Only the vector of a text: embed.

The other search calls: Search from your own code.