Search
Text, regex, filters, vectors, counts.
Search
/v1/namespaces/{name}/search metered: query Exact text (literal, ignoring case) or regex (RE2), filtered by metadata, newest first with the matched text and its line; or, with vector, the nearest documents (alone, or hybrid with q and filter). Filters prune before any document is read. Counts as one query (metered; see Usage).
Parameters
namestring · pathrequiredThe namespace's name. |
Body application/json
qstringPlain text, matched literally and ignoring case; with regex an RE2 pattern. Empty: list documents, newest first. With a vector: only documents containing it (hybrid). Default "". |
regexbooleanDefault false. |
filterFilterEvery key must hold. {"status": "open"} equal; {"status": ["open", "pending"]} or {"status": {"in": [...]}} one of; {"priority": {"gte": 2, "lt": 5}} a numeric range (gt, gte, lt, lte); {"team": {"ne": "api"}} not equal (a missing key counts as not equal). Numbers compare as numbers. |
limitintegerHits a page (20; vector search 10). |
semanticstringSearch by meaning with a text, in a namespace with an embedding model (embed): it is embedded with that model and the tenant's key, then searched like vector (q and filter narrow it). |
cursorstringThe next of the previous page. |
scanbooleanAllow a regex the index can't narrow to scan a big namespace (otherwise 422 scan_refused). Default false. |
vectornumber[]An embedding: as many numbers as the namespace's dims. |
vector_b64stringThe vector as base64 of little-endian float32s (smaller than JSON numbers). |
nprobeintegerVector search: clusters probed in the biggest index (48). |
rerankintegerVector search: candidates reranked (64). |
fullbooleanVector search: rerank with the float32 vectors as written. Default false. |
Answer
namespacestring |
hitsHit[]Newest first (text) or nearest first (vector). |
hits[].idstring |
hits[].matchstringText search: the matched text. |
hits[].linestringText search: the line around the match. |
hits[].scorenumberVector search: cosine similarity (cosine namespaces) or euclidean distance. |
hits[].metaobject |
hits[].written_atstring |
nextstringText search: pass as cursor for the next page (empty: no more). |
docsintegerDocuments in the namespace. |
took_msnumber |
partialbooleanObject storage failed for some reads: hits may be missing. |
scannedintegerVector search: candidates estimated. |
rerankedintegerVector search: candidates reranked. |
temperaturestringHow warm the namespace was: warm (open), local (opened from the server's disk) or cold (opened from object storage). |
store_getsintegerObject-storage reads this query made (0 when warm). |
store_bytesintegerBytes those reads fetched. |
cpu_msnumberCPU the query used (metered, not billed). |
timed_outbooleanThe query ran past the plan's time limit (query_seconds): the answer is partial. |
Status codes
200OK |
400Malformed: not the JSON expected. |
401No key, or an unknown or revoked one. |
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro. |
403The key's scope or namespaces don't allow it, or the tenant is suspended. |
404No such namespace, document, key or tenant (or one this key may not see: the same answer). |
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true). |
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds. |
502Billing (Stripe) is unavailable right now. |
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe). |
curl -s https://api.skimmerdb.com/v1/namespaces/support/search \
-H "Authorization: Bearer $KEY" \
-d '{"q":"acme-1042","filter":{"status":"open"}}'from skimmerdb import SkimmerDB
from skimmerdb._api.api.search import search
from skimmerdb._api.models import SearchRequest
db = SkimmerDB() # SKIMMERDB_KEY
answer = search.sync("support", client=db.api, body=SearchRequest.from_dict({"q":"acme-1042","filter":{"status":"open"}}))import { SkimmerDB } from "skimmerdb";
import { search } from "skimmerdb/api";
const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await search({ client: db.client, path: { name: "support" }, body: {"q":"acme-1042","filter":{"status":"open"}} });{
"namespace": "support",
"hits": [
{
"id": "t-1",
"match": "ACME-1042",
"line": "Refund requested for order ACME-1042",
"meta": {
"priority": 3,
"status": "open"
},
"written_at": "2026-10-05T01:30:12Z"
}
],
"next": "",
"docs": 2,
"took_ms": 0.41,
"partial": false,
"temperature": "warm",
"store_gets": 0,
"store_bytes": 0,
"cpu_ms": 0.12,
"timed_out": false
}Search (query string)
/v1/namespaces/{name}/search metered: query Text search as GET, the same answer as POST. Counts as one query (metered; see Usage).
Parameters
namestring · pathrequiredThe namespace's name. |
qstring · queryText (or a regex with regex=1); empty lists documents. |
regexboolean · queryq is an RE2 pattern. |
filterstring · queryA filter as JSON text, e.g. {"status":"open"}. |
limitinteger · queryHits a page (20). |
cursorstring · queryThe next of the previous page. |
scanboolean · queryAllow a regex the index can't narrow to scan a big namespace. |
Answer
namespacestring |
hitsHit[]Newest first (text) or nearest first (vector). |
hits[].idstring |
hits[].matchstringText search: the matched text. |
hits[].linestringText search: the line around the match. |
hits[].scorenumberVector search: cosine similarity (cosine namespaces) or euclidean distance. |
hits[].metaobject |
hits[].written_atstring |
nextstringText search: pass as cursor for the next page (empty: no more). |
docsintegerDocuments in the namespace. |
took_msnumber |
partialbooleanObject storage failed for some reads: hits may be missing. |
scannedintegerVector search: candidates estimated. |
rerankedintegerVector search: candidates reranked. |
temperaturestringHow warm the namespace was: warm (open), local (opened from the server's disk) or cold (opened from object storage). |
store_getsintegerObject-storage reads this query made (0 when warm). |
store_bytesintegerBytes those reads fetched. |
cpu_msnumberCPU the query used (metered, not billed). |
timed_outbooleanThe query ran past the plan's time limit (query_seconds): the answer is partial. |
Status codes
200OK |
400Malformed: not the JSON expected. |
401No key, or an unknown or revoked one. |
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro. |
403The key's scope or namespaces don't allow it, or the tenant is suspended. |
404No such namespace, document, key or tenant (or one this key may not see: the same answer). |
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true). |
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds. |
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe). |
curl -s https://api.skimmerdb.com/v1/namespaces/support/search \
-H "Authorization: Bearer $KEY"from skimmerdb import SkimmerDB
from skimmerdb._api.api.search import search_get
db = SkimmerDB() # SKIMMERDB_KEY
answer = search_get.sync("support", client=db.api)import { SkimmerDB } from "skimmerdb";
import { searchGet } from "skimmerdb/api";
const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await searchGet({ client: db.client, path: { name: "support" } });Count
/v1/namespaces/{name}/count metered: query Exact: every visible document that matches. exact: false estimates from a sample (lo..hi a 95% interval). Counts as one query (metered; see Usage).
Parameters
namestring · pathrequiredThe namespace's name. |
Body application/json
qstringDefault "". |
regexbooleanDefault false. |
filterFilterEvery key must hold. {"status": "open"} equal; {"status": ["open", "pending"]} or {"status": {"in": [...]}} one of; {"priority": {"gte": 2, "lt": 5}} a numeric range (gt, gte, lt, lte); {"team": {"ne": "api"}} not equal (a missing key counts as not equal). Numbers compare as numbers. |
exactbooleanfalse: estimate from a sample of the candidates (fast on big namespaces; no filters). Default true. |
sampleintegerEstimates: candidates checked (2,000). |
scanbooleanAllow a regex the index can't narrow to scan a big namespace (otherwise 422 scan_refused). Default false. |
Answer
namespacestring |
countinteger |
exactbooleanfalse: count is an estimate (lo..hi is its 95% interval). |
samplestring[]Some matching ids. |
docsinteger |
took_msnumber |
partialboolean |
temperaturestringHow warm the namespace was: warm (open), local (opened from the server's disk) or cold (opened from object storage). |
store_getsinteger |
store_bytesinteger |
lointeger |
hiinteger |
candidatesinteger |
cpu_msnumber |
Status codes
200OK |
400Malformed: not the JSON expected. |
401No key, or an unknown or revoked one. |
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro. |
403The key's scope or namespaces don't allow it, or the tenant is suspended. |
404No such namespace, document, key or tenant (or one this key may not see: the same answer). |
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true). |
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds. |
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe). |
curl -s https://api.skimmerdb.com/v1/namespaces/support/count \
-H "Authorization: Bearer $KEY" \
-d '{"q":"refund","filter":{"status":"open"}}'from skimmerdb import SkimmerDB
from skimmerdb._api.api.search import count
from skimmerdb._api.models import CountRequest
db = SkimmerDB() # SKIMMERDB_KEY
answer = count.sync("support", client=db.api, body=CountRequest.from_dict({"q":"refund","filter":{"status":"open"}}))import { SkimmerDB } from "skimmerdb";
import { count } from "skimmerdb/api";
const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await count({ client: db.client, path: { name: "support" }, body: {"q":"refund","filter":{"status":"open"}} });{
"namespace": "support",
"count": 1,
"exact": true,
"sample": [
"t-1"
],
"docs": 2,
"took_ms": 0.2,
"partial": false,
"temperature": "warm",
"store_gets": 0,
"store_bytes": 0,
"lo": 1,
"hi": 1,
"candidates": 1,
"cpu_ms": 0.05
}Count (query string)
/v1/namespaces/{name}/count metered: query Count as GET. Counts as one query (metered; see Usage).
Parameters
namestring · pathrequiredThe namespace's name. |
qstring · queryText (or a regex with regex=1); empty lists documents. |
regexboolean · queryq is an RE2 pattern. |
filterstring · queryA filter as JSON text, e.g. {"status":"open"}. |
scanboolean · queryAllow a regex the index can't narrow to scan a big namespace. |
exactboolean · query0: estimate. |
sampleinteger · queryEstimates: candidates checked. |
Answer
namespacestring |
countinteger |
exactbooleanfalse: count is an estimate (lo..hi is its 95% interval). |
samplestring[]Some matching ids. |
docsinteger |
took_msnumber |
partialboolean |
temperaturestringHow warm the namespace was: warm (open), local (opened from the server's disk) or cold (opened from object storage). |
store_getsinteger |
store_bytesinteger |
lointeger |
hiinteger |
candidatesinteger |
cpu_msnumber |
Status codes
200OK |
400Malformed: not the JSON expected. |
401No key, or an unknown or revoked one. |
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro. |
403The key's scope or namespaces don't allow it, or the tenant is suspended. |
404No such namespace, document, key or tenant (or one this key may not see: the same answer). |
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true). |
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds. |
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe). |
curl -s https://api.skimmerdb.com/v1/namespaces/support/count \
-H "Authorization: Bearer $KEY"from skimmerdb import SkimmerDB
from skimmerdb._api.api.search import count_get
db = SkimmerDB() # SKIMMERDB_KEY
answer = count_get.sync("support", client=db.api)import { SkimmerDB } from "skimmerdb";
import { countGet } from "skimmerdb/api";
const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await countGet({ client: db.client, path: { name: "support" } });Warm a namespace
/v1/namespaces/{name}/warm metered: query Opens the namespace and fetches what these searches will need, so an agent about to work on it gets warm answers from its first query. Counts as one query (metered; see Usage).
Parameters
namestring · pathrequiredThe namespace's name. |
Body application/json
queriesstring[]Searches about to be made: their document lists are fetched now. |
regexbooleanDefault false. |
Answer
namespacestring |
temperaturestringBefore warming: warm, local or cold. |
store_getsinteger |
store_bytesinteger |
took_msnumber |
Status codes
200OK |
400Malformed: not the JSON expected. |
401No key, or an unknown or revoked one. |
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro. |
403The key's scope or namespaces don't allow it, or the tenant is suspended. |
404No such namespace, document, key or tenant (or one this key may not see: the same answer). |
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true). |
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds. |
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe). |
curl -s https://api.skimmerdb.com/v1/namespaces/support/warm \
-H "Authorization: Bearer $KEY" \
-d '{"queries":["refund","ERR-404"]}'from skimmerdb import SkimmerDB
from skimmerdb._api.api.search import warm_namespace
from skimmerdb._api.models import WarmRequest
db = SkimmerDB() # SKIMMERDB_KEY
answer = warm_namespace.sync("support", client=db.api, body=WarmRequest.from_dict({"queries":["refund","ERR-404"]}))import { SkimmerDB } from "skimmerdb";
import { warmNamespace } from "skimmerdb/api";
const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await warmNamespace({ client: db.client, path: { name: "support" }, body: {"queries":["refund","ERR-404"]} });{
"namespace": "support",
"temperature": "cold",
"store_gets": 3,
"store_bytes": 18211,
"took_ms": 41.5
}