Browse documentation
Search the index
Search the agent-first web index. Returns metadata-only hits (url, host, snippet, score, trust and graph signals) — never the page body; fetch that with get_document when a snippet is not enough.
/search Request
curl \
-H "x-api-key: $UNLOB_API_KEY" \
"https://api.unlob.com/search?q=<q>" Behaviour
The query supports boolean operators: AND, OR, -term to exclude, and "exact phrase". Name a vertical to disambiguate, or omit it and the router picks one from the query.
The index is admission-controlled, so a small result set usually means the index holds little on the topic, not that the query was wrong. One exception: if `partial` comes back true, part of the corpus was unreachable and the answer really is incomplete.
Every filter below is also a query parameter on GET /search, with the same name and the same meaning. IN-list filters accept either an array or a comma-separated string.
Parameters
| Name | Type | Description |
|---|---|---|
authority | string | Publisher-authority IN-list |
collapse | "none" | "host" | "page" | "story" | Group results: one per host, per page, or per story (near-dup cluster). collapse=story is how you stop reading the same wire copy five times. |
community | string | Graph signal: restrict to these graph communities |
content_type | string | IN-list: article, news, docs, reference, qa, forum, academic, product, code, how-to, opinion, video, document |
exclude_site | string | Hosts to exclude |
facets | boolean | Also return host/vertical/source/content-type facet counts and a publish-year histogram |
fields | string | Project the hit down to these fields, to save context |
from | integer | Only results fetched at/after this unix-second timestamp |
lang | string | Single language code, e.g. en |
langs | string | Language IN-list |
limit | integer | 0 returns only the match count |
max_words | integer | Passage length ceiling |
min_centrality | number | Graph signal: only passages this central to the corpus |
min_host_rank | number | Trust floor (0..1) |
min_independent_sources | integer | Graph signal: only stories asserted by at least this many distinct hosts. The corroboration filter. |
min_quality | integer | Quality floor |
min_words | integer | Passage length floor |
mode | "keyword" | "semantic" | "hybrid" | |
prefer_authority | boolean | Soft rerank bias toward higher-authority hosts |
prefer_recent | boolean | Soft rerank bias toward newer passages — a nudge, not a filter |
published_from | integer | Content publish date at/after this unix-second timestamp (not crawl time) |
published_to | integer | Content publish date at/before this |
qrequired | string | Boolean-capable: rust AND async, -python, "exact phrase" |
safe | boolean | true (the default) drops explicit content; false allows everything |
site | string | Restrict to an exact host, e.g. docs.rs |
sort | "relevance" | "recency" | "host_rank" | "quality" | "published" | "words" | "centrality" | |
source | "cc" | "delta" | cc = Common Crawl, delta = freshly crawled |
term | string | Exact-needle: only passages carrying this salient term, e.g. CVE-2024-3094. Use it for identifiers an embedder is blind to. |
tld | string | Top-level-domain IN-list, e.g. edu, gov |
to | integer | Only results fetched at/before this unix-second timestamp |
topic | string | Topic-tag IN-list |
vertical | string | e.g. code, cooking, science. Omit to auto-route. |
Responses
| Status | Meaning |
|---|---|
200 | Ranked passages. Check `partial` before treating a short answer as complete. |
401 | Missing, unknown or revoked key. A key minted moments ago can answer 401 until it propagates to the serving fleet. |
429 | Over the per-minute rate, or past a hard-capped monthly quota. `retry-after` is present on the rate-limit case only. |
Response body
WebSearchResponse
| Name | Type | Description |
|---|---|---|
facets | object | Present only when facets=true |
moderequired | "keyword" | "semantic" | "hybrid" | The mode actually used |
partial | boolean | true when at least one shard failed or timed out — the answer is short because a slice of the corpus was unreachable, NOT because that is all there is. Never treat a partial result as complete. |
resultsrequired | object[] | — |
routedrequired | boolean | true when the router chose the vertical, false when you named it |
totalrequired | integer | — |
vertical | string | null | The vertical actually queried |
The same call over MCP is a tool with these parameter names unchanged. See Errors for what to do with each status.