Skip to main content

Search API

Full-text and semantic search across indexed documents and knowledge graph entities.

Base path: /api/v1/search

Related pages

GET /api/v1/search

Run a search query using keyword, semantic, or hybrid strategies.

Query Parameters

ParameterTypeRequiredDefaultDescription
qstringYes--Search query string
search_typestringNokeywordSearch strategy: keyword, semantic, or hybrid
limitintNo50Maximum number of results (min: 1, capped at server max: 1000)

Search Types

TypeDescription
keywordFull-text keyword search against the FTS index
semanticVector similarity search using embeddings
hybridSemantic search with automatic keyword fallback if no vector results are found
Limit behavior

When limit is not provided, the server default page size (50) is used. Values exceeding the server maximum (1000) are clamped automatically.

Examples

# Keyword search
curl "http://localhost/api/v1/search?q=machine+learning&search_type=keyword"

# Semantic search
curl "http://localhost/api/v1/search?q=artificial+intelligence&search_type=semantic"

# Hybrid search (semantic with keyword fallback)
curl "http://localhost/api/v1/search?q=neural+networks&search_type=hybrid"

# Keyword search with a custom result limit
curl "http://localhost/api/v1/search?q=deep+learning&search_type=keyword&limit=10"

Response

200 OK

{
"data": [
{
"result_type": "chunk",
"score": 0.89,
"node": null,
"chunk": {
"chunk_id": "chunk-abc123",
"source_id": "src-def456",
"chunk_index": 5,
"content": "Machine learning is a subset of artificial intelligence...",
"page_number": 3,
"section": "Introduction",
"filename": "paper.pdf"
}
},
{
"result_type": "node",
"score": 0.75,
"node": {
"id": "node-789ghi",
"label": "Machine Learning",
"template_id": "concept",
"edge_count": 7
},
"chunk": null
}
],
"type": "keyword"
}

SearchResponse

FieldTypeDescription
dataSearchResult[]Array of search results
typestringSearch type used: keyword, semantic, or hybrid

SearchResult

FieldTypeDescription
result_typestring"node" or "chunk"
scorefloatRelevance score
node`SearchNodeHitnull`
chunk`ChunkResultnull`

SearchNodeHit

A narrow projection of a graph node — only the fields the search engine actually populates. Full node payloads (properties, position, embedding, timestamps, citation counts) are never present in search results; fetch the node via the Nodes API when you need them.

FieldTypeDescription
idstringNode identifier
labelstringNode label
template_idstring or nullTemplate the node was created from (null if untemplated)
edge_countintNumber of edges connected to the node (batched lookup; default 0)

ChunkResult

FieldTypeDescription
chunk_idstringUnique chunk identifier
source_idstringParent source document identifier
chunk_indexintPosition of the chunk within the source
contentstringChunk text content
page_numberint or nullPage number (if available)
sectionstring or nullSection heading (if available)
filenamestringSource filename

Index Statistics

GET /api/v1/search/stats

Returns statistics about the current search indexes.

Example

curl "http://localhost/api/v1/search/stats"

Response

200 OK

{
"fulltext_doc_count": 1500,
"vector_index_size": 1500,
"vector_dimension": 1024
}

SearchStatistics

FieldTypeDescription
fulltext_doc_countintNumber of documents in the fulltext index
vector_index_sizeintNumber of vectors in the sqlite-vec index
vector_dimensionintDimensionality of stored vectors

Index Status

GET /api/v1/search/indexes/status

Check whether the search indexes need rebuilding. Returns the current model and dimension configuration alongside live index row counts. Use this before calling POST /api/v1/search/indexes to decide whether a full reindex is required.

Example

curl "http://localhost/api/v1/search/indexes/status"

Response

200 OK

{
"needs_rebuild": false,
"embedding_model": "nomic-embed-text",
"vector_dimensions": 768,
"fulltext": {
"document_count": 1500
},
"vector": {
"vector_count": 1500,
"dimensions": 768
},
"error": null
}
FieldTypeDescription
needs_rebuildbooltrue when the persisted model/dimensions no longer match the index — a full reindex is required
embedding_modelstring | nullName of the embedding model the index was built against
vector_dimensionsint | nullDimensionality of vectors currently in the index
fulltextobject | nullFulltext index stats (e.g. {"document_count": int})
vectorobject | nullVector index stats (e.g. {"vector_count": int, "dimensions": int})
errorstring | nullPopulated when index stats could not be read (e.g. table missing)

Rebuild Indexes

POST /api/v1/search/indexes

Rebuilds search indexes from all graph nodes and document chunks. Auto-detects whether embeddings need regeneration based on the current embedding model configuration.

  • Fast rebuild (FTS-only): When embeddings are current, only the fulltext index is rebuilt. Returns 200 OK immediately.
  • Full rebuild (with re-embedding): When the embedding model or dimensions have changed, queues a background job to regenerate all embeddings. Returns 202 Accepted with a task ID.

Use Cases

  • After bulk imports
  • When an index is corrupted
  • After manual graph modifications
  • After changing the embedding model (triggers full re-embedding)

Example

curl -X POST "http://localhost/api/v1/search/indexes"

Response (Fast Rebuild)

200 OK

{
"success": true,
"total_nodes": 1500,
"nodes_with_embeddings": 1200,
"chunks_indexed": 3400,
"message": "Search indexes rebuilt successfully"
}

Response (Full Rebuild with Re-embedding)

202 Accepted — returns a different model, QueuedRebuildResponse:

{
"task_id": "task-rebuild-abc123",
"status": "queued",
"regenerated": true,
"message": "Embedding regeneration and index rebuild queued"
}
Tracking progress

When a 202 response is returned, use GET /api/v1/queue/tasks/{task_id} to monitor the re-embedding job.

RebuildIndexResponse (200 OK)

FieldTypeDescription
successboolWhether the rebuild completed successfully
total_nodesintTotal nodes processed
nodes_with_embeddingsintNodes that have vector embeddings
chunks_indexedintNumber of document chunks indexed (default: 0)
messagestringHuman-readable status message

QueuedRebuildResponse (202 Accepted)

FieldTypeDescription
task_idstringBackground task ID for the queued re-embedding job
statusstringAlways "queued"
regeneratedboolAlways true — embeddings will be regenerated
messagestringAlways "Embedding regeneration and index rebuild queued"

Generate Missing Embeddings

POST /api/v1/search/embeddings

Generates embeddings synchronously for every graph node missing one — the request blocks until done and can take minutes on large graphs. Each embedding is generated inline before the response is returned.

Blocking request

This endpoint does not queue background work. On a graph with many unembedded nodes, expect a long-running request — set a generous client timeout.

Use Cases

  • Existing nodes created before auto-embedding was enabled
  • Nodes imported from external sources without embeddings

Example

curl -X POST "http://localhost/api/v1/search/embeddings"

Response

200 OK

{
"success": true,
"total_nodes": 1500,
"processed_count": 300,
"message": "Generated embeddings for 300 nodes"
}

If some nodes fail, the failure count is appended to the message, e.g. "Generated embeddings for 295 nodes (5 failed)".

GenerateEmbeddingsResponse

FieldTypeDescription
successboolWhether the run completed
total_nodesintTotal nodes in the graph
processed_countintNumber of nodes that received a new embedding
messagestringHuman-readable status message