Search
Search Ideas
Section titled “Search Ideas”GET /api/v1/ideas/search
Searches your unarchived ideas by meaning (default) or by keyword. The two modes are separate engines with separate result shapes — the response tells you which one ran.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Yes | — | Search query, max 500 characters |
mode | string | No | semantic | keyword or semantic; anything else returns 400 |
limit | number | No | 20 | Clamped to 100. Keyword mode can return up to 2× this |
fts_mode | string | No | or | Keyword matching: or, and, or exact |
min_score | number | No | 0.2 | Semantic score floor; overrides your search_threshold setting |
There is no offset — search is not paginated. Raise limit instead.
Semantic Search
Section titled “Semantic Search”The default mode. The query is embedded, matched against your idea vectors, filtered by score,
and then reranked by a second model before being cut to limit.
curl "https://neuralrepo.com/api/v1/ideas/search?q=user+interface+theming" \ -H "X-API-Key: nrp_YOUR_KEY"Two consequences worth knowing:
- Results are ordered by the reranker, not by raw
score, so scores are not guaranteed to descend down the list. - Ideas captured seconds ago may be missing. An idea is only searchable once its queued
embedding lands (
vectorize_idstops beingnull).
Only ideas scoring strictly above min_score survive. The default floor is 0.2; your
search_threshold user setting replaces it, and an explicit min_score parameter overrides
both.
Keyword Search
Section titled “Keyword Search”Keyword mode queries the SQLite FTS5 index over titles and bodies, ordered by BM25 rank.
curl "https://neuralrepo.com/api/v1/ideas/search?q=dark+mode&mode=keyword" \ -H "X-API-Key: nrp_YOUR_KEY"const params = new URLSearchParams({ q: "dark mode", mode: "keyword", fts_mode: "and",});const res = await fetch( `https://neuralrepo.com/api/v1/ideas/search?${params}`, { headers: { "X-API-Key": "nrp_YOUR_KEY" } });const results = await res.json();Before matching, the query is lowercased, stripped of punctuation, and split on whitespace.
Tokens of one character and common stop words (the, and, for, what, this, and about
sixty others) are dropped. A query made entirely of stop words matches nothing — "how to do it" reduces to zero tokens and returns an empty array.
fts_mode controls how the surviving tokens are combined:
fts_mode | Behaviour | dark mode becomes |
|---|---|---|
or (default) | Any token matches | "dark" OR "mode" |
and | Every token must match | "dark" "mode" |
exact | The raw phrase, quoted; stop words are kept | "dark mode" |
Response
Section titled “Response”200 OK
The response echoes the query, reports search_type (semantic or fts), and — in keyword
mode — the fts_mode that ran.
{ "query": "user interface theming", "search_type": "semantic", "results": [ { "id": 137, "number": 42, "title": "Add dark mode support", "body": "Users have requested a dark theme...", "status": "exploring", "source": "web", "source_url": null, "is_archived": 0, "tags": ["ui", "feature-request"], "score": 0.92, "created_at": "2026-03-20 10:00:00", "updated_at": "2026-03-22 14:30:00" } ]}Score Field
Section titled “Score Field”| Mode | score |
|---|---|
fts | Always null — the BM25 rank orders the rows but is not returned |
semantic | Cosine similarity between the query and the idea embedding |
Free-plan semantic allowance
Section titled “Free-plan semantic allowance”Free accounts get 10 semantic searches per calendar month. Once they are spent, the endpoint serves keyword results instead and says so:
{ "query": "user interface theming", "search_type": "fts", "fts_mode": "or", "results": [], "semantic_limit_reached": true, "semantic_limit_message": "You've used all 10 semantic searches this month. Showing keyword results instead. Upgrade to Pro for unlimited semantic search."}Three details that surprise people:
- The counter is incremented before the search runs, so a search that errors or matches nothing still costs one of the ten.
mode=keywordrequests are free and never touch the counter.- The count resets on the first of the month; the underlying counter is stored per account-month with a 35-day expiry.
Pro accounts have no semantic-search limit. Both plans have unlimited keyword search.
Comparison
Section titled “Comparison”Keyword (mode=keyword) | Semantic (default) | |
|---|---|---|
| Engine | SQLite FTS5, BM25 rank | Vector index + reranker |
| Matches exact words | Yes | Not necessarily |
| Finds conceptual matches | No | Yes |
| Needs an embedding | No — searchable immediately | Yes — after the queue processes the idea |
Returns a score | No (null) | Yes |
Respects limit | Returns up to 2× | Yes |
| Free-plan limit | None | 10 per month |
Status Codes
Section titled “Status Codes”| Status | Meaning |
|---|---|
200 OK | Search completed — including when results is empty |
400 Bad Request | Missing q, or a mode other than keyword/semantic |
401 Unauthorized | Missing or invalid auth |