API Reference
Base URL: . All endpoints accept and return JSON. Field names are camelCase. Endpoints are also mounted under /api.
Quickstart
- Create a key on the dashboard.
- Send a search:
curl -X POST /search \
-H "x-api-key: nv-YOUR_KEY" -H "Content-Type: application/json" \
-d '{"query": "blog posts about building a search engine", "numResults": 3, "contents": {"highlights": true}}'
{
"requestId": "3f1b…",
"autopromptString": "Here is a great resource about blog posts about building a search engine:",
"resolvedSearchType": "neural",
"results": [
{
"id": "8acf991ec7c74ea906f3",
"url": "https://www.sqlite.org/fts5.html",
"title": "SQLite FTS5 Extension",
"publishedDate": null,
"author": null,
"score": 0.77,
"highlights": ["FTS5 is an SQLite virtual table module that provides full-text search functionality…"],
"highlightScores": [0.71]
}
],
"costDollars": {"total": 0.008},
"latencyMs": 41
}
Authentication
Send your key in the x-api-key header (or Authorization: Bearer nv-…). Keys are created and revoked on the dashboard. The free plan allows 1,000 requests per calendar month. The website playground calls the API without a key and is limited to 20 results.
Search
Find pages by meaning (neural), by exact terms (keyword), or let the engine choose (auto). Neural search rewrites short queries into a natural-language "autoprompt" unless useAutoprompt is false.
| Field | Type | Description |
|---|---|---|
query | string, required | What you're looking for. Neural search works best with a full sentence: "a page explaining how vector databases index embeddings". |
type | "auto" | "neural" | "keyword" | "fast" | Default "auto". Neural = hybrid embedding + BM25 fusion, keyword = BM25 only, fast = embedding only. |
numResults | int, 1–100 | Default 10. |
useAutoprompt | bool | Default true. Returned as autopromptString when applied. |
contents | object | Return page content with each result. See Contents options. |
| filters | Any of the filter fields. |
Response: requestId, resolvedSearchType, autopromptString, results[] (id, url, title, publishedDate, author, score, plus requested content fields), costDollars, latencyMs.
Contents options
Pass contents on /search and /findSimilar; pass the same keys top-level on /contents. Each option can be true or an object.
| Option | Fields | Returns |
|---|---|---|
text | maxCharacters | text: cleaned page text (boilerplate, navigation and scripts removed). |
highlights | numSentences (1–10), highlightsPerUrl (1–10), query | highlights[] and highlightScores[]: the passages most relevant to the query (or a custom highlight query). |
summary | query | summary: a short query-focused extractive summary. |
{"query": "how does CRISPR editing work", "numResults": 5,
"contents": {"text": {"maxCharacters": 2000}, "highlights": {"numSentences": 2, "highlightsPerUrl": 2}, "summary": true}}
Filters
| Field | Type | Description |
|---|---|---|
includeDomains | string[] | Only these domains (subdomains included). |
excludeDomains | string[] | Never these domains. |
startPublishedDate / endPublishedDate | ISO 8601 | Published-date window, e.g. "2024-01-01T00:00:00Z". Pages without a detected date are excluded when set. |
startCrawlDate / endCrawlDate | ISO 8601 | When the page was indexed. |
category | string | One of: research paper, news, github, encyclopedia, docs, personal site, tweet, linkedin profile, web page. |
includeText | string[] (≤5) | Phrases that must appear in the page. |
excludeText | string[] (≤5) | Phrases that must not appear. |
Get contents
Fetch clean text, highlights and summaries for result IDs or arbitrary URLs. URLs not yet in the index are live-crawled (livecrawl: "never" | "fallback" | "always"; default "fallback"). Results carry a statuses[] array with per-item outcome.
{"urls": ["https://www.paulgraham.com/greatwork.html"], "text": {"maxCharacters": 3000}, "highlights": {"query": "how to choose what to work on"}}
Find similar
Pages semantically similar to the one at url. If the URL isn't indexed it is crawled first. Supports numResults, excludeSourceDomain, contents and all filters.
{"url": "https://github.com/qdrant/fastembed", "numResults": 5, "excludeSourceDomain": true}
Answer
Runs a search, then writes an answer grounded in the top pages with inline [n] citations. When the server has an LLM_API_KEY for nevatoken.com the answer is generated by an LLM (DeepSeek V4 Pro by default); otherwise an extractive answer is returned. With "stream": true the response is Server-Sent Events: citations, then delta events, then done.
| Field | Type | Description |
|---|---|---|
query | string | The question. |
text | bool | Include full page text in each citation. |
numSources | int, 1–20 | Pages to ground on. Default 8. |
stream | bool | SSE streaming. |
{"answer": "FTS5 is SQLite's full-text search module … [1]", "citations": [{"id": "…", "url": "…", "title": "…", "snippet": "…"}]}
Index management
Protected by the x-admin-token header when the server sets NEVA_ADMIN_TOKEN. Open in development.
| Endpoint | Description |
|---|---|
GET /api/stats | Public: document, chunk and domain counts, categories, crawler status. |
POST /api/admin/index {"url"} | Fetch, clean, embed and store one page now. |
POST /api/admin/crawl {"urls", "maxDepth", "maxPages", "sameDomainOnly", "allowedDomains"} | Start a breadth-first background crawl. |
GET /api/admin/crawl · POST /api/admin/crawl/stop | Crawler status with recent queue entries; stop. |
GET /api/admin/documents?q=&limit=&offset= | List indexed documents. |
DELETE /api/admin/documents/{id} | Remove a document from the index. |
Dashboard API
Dashboard endpoints belong to the signed-in account. Send a Firebase ID token as Authorization: Bearer <idToken> (the website does this for you after you sign in). GET /api/auth/me returns your profile.
| Endpoint | Description |
|---|---|
POST /api/dashboard/keys {"name"} | Create a key. The full key is returned once. |
GET /api/dashboard/keys | List keys with monthly usage. |
DELETE /api/dashboard/keys/{id} | Revoke. |
GET /api/dashboard/usage?keyId=&days=30 | Requests and spend per day and per endpoint. |
Python SDK
A dependency-free client lives at sdk/python/nevabase.py in the repository.
from nevabase import Nevabase
nv = Nevabase("nv-YOUR_KEY", base_url="")
r = nv.search("essays on why startups fail", num_results=5, include_domains=["paulgraham.com"],
contents={"highlights": True})
sim = nv.find_similar("https://www.sqlite.org/fts5.html", num_results=5)
docs = nv.get_contents(urls=["https://arxiv.org/abs/1706.03762"], text={"maxCharacters": 2000})
ans = nv.answer("what problem does FTS5 solve?")
for ev in nv.stream_answer("what is attention in transformers?"):
if ev["type"] == "delta": print(ev["text"], end="")
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key. |
403 | Admin token required. |
422 | Validation error, or a URL that could not be crawled. |
429 | Monthly quota exceeded on the free plan. |
Errors are JSON: {"error": "message"} (validation errors use FastAPI's detail array).