Skip to main content

Search

Semantic search across your workspace's documents using vector similarity (pgvector + Gemini embeddings). Search operates at the section-chunk level: it returns the most relevant passages of your documents along with their heading breadcrumbs, plus a single pre-formatted text block ready to drop into an LLM prompt.


Endpoint

GET /api/v1/search?q=<query>

Query parameters

NameTypeRequiredDefaultRangeDescription
qstringYes1–500 charsNatural language search query
limitnumberNo81–20Maximum chunks to return
document_idstring (UUID)NoRestrict the search to a single document
budget_tokensnumberNo1500100–8000Token budget for the formatted text block

There is no threshold parameter — results are ranked by relevance and capped at limit.


Example

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://app.sophic.so/api/v1/search?q=how+do+we+deploy+to+production&limit=8"

Response

The response has two top-level fields:

  • text — a single string that formats the matched passages (with heading breadcrumbs) for direct LLM consumption, truncated to budget_tokens. This is what the MCP search_knowledge_base tool surfaces to agents.
  • results — the structured matches, ordered by relevance.
{
"text": "## Production Deployment Runbook › Steps\n1. Run migrations...\n\n...",
"results": [
{
"chunk": {
"id": "f1e2...",
"content": "1. Run migrations against the primary...",
"section_id": "a9c0...",
"chunk_index": 0,
"distance": 0.18
},
"section": {
"id": "a9c0...",
"document_id": "abc123",
"heading_title": "Steps",
"heading_depth": 2,
"path": "1.3"
},
"ancestors": [
{ "id": "...", "node_id": "...", "heading_title": "Production Deployment Runbook", "heading_depth": 1 }
]
}
]
}

Each result is a section chunk:

FieldDescription
chunk.contentThe matched passage text
chunk.distanceCosine distance from the vector lane. null when the chunk surfaced only via the lexical lane (hybrid mode)
chunk.rrf_scoreFused reciprocal-rank score — present in hybrid mode only
section.document_idThe document this chunk belongs to — pass it to GET /api/v1/documents/:id for the full document
section.heading_title / heading_depth / pathThe heading the chunk lives under, and its position in the document outline
ancestorsThe chain of parent headings above the chunk, for breadcrumb context

How it works

  1. Your query is embedded using Google Gemini (gemini-embedding-001, 768 dimensions)
  2. The embedding is matched against document-section chunk vectors via the match_document_section_chunks Postgres RPC (pgvector cosine similarity), scoped to the workspace
  3. Ancestor headings are joined server-side so each chunk carries its outline context
  4. The matches are formatted into the text block within the budget_tokens budget
  5. If embedding generation or retrieval fails, the API returns 500 with { "error": "Search failed" }

  • GET /api/v1/grep — exact-string / regex search when you have a literal identifier rather than a concept.