Skip to content

REST API

The backend exposes a JSON REST API. FastAPI generates the full interactive reference (request and response schemas):

Outside production only

With APP_ENV=production (the default) these three routes are disabled. To browse them, run your local environment with APP_ENV=development.

Conventions

Topic Convention
Prefix Every route lives under /api/v1 (settings.API_V1_PREFIX). AI providers under /api/v1/ai.
Authentication Authorization: Bearer <JWT> obtained from POST /users/login (or after MFA / OAuth).
Language Accept-Language: es or en: error messages and AI content answer in that language.
Errors FastAPI HTTPException: body {"detail": ...}, where detail is a string or an object with a code (e.g. {"error": "response_truncated"}).
Validation 422 with Pydantic's detail when the body doesn't match the schema.
Limits 413 when the body exceeds MAX_REQUEST_BODY_BYTES; 429 when a rate limit is exceeded, with Retry-After on the routes that compute it.
Invalid session 401 when the token expired, is invalid or predates the last password change (pca claim).

Common codes: 200/201 success, 400 business rule, 401 no session, 403 not allowed (e.g. not an admin or plan limit), 404 doesn't exist or isn't yours.

Endpoints by group

Routes are relative to /api/v1. Public = no token; User = JWT; Admin = JWT of a user with the admin role.

Users and authentication (users/)

Method Route Access
GET /users/installation-status Public
GET /users/admin-count Public
POST /users/register Public
POST /users/login Public
POST /users/reset-password-request Public
POST /users/reset-password-confirm Public
GET · PUT · DELETE /users/me User
PUT /users/change-password User

MFA (mfa/)

Method Route Access
POST /mfa/verify, /mfa/switch-method, /mfa/resend-email-code During login (mfa_token in the body)
GET /mfa/status User
POST /mfa/setup-totp, /mfa/enable-totp User
POST /mfa/enable-email, /mfa/verify-email-activation User
POST /mfa/disable, /mfa/regenerate-recovery-codes User
PUT /mfa/default-method User
GET /mfa/admin/users, /mfa/admin/users/export Admin
POST /mfa/admin/users/{user_id}/reset-mfa Admin

OAuth (oauth/)

Method Route Access
GET /oauth/providers Public
GET /oauth/authorize/{provider} Public
POST /oauth/callback Public

Projects, folders and diagrams

Method Route Access
GET · POST /projects User
GET · PUT · DELETE /projects/{project_id} User
GET /projects/{project_id}/export, /projects/{project_id}/export/summary User
POST /projects/{project_id}/import User
POST /projects/{project_id}/folders User
GET · PUT · DELETE /folders/{folder_id} User
POST /projects/{project_id}/diagrams User
GET /diagrams/recent User
GET · PUT · DELETE /diagrams/{diagram_id} User
POST /diagrams/{diagram_id}/move, /diagrams/{diagram_id}/duplicate User
POST /diagrams/{diagram_id}/fix User
POST /diagrams/convert User
POST /diagrams/render Public (per-IP limit)

AI (ai_providers/, mounted at /ai)

Method Route Access
GET /ai/settings User
PUT /ai/settings/default-provider, /ai/settings/auto-fix User
POST /ai/providers User
PUT · DELETE /ai/providers/{provider_index} User
POST /ai/test-provider User (tests a key without saving it)
POST /ai/generate-diagram, /ai/improve-diagram User
POST /ai/generate-description, /ai/refine-description User

AI chat (chat_sessions/)

Method Route Access
GET · POST /chat-sessions User
GET /chat-sessions/stats/provider-usage User
GET · PUT · DELETE /chat-sessions/{session_id} Owner
PUT /chat-sessions/{session_id}/model Owner
POST /chat-sessions/{session_id}/messages Owner
POST /chat-sessions/{session_id}/messages/stream (SSE) Owner
DELETE /chat-sessions/{session_id}/messages/{message_id} Owner
PUT /chat-sessions/{session_id}/messages/{message_id}/status Owner

Each session belongs to the user who created it: another user's session answers 404, like a missing one, and the message endpoints check that the message belongs to the session in the route.

Prompt history (prompt_history/)

Method Route Access
GET · POST /prompt-history User
DELETE /prompt-history/{entry_id} User
Method Route Access
POST /shared-links User
GET /shared-links/diagram/{diagram_id} User
PUT · DELETE /shared-links/{link_id} User
GET /shared/{token}/info, /shared/{token}/diagram Public
POST /shared/{token}/verify Public (access code)

Plans and subscriptions (subscriptions/)

Method Route Access
GET /plans, /plans/{plan_id} Public
GET /subscriptions/me, /subscriptions/usage, /subscriptions/billing-history User
POST /subscriptions/checkout, /subscriptions/cancel, /subscriptions/update-payment-method User
GET /subscriptions/invoices/{invoice_id}/pdf-url User
GET · POST /admin/plans Admin
PUT · DELETE /admin/plans/{plan_id} Admin
POST /admin/plans/{plan_id}/prices Admin
DELETE /admin/plans/{plan_id}/prices/{currency} Admin
POST /webhooks/stripe Stripe signature (idempotent by event_id)

Integrations (integrations/)

Method Route Access
GET /admin/integrations/status Admin
GET · POST /admin/integrations/vendors Admin
PUT · DELETE /admin/integrations/vendors/{vendor_id} Admin
GET /admin/integrations/vendors/{vendor_id}/config (masked) Admin
POST /admin/integrations/vendors/{vendor_id}/test Admin
PUT /admin/integrations/vendors/{vendor_id}/set-default Admin

Health

Outside /api/v1:

Method Route Response
GET / Name, version, environment and status
GET /health {"status": "ok"}

Quick example

# 1. Sign in
TOKEN=$(curl -s -X POST http://localhost:5172/api/v1/users/login \
  -H 'Content-Type: application/json' \
  -d '{"email": "you@example.com", "password": "<your-password>"}' | jq -r .access_token)

# 2. List your projects
curl -s http://localhost:5172/api/v1/projects -H "Authorization: Bearer $TOKEN"

Note

When the account has MFA enabled, login doesn't return the final token but mfa_required and an mfa_token, which are exchanged for the access token with POST /mfa/verify.