DDARE Docs
Backend

Backend API Reference

Human-readable REST API overview and links to interactive Swagger and Redoc.

The DARE backend API is auto-documented using drf-spectacular (OpenAPI 3.0).

Interactive Documentation

When the backend is running locally:

  • OpenAPI Schema: /api/schema/ — Raw JSON/YAML schema for code generation and the most reliable local API reference
  • Swagger UI: /api/docs/ — Interactive API explorer. This page loads Swagger UI assets from a CDN, so it may not render on offline or restricted networks.
  • ReDoc: /api/redoc/ — Clean, readable API reference

Authentication

All endpoints require JWT authentication unless noted otherwise. Include the access token in the Authorization header:

Authorization: Bearer <access_token>

Tokens are obtained via POST /users/api/dj-rest-auth/login/ and refreshed via POST /users/api/dj-rest-auth/token/refresh/.

API Overview

ModuleBase PathDescription
Auth/users/api/dj-rest-auth/Login, registration, password management
Conversations/api/conversations/Chat CRUD, messages, cloning, sharing
Ensemble presets/api/ensemble-presets/Private saved role briefs and per-seat angles
Files/api/files/Upload, processing, folders, tags
Workflows/api/workflows/Workflow CRUD, runs, versions
Prompts/api/prompts/Prompt template management
Agents/api/agents/AI agent configuration
LLM Models/api/llms/Available models and pricing
Billing/api/billing/Token usage and cost tracking
Notifications/api/notifications/User notifications
MCP/mcp/Model Context Protocol servers
DARE Tools/dare/Tool plugins
Memory/api/items/Context memory management
Sharing/api/sharing/Conversation and workflow sharing
API Keys/api/api-keys/External API key management

Ensemble briefs and presets

GET /api/ensemble-presets/defaults/ returns the authenticated user's effective responder, evaluator, and chairman role instructions. The preset collection supports paginated listing and creation; detail endpoints support retrieval, updates, and soft deletion. Presets are private to their owner.

Preset names accept up to 80 characters, role briefs up to 4,000 characters, and each positional seat angle up to 300 characters. Empty role text uses the default instructions. Multiple presets may share a name; clients identify them by ID.

Apply migration conversations.0100_ensemble_preset before deploying the briefs frontend. It adds a table without changing existing conversations. Panel/council execution remains controlled by the existing enable_ensemble feature flag.

Transaction history and exports

GET /api/billing/transactions/ pages the authenticated user's transactions, newest first. GET /api/billing/transactions/export/ returns every matching row as CSV, with costs at full six-decimal precision. Both accept the same optional query parameters; an invalid value returns 400.

ParameterValues
platformALL, DARE, SocraticBots; defaults to the caller's sign-in platform
billing_modewallet, own_api, litellm
modelan exact model name from models
created_afterISO 8601 datetime, inclusive
created_beforeISO 8601 datetime, exclusive; must follow created_after

The list response adds summary, counts per billing mode under every filter except billing_mode, and models, the model names on the selected platform. Deploy this API before the matching frontend. No migration is required.

LiteLLM background models

LiteLLM wallets expose one optional backgroundModel setting through /api/billing/wallets/litellm/. DARE uses it for invisible text work such as conversation titles, summaries, memory extraction, and advanced RAG query analysis. An empty value falls back to DARE's configured background model.

Both LiteLLM connection-test endpoints return models plus a nullable suggestedModel. The recommendation prefers GPT-5.6 Luna, then the newest Gemini Flash model, then another lightweight text model. Clients may highlight the recommendation, but the user remains free to select any returned model.

Group spend limits and refill caps

Group owners manage two per-member ceilings through PATCH /api/billing/group-wallets/{id}/ and the member override endpoint PUT /api/billing/group-wallets/{id}/members/{userId}/override/:

Field (group / override)Meaning
litellmMemberCap / litellmCapMost a member may spend, in total, through the group's LiteLLM keys. Measured at DARE's reference rates. Unset means no limit.
refillCap / refillCapScheduled refills top a DARE wallet up to this balance instead of adding the full amount. The group budget is charged only for what is added. Unset inherits the next tier (user → group → system); when no tier sets it, the refill amount is the ceiling, so balances never stack.

Each field has a matching clear* flag (clearLitellmMemberCap, clearLitellmCap, clearRefillCap) that unsets it. Amounts must be non-negative.

Member rows carry spendLimit (limit, used, source, isReached), or null when no limit applies. The group wallet carries gatewayKeys: for each of the group's keys, the gateway-reported spend and budget (read from x-litellm-key-* response headers) beside DARE's estimate, so the two can be reconciled without a gateway admin key. The student's GET /api/billing/wallets/ row for a group key includes the same spendLimit.

The group's owner sees the group's key without joining the group, is moved onto it when a key is issued or when they are assigned as owner, and is never held to the member limit.

A member who has used their limit cannot dispatch through the group key. Chat answers with the socket error spend_limit_reached; other paths raise PaymentRequiredError with code LITELLM_SPEND_LIMIT_REACHED. Every LiteLLM call is sent with the OpenAI user field set to dare-user-&lt;id&gt;, so the gateway can attribute spend per DARE user.

Document reprocessing and vision model selection

POST /api/files/{id}/reprocess/ accepts these camelCase JSON fields:

FieldBehavior
actionreparse processes the stored original; retry_images retries failed figure descriptions only.
processingModeRequired for reparse: basic or advanced. Omit for retry_images, which retains the existing mode.
modelIdentifierOptional vision model for this run. Used for Advanced reprocessing or failed-image retries without changing the upload preference.

