Privacy-first document Q&A with local RAG
SafeQueryAI exposes REST endpoints for session lifecycle, file handling, and document question-answering.
http://localhost:5000/api
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/sessions |
Create a new session |
GET |
/sessions/{sessionId} |
Get session metadata |
DELETE |
/sessions/{sessionId} |
Delete a session |
GET |
/sessions/{sessionId}/files |
List session files |
POST |
/sessions/{sessionId}/files |
Upload PDF or CSV file |
POST |
/sessions/{sessionId}/questions |
Ask question (single response) |
POST |
/sessions/{sessionId}/questions/stream |
Ask question (SSE stream) |
GET |
/health |
Liveness check |
POST /sessions
Response example:
{
"sessionId": "uuid-string",
"createdAt": "2026-03-18T12:30:00Z"
}
GET /sessions/{sessionId}
Response example:
{
"sessionId": "uuid-string",
"createdAt": "2026-03-18T12:30:00Z"
}
DELETE /sessions/{sessionId}
Response example:
{
"sessionId": "uuid-string",
"cleared": true,
"message": "Session cleared. All uploaded files have been removed."
}
GET /sessions/{sessionId}/files
Response example:
{
"sessionId": "uuid-string",
"files": [
{
"fileId": "file-id",
"originalFileName": "document.pdf",
"fileType": "pdf",
"fileSizeBytes": 102400,
"uploadedAt": "2026-03-18T12:31:00Z"
}
]
}
POST /sessions/{sessionId}/files
Content-Type: multipart/form-data
Form field:
- file (required)
Constraints:
.pdf, .csv20 MB25 MBResponse example:
{
"fileId": "file-id",
"fileName": "document.pdf",
"fileType": "pdf",
"fileSizeBytes": 102400,
"uploadedAt": "2026-03-18T12:31:00Z"
}
POST /sessions/{sessionId}/questions
Content-Type: application/json
{
"question": "What does the document say about...?"
}
Response example:
{
"question": "What does the document say about...?",
"answer": "...",
"hasConfidentAnswer": true,
"evidence": [
{
"fileName": "document.pdf",
"snippet": "..."
}
]
}
POST /sessions/{sessionId}/questions/stream
Content-Type: application/json
Accept: text/event-stream
{
"question": "What does the document say about...?"
}
SSE event types:
{"type":"token","content":"..."}{"type":"done","question":"...","hasConfidentAnswer":true,"evidence":[...]}Frontend consumption example:
const response = await fetch(`/api/sessions/${sessionId}/questions/stream`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' },
body: JSON.stringify({ question })
});
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = new TextDecoder().decode(value);
// Parse data: lines
}
GET /health
Response example:
{
"status": "healthy",
"timestamp": "2026-03-18T12:30:00Z"
}
Error payloads generally use:
{
"error": "Error summary",
"detail": "Optional additional detail"
}
Common cases:
| Code | Message | Solution |
|---|---|---|
| 400 | Invalid request | Validate payload and required fields |
| 404 | Session not found | Create a new session and retry |
| 400 | Unsupported file type | Use PDF or CSV |
| 400 | File too large | Keep file at or under configured limit |
Frontend development server proxies /api to backend:
http://localhost:5173http://localhost:5000This removes the need for manual CORS configuration during local development.
{
"question": "string (1-2000 chars)"
}