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:8080/api/v1/search?q=machine+learning&search_type=keyword"

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

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

# Keyword search with a custom result limit
curl "http://localhost:8080/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",
"template_id": "concept",
"label": "Machine Learning",
"properties": {},
"position": null,
"embedding": null,
"source_id": null,
"created_at": "2026-01-15T10:30:00",
"updated_at": "2026-01-15T10:30:00",
"edge_count": null,
"incoming_edge_count": null,
"outgoing_edge_count": null,
"citation_count": null,
"relationship_type_count": null
},
"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`NodeResponsenull`
chunk`ChunkResultnull`

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:8080/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:8080/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:8080/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

{
"task_id": "task-rebuild-abc123",
"success": true,
"total_nodes": 1500,
"nodes_with_embeddings": 0,
"chunks_indexed": 3400,
"message": "Embeddings need regeneration. Queued re-embedding for 1500 nodes and 3400 chunks."
}
Tracking progress

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

RebuildIndexResponse

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
task_idstring?Background task ID (only present for 202 responses)

Generate Missing Embeddings

POST /api/v1/search/embeddings

Queues embedding generation for all graph nodes that do not yet have vector embeddings. Processing happens asynchronously in the background via the Operations queue.

Monitor progress

Use GET /api/v1/search/stats to check vector_index_size as embeddings are generated.

Use Cases

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

Example

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

Response

202 Accepted

{
"success": true,
"total_nodes": 1500,
"nodes_queued": 300,
"message": "Queued 300 nodes for embedding generation"
}

GenerateEmbeddingsResponse

FieldTypeDescription
successboolWhether the queuing completed successfully
total_nodesintTotal nodes in the graph
nodes_queuedintNumber of nodes queued for embedding generation
messagestringHuman-readable status message