The selected model must be available for vision in the authenticated user's active wallet. An unavailable selection returns 409 without queuing work; the worker also checks availability before making model calls. Requests without modelIdentifier retain existing model-resolution behavior for older clients.

Failed-image retries preserve successful descriptions. Full Advanced reprocessing uses the selected model for applicable scanned-page transcription and figure descriptions; scanned-page approval limits still apply. Cached outputs are scoped by user, image content, context, model, and prompt version, so changing models cannot reuse a different model's cached description.

Deploy the API and restart background workers before releasing a frontend that sends modelIdentifier. This is an additive request field and requires no database migration.

Improving Documentation

To add descriptions to endpoints, use @extend_schema decorators on custom @action methods:

from drf_spectacular.utils import extend_schema, OpenApiParameter

@extend_schema(
    summary="Export conversation as PDF",
    parameters=[OpenApiParameter(name="id", type=str, location="path")],
    responses={200: OpenApiTypes.BINARY},
)
@action(detail=True, methods=["get"], url_path="export-pdf")
def export_pdf(self, request, pk=None):
    ...

Document upload processing

POST /api/files/ accepts multipart files and matching names, plus optional processing_mode: basic or advanced (default). Multipart field names use underscores; the JSON response exposes the saved choice as processingMode. Invalid processing modes return HTTP 400 before any file is created.

  • Basic (text only): uses flat-text extraction and skips Docling layout and visual extraction. Scanned documents without embedded text need Advanced.
  • Advanced (Docling): preserves document structure, tables, and images for supported document formats and uses the existing visual enrichment workflow. Plain text and CSV go through Docling as well (read as Markdown and as a table), so Advanced always means "find the structure"; JSON has no Docling backend and keeps text extraction. Existing fallback diagnostics remain visible if Docling cannot parse a document. Standalone media handling is unchanged.

The mode is stored per file and reused when reprocessing. Existing files and callers that omit the option retain Advanced behavior. The mode cannot be changed with a file metadata PATCH; upload another copy to compare both approaches. Apply files.0024_file_processing_mode before deploying the new upload UI and restart API/worker processes. The stored parser_name remains parser provenance (basic, docling, or another parser), separate from the requested processing mode.

The authenticated GET /api/files/{id}/viewer-capabilities/ endpoint returns structure and map booleans. Both require a persisted structured parse from Docling or the notebook parser, including document elements. Basic uploads, text-only fallbacks, and files awaiting parsing expose neither view. The frontend uses these capabilities rather than inferring them from the requested mode. Migration 0025 normalizes historical legacy parser identifiers to basic in file metadata and the stored document model; processing history remains an audit record.

POST /api/files/bulk-tags/ takes { "fileIds": [...], "tagIds": [...] } and adds every tag to every file, leaving tags a file already has in place. Files must be the caller's own; tags must be the caller's or global. Any other id returns 404 and changes nothing. The response lists files with each file's id and full tags.

GET /api/files/content-search/?q= (3 to 200 characters) returns results for up to 50 of the caller's files whose indexed text contains q, each with fileId, the first matching snippet, and its page (nullable). It reads stored chunks, so files still processing, or with no extractable text, do not match. No migration is required.

Search index health

GET /api/files/{id}/index-health/ compares the chunks a file should have in its search index (its stored map rows) with the chunk identities the vector database holds right now, and returns state, expected, present, missingCount, missingChunks (first 100), unexpected, generation, backend, checkedAt, and error. States: verified (every expected chunk present), incomplete (some missing, duplicated, or unexpected), missing (none present), unavailable (the vector database could not be reached, which is deliberately distinct from confirmed loss), unverifiable (indexed before map rows existed, so only presence is known), not_indexed, and processing. Owner only. The check reads identities, not vectors or text, so it is cheap enough for the Map tab to run on open; the full content comparison happens once at publication (see docs/ingestion-verification.md).

Reprocess a stored document

POST /api/files/{id}/reprocess/ accepts JSON { "action": "reparse", "processingMode": "basic" | "advanced" } or { "action": "retry_images" }. It returns the updated file with HTTP 202 and a job ID. Only the owner can start work. Media, missing originals, and already-running work are rejected with 409; queue failures return 503 and restore the previous file status. Poll the existing job-status endpoint, then refresh file metadata when processing finishes.

Reparse retains the file ID and original bytes, honors the newly selected mode, and renews scanned-page approval if needed. Image retry uses the saved lossless Docling parse, retries only failed figure descriptions, and preserves completed figures and page transcriptions. Older incomplete document models must first be reprocessed with Advanced. failedImageCount in file metadata identifies retryable figure failures. Existing wallet selection, billing, caches, and processing traces apply; image retries also rebuild embeddings to make recovered descriptions searchable.

The active index stays searchable while replacement is built. New vectors use a separate generation; chunks and the generation pointer publish transactionally, then old vectors are retired. Empty or failed replacements retain the previous parse and index. Failed staged-vector cleanup is logged; unpublished generations are excluded from retrieval. Duplicate delivery of a completed job does not rerun it. A failed reprocess keeps its failure trace and reports that the previous document was retained. Scanned documents may pause for the existing OCR approval workflow.

The existing conversation tool-call activity and retrieval trace expose actual retrieval steps and sources. This feature adds no agentic whole-file-context tool.

On this page