API Reference
Ragz exposes a REST API for everything the web app does — auth, workspaces, documents, chat — plus a separate, API-key-authenticated surface for programmatic and OpenAI-compatible access. Every route returns JSON (chat responses stream as Server-Sent Events).
The source of truth
This section is a guided tour. The complete, always-accurate machine-readable
spec is served live by the backend at /api/openapi.json (interactive
Swagger UI at /api/docs, when enabled). If anything here and the running
server disagree, the server wins — generate your client from the OpenAPI
document, don't hand-write it against these pages.
Base URLs
| Surface | Base path | Auth |
|---|---|---|
| Web app / session API | /api/v1 | Bearer JWT (access token) |
| External / programmatic API | /external/v1 | API key |
A self-hosted instance is reachable at whatever origin you deployed it to —
these examples use https://ragz.example.com.
curl https://ragz.example.com/api/openapi.jsonTwo auth modes
- Session JWT — used by the Ragz web app. A 15-minute access token
(
Authorization: Bearer <token>) issued byPOST /api/v1/auth/login, backed by a rotating refresh token in anhttpOnlycookie. See Authentication. - API keys — used by scripts, backend integrations, and the
OpenAI-compatible endpoint. A superadmin
issues a key scoped to one user and one workspace; it's sent the same way,
as a bearer token (or
X-API-Key), against the/external/v1/*routes.
Both credential types resolve to the same tenant-scoped permission model — an API key can never see more than the workspace it was issued for.
Errors
Every error response is application/problem+json (RFC 9457):
{
"type": "about:blank",
"title": "Not permitted",
"status": 403,
"detail": "requires permission documents.upload"
}Common status values: 400 bad request, 401 authentication failed,
403 not permitted, 404 not found, 409 conflict, 413 payload too
large, 429 rate limited / quota exhausted, 502 upstream (LLM/provider)
error.
Rate limiting
Auth endpoints (login, register, refresh, password reset, invitation
accept) and chat message sends are rate-limited per account/user — a 429
with Too many requests means back off and retry. Limits are enforced
server-side (Redis-backed); there is no client-visible quota header today.
Pagination and streaming
- List endpoints (documents, chats, audit events) return a plain JSON array
or an explicit
{ rows: [...] }/ cursor page — check each endpoint's response model in the OpenAPI spec. - The audit log (
GET /api/v1/admin/audit) is cursor-paginated (cursorquery param,next_cursorin the response). - Chat is streamed:
POST /api/v1/chats/{id}/messagesandPOST /messages/{id}/regeneraterespond withtext/event-stream(Server-Sent Events), not a single JSON body. See Chat for the event frames.
Multi-tenant by construction
Every route above is scoped to the caller's organization and workspace membership. There is no way to pass a different tenant's id and read its data — that boundary is enforced server-side on every request, not just in the UI.