Skip to main content
CodeSenseiSearch

API Reference

The deployed API serves all endpoints below at https://code-sensei-search-api.vercel.app/api. Swagger UI with live schemas is at /api/docs.

Conventions

No auth on search

The search, suggestions, and stats endpoints are public. Authentication is only required for admin and ingestion trigger routes (not documented here).

Rate limit

Global limit is 60 requests per minute per IP, enforced by NestJS Throttler. Requests that exceed the window get 429 with the standard rate-limit headers.

Response envelope

Successful responses wrap the payload in { success: true, data: ... }. Errors follow NestJS's standard { statusCode, message } shape.

CORS

Allowed origin is set via the FRONTEND_URL env var on the API. For local development, add your origin to the same var and redeploy, or run the API locally.

Endpoints

GET/api/health

Liveness + dependency reachability probe. Reports DB, Redis, and Gemini status independently. 200 when DB + Redis are up; 503 otherwise.

Request

curl https://code-sensei-search-api.vercel.app/api/health

Response

{
  "status": "ok",
  "timestamp": "2026-04-23T...",
  "service": "CodeSenseiSearch API",
  "version": "0.1.0",
  "uptimeSec": 42,
  "components": {
    "database": { "status": "up", "latencyMs": 21 },
    "redis":    { "status": "up", "latencyMs": 2 },
    "gemini":   { "status": "up" }
  }
}
POST/api/search/hybrid

Recommended default. Runs vector + full-text search in parallel, merges them with a configurable weighted score (default 0.6 vector / 0.4 text), and reranks the top K.

Request

curl -X POST https://code-sensei-search-api.vercel.app/api/search/hybrid \
  -H "content-type: application/json" \
  -d '{
    "query": "useEffect cleanup",
    "options": {
      "limit": 10,
      "vectorWeight": 0.6,
      "textWeight": 0.4
    }
  }'

Response

{
  "success": true,
  "data": {
    "query": "useEffect cleanup",
    "results": [
      {
        "id": "ckn...",
        "chunkText": "A useEffect cleanup runs on two occasions...",
        "similarity": 0.87,
        "source": "documentation",
        "language": "javascript",
        "title": "How do React useEffect cleanup functions work?"
      }
    ],
    "totalResults": 10,
    "searchTime": 112,
    "searchMethod": "hybrid",
    "metadata": {
      "embeddingGenerated": true,
      "vectorSearchUsed":   true,
      "textSearchUsed":     true,
      "vectorResults": 12,
      "textResults":   8,
      "mergedResults": 10
    }
  }
}
POST/api/search/semantic

Vector-only search. Embeds the query with Gemini RETRIEVAL_QUERY and returns top-K by cosine similarity against stored chunk embeddings.

Request

curl -X POST https://code-sensei-search-api.vercel.app/api/search/semantic \
  -H "content-type: application/json" \
  -d '{"query": "distributed lock with Redis", "options": {"limit": 5}}'

Response

{
  "success": true,
  "data": {
    "query": "distributed lock with Redis",
    "results": [ /* similar shape to hybrid, but no text-search metadata */ ],
    "totalResults": 5,
    "searchMethod": "semantic"
  }
}
POST/api/search/text

Full-text search via Postgres tsvector + ts_rank. Useful when you already know the keywords and want lexical precision.

Request

curl -X POST https://code-sensei-search-api.vercel.app/api/search/text \
  -H "content-type: application/json" \
  -d '{"query": "pgvector HNSW", "options": {"limit": 5}}'

Response

{
  "success": true,
  "data": {
    "query": "pgvector HNSW",
    "results": [ /* ... */ ],
    "totalResults": 3,
    "searchMethod": "text"
  }
}
GET/api/search/suggestions

Autocomplete hints for the search bar. Returns an array of suggested completions based on the prefix. Pass at least 2 chars.

Request

curl "https://code-sensei-search-api.vercel.app/api/search/suggestions?q=react"

Response

{
  "success": true,
  "data": {
    "query": "react",
    "suggestions": ["react useEffect", "react server components"]
  }
}
GET/api/search/stats

Corpus-wide counts. Chunks, chunks-with-embeddings, per-content-type split, and the list of languages present in the index.

Request

curl https://code-sensei-search-api.vercel.app/api/search/stats

Response

{
  "success": true,
  "data": {
    "totalChunks": 15,
    "chunksWithEmbeddings": 15,
    "embeddingCoverage": 1.0,
    "repositoryChunks": 0,
    "questionChunks": 0,
    "availableLanguages": ["javascript", "typescript", "python", "go", "rust"]
  }
}

Status codes

CodeNameWhen
400Bad RequestMissing `query` or invalid options
403ForbiddenOnly applies to guarded operator routes (/api/seed, /api/admin)
429Too Many RequestsGlobal rate limit of 60 requests per minute per IP is in effect on all routes
500Internal ErrorUnexpected server fault; check /api/health
503Service UnavailableReturned by /api/health when either the DB or Redis is down; transient, worth retrying