vector-auditor / BACKEND_API.md
AkshayM
production hardening: circuit breakers, graceful degradation, health checks, parallel uploads, HF Spaces deploy config
fc2fe9f
|
Raw
History Blame Contribute Delete
6.9 kB

Backend API Contract β€” Frontend Reference

Base URL: http://localhost:8000

Authentication

All endpoints except /auth/* and /health//ready require:

Authorization: Bearer <access_token>

Auth Endpoints

Method Path Request Response
POST /auth/register { email, password, first_name?, last_name? } UserResponse
POST /auth/login { email, password } { access_token, user_id, roles }
POST /auth/logout β€” 204
GET /auth/token/refresh β€” { access_token }
POST /auth/mfa/setup β€” { secret, uri, qr_code_url }
POST /auth/mfa/verify { code } UserResponse
GET /auth/oauth/config β€” { github_client_id }
POST /auth/oauth/github { code } LoginResponse

Documents

Upload β€” POST /documents

Content-Type: multipart/form-data
Body: files[] = (binary PDF files)

Returns { uploaded_documents: [{ upload_id, document_id, filename, status }] }

Documents process asynchronously. Poll GET /uploads/{upload_id} for status.

List Documents β€” GET /documents

Response: [
  {
    id: string,
    filename: string,
    status: "processing" | "ready" | "failed",
    has_pii: bool,
    cloudinary_url: string | null,   // PDF viewing URL
    uploaded_by: string,
    created_at: string | null
  }
]

Get Document β€” GET /documents/{doc_id}

Returns single DocumentResponse (same shape as list item).

Delete Document β€” DELETE /documents/{doc_id}

204 No Content.

Backfill Cloudinary β€” POST /documents/backfill

Re-uploads old docs to Cloudinary. Returns { backfilled: number, total: number }.

Upload Status β€” GET /uploads/{upload_id}

{
  id, filename, stage, progress, error?, document_id?, user_id, created_at?, updated_at?
}

Stages: uploading β†’ extracting β†’ chunking β†’ embedding β†’ indexing β†’ completed

Query

Non-streaming β€” POST /query

{
  "question": "what is attention?",
  "document_ids": ["uuid1", "uuid2"],   // optional, null = all docs
  "mode": "white_box",                   // "white_box" | "black_box"
  "max_citations": 20,                   // optional, 1-100
  "conversation_history": [              // optional, last 6 turns max
    { "role": "user", "content": "..." },
    { "role": "assistant", "content": "..." }
  ]
}

Response:

{
  "answer": "The Transformer uses multi-head attention... [1][2]",
  "citations": [
    {
      "quote": "excerpt from the document",
      "source": "attention_paper.pdf",       // filename
      "location": "page 3 / chunk 5",
      "page": 3,
      "document_id": "uuid"
    }
  ],
  "reasoning_path": ["Retrieved 6 citations across 2 hop(s)", "VERIFIED"],
  "tokens_used": 450,
  "cost_usd": 0.0009,
  "query_id": "hex",
  "verification": "VERIFIED"               // white_box only, null for black_box
}

Streaming β€” POST /query/stream

Same request body. Server-Sent Events (SSE):

data: {"type": "citations", "citations": [...], "query_id": "...", "reasoning_path": [...]}
data: {"type": "token", "content": "The"}
data: {"type": "token", "content": " Transformer"}
data: {"type": "token", "content": " uses..."}
data: {"type": "verification", "content": "VERIFIED"}       // white_box only
data: {"type": "gap_analysis", "content": "missing X"}       // white_box only, one per gap
data: {"type": "done", "tokens_used": 450, "cost_usd": 0.0009, "mode": "white_box", "query_id": "..."}
data: [DONE]

Citation click: Use citation.document_id β†’ fetch GET /documents/{document_id} β†’ read cloudinary_url β†’ open in PDF viewer at that URL.

Analyze

POST /analyze

{
  "question": "Compare their methodologies",    // optional
  "document_ids": ["uuid1", "uuid2"],           // optional, null = error
  "max_citations": 20
}

Response:

{
  "summary": "Both papers use Transformer-based architectures...",
  "key_findings": ["Finding 1", "Finding 2", "..."],
  "methodology": "Description of methods...",
  "research_gaps": ["Gap 1", "Gap 2"],
  "contradictions": ["Contradiction 1"],
  "open_questions": ["Question 1"],
  "limitations": "Only 3 documents analyzed",
  "confidence": "high",
  "citations": [/* same Citation shape as query */],
  "documents_analyzed": ["doc-uuid-1", "doc-uuid-2"],
  "cross_document_comparison": {
    "common_themes": ["both use attention"],
    "differences": ["doc1 uses BERT, doc2 uses GPT"],
    "complementary_insights": ["doc1's findings on X support doc2's Y"]
  },                                      // null when single doc
  "per_document_summary": {
    "paper1.pdf": "Introduces Transformer...",
    "paper2.pdf": "Applies BERT to..."
  }                                       // null when single doc
}

PDF Viewer Flow

  1. Query returns citations with document_id
  2. Frontend user clicks citation [N]
  3. Frontend calls GET /documents/{document_id} β†’ gets cloudinary_url
  4. Opens Cloudinary URL in PDF viewer (iframe or new tab)

Cloudinary URL format: https://res.cloudinary.com/da1nocxo0/image/upload/v.../{user_id}/{doc_id}.pdf

The cloudinary_url is always set for new uploads. For old docs, run POST /documents/backfill once.

Sessions (Chat History)

Method Path Notes
GET /sessions List all sessions
POST /sessions Create new session
GET /sessions/{sid} Session with messages
PUT /sessions/{sid} Update title
DELETE /sessions/{sid} Delete session
GET /sessions/{sid}/messages List messages
POST /sessions/{sid}/messages Add message
POST /sessions/{sid}/feedback Thumbs up/down

Query Modes

White Box (default)

  • Temperature: default (some variation)
  • Max tokens: 3048
  • Streams: verification + gap_analysis events
  • Multi-hop retrieval (up to 3 rounds)
  • Reasoning path included
  • Structured answer with sections

Black Box

  • Temperature: 0 (deterministic)
  • Max tokens: default (2048)
  • No verification, no gap analysis, no reasoning
  • Single-pass retrieval only
  • Minimal answer β€” just the cited response, no commentary

Greeting Detection

All three endpoints (/query, /query/stream, /analyze) detect greetings and return a friendly message without calling the LLM or searching documents:

"Hi there! What would you like to know about your documents?"   // /query, /query/stream
"Hi there! Please select documents to analyze, or ask me a question about your documents."  // /analyze

Common Error Codes

Code Meaning
401 Missing/invalid token
400 Guardrails blocked the query
413 File too large (max 50MB)
502 LLM provider unreachable
429 Rate limited (20/min for query, 10/min for analyze)