Riferimento API
API REST del server Express (porta 3000, prefisso /api), con Swagger UI su /api-docs e spec OpenAPI su /api-docs/json generata dalle annotazioni @openapi JSDoc.
API REST del server Express (porta 3000, prefisso /api), con Swagger UI su /api-docs e spec OpenAPI su /api-docs/json generata dalle annotazioni @openapi JSDoc.
Autenticazione
| Metodo | Header | Uso |
|---|---|---|
| JWT | Authorization: Bearer <token> | Utenti interni (frontend, Tauri) |
| API key | X-Api-Key: sk-... | Widget embed, integrazioni programmatiche |
| Collector secret | X-Collector-Secret | Server↔collector (confronto constant-time) |
| Query token | ?token= | Accesso immagini OCR |
Middlewares (packages/server/src/middleware/): auth.ts, rbac.ts, license.ts, rateLimit.ts, widgetCors.ts.
Rate limit
| Limiter | Limite (prod/dev) | Scope |
|---|---|---|
| generale | 200 / 2000 req/min | IP |
| auth | 10 / 100 req/min | IP |
| probe | 10 / 100 req/min | IP |
| widget chat | 30 / 200 req/min (override per-widget) | widgetId |
| widget daily | 5 / 50 messaggi al giorno | widgetId + IP |
| widget session | 50 / 500 creazioni al giorno | IP |
| widget lead | 3 / 30 all'ora | IP |
Non esiste un rate limiter dedicato al chat LLM: l'agente ReAct impone i propri limiti internamente (concorrenza per utente, budget di token, wallclock timeout - agentBudgetService.ts); il limiter globale 200/min resta la rete di sicurezza. Le richieste con header X-Widget-Id saltano il limiter globale (a monte le throttla il widget service); i widget usano rateLimitPerMinute / sessionLimitPerDay come override per-widget.
Convenzioni risposta
- Successo: entità JSON o
{ ok: true }. - Errore:
{ error: string }(+detailsper errori validazione Zod). - License gating:
402 { error, feature, tier, limit?, current? }. - RBAC:
401(no auth),403(permessi insufficienti). - SSE:
event: <type>\ndata: <json>\n\n.
Auth - /api/auth (routes/auth.ts)
| Metodo | Path | Auth | RBAC | Note |
|---|---|---|---|---|
| POST | /auth/register | pubblico | - | Solo se ALLOW_REGISTRATION=true; body registerSchema |
| POST | /auth/admin-register | JWT | requireAdmin | body adminRegisterSchema |
| POST | /auth/login | pubblico | - | body loginSchema (safeParse → 400 se invalido) → { user, token } |
| GET | /auth/me | JWT | - | Profilo corrente |
| GET | /auth/users | JWT | requireAdmin | Lista utenti |
| POST | /auth/change-password | JWT | - | changePasswordSchema |
| POST | /auth/set-initial-password | JWT | - | Primo login (mustChangePassword) |
| POST | /auth/admin-reset-password | JWT | requireAdmin | Reset password utente |
Users - /api/users (routes/users.ts, authMiddleware)
| Metodo | Path | RBAC | Note |
|---|---|---|---|
| GET | /users | requireAdmin | Lista paginata |
| GET | /users/:id | self/admin | |
| PUT/PATCH | /users/:id | self/admin | updateUserSchema |
| DELETE | /users/:id | requireAdmin | |
| POST/DELETE | /users/:id/avatar | JWT | Upload/rimozione avatar (multipart) |
Roles - /api/roles (routes/roles.ts, authMiddleware)
| Metodo | Path | RBAC | Note |
|---|---|---|---|
| GET | /roles/me/menu-sections | JWT | Sezioni sidebar visibili |
| GET | /roles | requireAdmin | Lista ruoli |
| GET | /roles/:roleId | requireAdmin | Dettaglio (UUID) |
| POST | /roles | requireAdmin | Crea ruolo (createRoleSchema, isDefault=false) |
| PUT | /roles/:roleId | requireAdmin | Update (replace atomico permessi) |
| PUT | /roles/:roleId/menu-sections | requireAdmin | Sezioni menu |
| DELETE | /roles/:roleId | requireAdmin | |
| POST | /roles/assign | requireAdmin | Assegna ruolo a utente |
| POST | /roles/revoke | requireAdmin | Revoca ruolo |
Projects - /api/projects (routes/projects.ts, authMiddleware)
| Metodo | Path | RBAC | License | Note |
|---|---|---|---|---|
| GET | /projects | JWT | - | Lista paginata |
| POST | /projects | project:create | max_projects | Creazione |
| GET | /projects/:projectId | requireProjectAccess | - | |
| GET | /projects/:projectId/usage | requireProjectAccess | - | Statistiche uso |
| GET | /projects/:projectId/export | requireProjectAccess | - | Stream archivio |
| PUT | /projects/:projectId | requireProjectAccess | - | |
| DELETE | /projects/:projectId | requireProjectAccess | - | Soft delete |
| POST/DELETE | /projects/:projectId/access | requireProjectAccess | - | Gestione ProjectAccess |
Workspaces - /api/workspaces (routes/workspaces.ts, authMiddleware)
| Metodo | Path | RBAC | License | Note |
|---|---|---|---|---|
| GET | /workspaces | JWT | - | Lista |
| POST | /workspaces | workspace:create | max_workspaces | Creazione |
| GET/PUT/DELETE | /workspaces/:workspaceId | requireWorkspaceAccess | - | Soft delete |
| PUT | /workspaces/:workspaceId/restore | requireWorkspaceAccess | - | Ripristino soft-deleted |
| POST | /workspaces/:workspaceId/access | requireWorkspaceAccess | - | WorkspaceAccess |
| GET/POST/PUT/DELETE | /workspaces/:workspaceId/folders[/:folderId] | requireWorkspaceAccess | - | Cartelle chat |
| PUT | /workspaces/:workspaceId/folders/:folderId/restore | requireWorkspaceAccess | - |
Chat - montati su /api/workspaces (routes/chat*.ts, authMiddleware)
| Metodo | Path | RBAC | Note |
|---|---|---|---|
| POST | /workspaces/:id/chat | requireWorkspaceAccess | Non-streaming → { chat, message } |
| POST | /workspaces/:id/chat/stream | requireWorkspaceAccess | SSE |
| GET | /workspaces/:id/chats | requireWorkspaceAccess | Lista paginata (chatList.ts) |
| GET | /workspaces/:id/chats/:chatId/messages | requireWorkspaceAccess | Messaggi paginati |
| PUT | /workspaces/:id/chats/:chatId | requireWorkspaceAccess | Rename (chatCrud.ts) |
| PATCH | /workspaces/:id/chats/:chatId/model | requireWorkspaceAccess | Modello per-chat { providerId?, model? } |
| PATCH | /workspaces/:id/chats/:chatId/folder | requireWorkspaceAccess | Sposta in cartella |
| DELETE | /workspaces/:id/chats/:chatId | requireWorkspaceAccess | |
| PUT | /workspaces/:id/chats/:chatId/move | requireWorkspaceAccess | Riordina |
| POST/DELETE | /workspaces/:id/chats/:chatId/pin | requireWorkspaceAccess | Pin chat |
| DELETE/PUT | /workspaces/:id/chats/:chatId/messages/:messageId | requireWorkspaceAccess | Delete/edit messaggio |
| GET | /workspaces/:id/agent-config | requireWorkspaceAccess | Config agente workspace (chatAgentConfig.ts) |
| PUT | /workspaces/:id/agent-config | requireWorkspaceAccess | |
| GET | /workspaces/:id/chats/export | requireWorkspaceAccess | Export (json/md/pdf) (chatExport.ts) |
| GET | /workspaces/:id/chats/:chatId/export | requireWorkspaceAccess | |
| POST | /workspaces/:id/chats/import/preview | requireWorkspaceAccess | Preview import (chatImport.ts) |
| POST | /workspaces/:id/chats/import/confirm | requireWorkspaceAccess | Conferma import |
| GET | /workspaces/:id/chats/:chatId/tokens | requireWorkspaceAccess | Token usati (chatTokens.ts) |
| GET | /workspaces/:id/tokens/today | requireWorkspaceAccess |
SSE - /workspaces/:id/chat/stream
Eventi: token, status, citations ({ sources }), done ({ chatId, messageId, modelUsed, providerUsed, mcpSources }), error ({ error }), oltre plan e wiki_edit.
Connectors (Enterprise) - /api/connectors (routes/connectors.ts, connectorOAuthCallback.ts) - F-CONN-2
Gating: authMiddleware → tenantContextMiddleware → requireAdmin → requireFeature("connectors_enabled") (Community: fail-closed, F-CONN-1); per-route connector:manage/connector:view. I webhook di piattaforma girano su una router SEPARATA PUBLIBICA (connectorsWebhookRouter, montata sullo stesso prefisso - NO RBAC, firma/secret per piattaforma) e il callback OAuth su connectorOAuthCallback.ts.
| Metodo | Path | Permesso | Note |
|---|---|---|---|
| POST | /connectors | connector:manage | Crea il connettore (nome/binding archivio/welcome-fallback/locale fallback/limiti) |
| GET | /connectors | connector:view | Lista |
| GET | /connectors/:id | connector:view | Dettaglio |
| PUT | /connectors/:id | connector:manage | EDIT (v0.28.1, F-CONN-2): nome/binding/messaggi/limiti modificabili - piattaforma/token immutabili; emette chat_connector.updated (audit) |
| DELETE | /connectors/:id | connector:manage | Elimina |
| GET | /connectors/oauth/providers | connector:manage | Provider OAuth disponibili |
Vedi 13 - Connectors.
Documents & Uploads (routes/documents.ts, routes/uploads.ts)
| Metodo | Path | RBAC | Note |
|---|---|---|---|
| GET | /documents | JWT | Lista |
| GET | /documents/:id | JWT | Dettaglio |
| GET | /documents/:id/text | JWT | Testo estratto |
| POST | /documents/upload | document:write | Multipart upload |
| PUT | /documents/:id/status | (pre-middleware) | Callback collector |
| DELETE | /documents/:id | document:delete | Soft delete |
| POST | /uploads | document:write | Staging draft (uploads.ts) |
| POST | /uploads/:id/assign | document:write | Assegna draft a workspace |
| GET | /uploads/pending | document:write | Drafts pending |
| DELETE/PATCH | /uploads/:id | document:write |
API Keys - /api/api-keys (routes/apiKeys.ts, authMiddleware)
GET lista le proprie chiavi, POST ne crea una nuova (la raw key sk-... è mostrata una sola volta, DELETE /:keyId revoca).
Dalla v0.20.1 le API key sono HMAC-SHA256: la chiave sk- non è più hashata con bcrypt ma con un digest HMAC-SHA256 dedicato (API_KEY_HMAC_SECRET, env var dedicata separata da JWT/encryption key rotation) e la verifica è una lookup indicizzata O(1) su api_keys.key_hash (unique index Postgres), non un confronto bcrypt-loop. Breaking change v0.20.1: operatori devono ri-emettere le chiavi widget/collector (vedi docs/API_KEY_MIGRATION.md). Dalla v0.22.0 i confronti dei segreti (X-Api-Key cache-bust, X-Collector-Secret) sono timing-safe (crypto.timingSafeEqual con length guard). Una chiave mancante/invalida → 401; una misconfigurazione HMAC lato server → 500 (fail-loud).
Agent Skills - /api/agent + /api/skills (routes/skills.ts, authMiddleware)
GET /api/agent/skills → skill builtin (rag_search, workspace_memory, document_temp_process).
Skill custom (v0.28.1, F-SKILL-1): CRUD GET/POST/PUT/DELETE /api/skills[...] con permessi skill:read/skill:create/skill:write/skill:delete; la create è gateata dal limite licenza max_skills (Community 3, Enterprise Infinity). Scope personal/global/workspace con arbitraggio server-side. POST /api/skills/:id/test → preview del prompt compilato (no chiamata LLM, no masking DLP). Vedi 15 - Custom Skills.
MCP Connections - /api/mcp-connections (routes/mcp.ts, authMiddleware + requireAdmin)
GET lista, GET /statuses (runtime live), POST crea, PUT /:id (auto-disconnect/reconnect se enabled), DELETE /:id, POST /:id/toggle, POST /:id/test (10s timeout, toolCount).
MCP Pins - /api/chats/:chatId/pins (routes/mcpPins.ts)
GET, POST (mcpPinCreateSchema), DELETE /:pinId.
MCP Server inbound (per IDE) - agent/mcpServer.ts
GET /api/mcp/sse (SSE transport), POST /api/mcp/message (JSON-RPC).
Marketplace - /api/mcp-marketplace (routes/marketplace.ts, authMiddleware + requireAdmin)
GET lista (query ?search, ?category, ?workspaceId per isInstalled), GET /:entryId, POST crea entry, POST /:entryId/install, POST /:entryId/uninstall. Vedi 07 - MCP Marketplace.
Providers / Models - /api/providers (routes/providers.ts, authMiddleware)
GET /models/available (selettore frontend), GET lista, GET/:id, POST crea, PUT/:id, DELETE/:id, PUT /:id/set-default, GET /:id/models, POST /:id/models/refresh (discovery), POST /:providerId/models/pull, PUT/DELETE /:providerId/models/:modelId, PUT /:providerId/models/:modelId/set-default.
Provider Presets - /api/provider-presets (routes/providerPresets.ts)
GET lista, GET /:presetId, POST /:presetId/install.
Widget (admin) - /api/widgets (routes/widgets.ts, authMiddleware + requireAdmin)
GET lista, POST (license widget_enabled + max_widgets), GET/PUT/DELETE /:id, PUT /:id/workspaces (whitelist), GET /:id/workspaces, GET /:id/leads (paginati), GET /:id/leads/export (CSV, license lead_export), GET /:id/leads/:leadId. Analytics: GET /analytics/daily, /analytics/topics, /analytics/summary.
Internal Widget (embed) - /api/internal/widget (routes/internalWidget.ts, apiKeyMiddleware + widgetCors)
Autenticazione API key (X-Api-Key). POST /search (RAG, IDOR-safe via widgetId), POST /lead, GET /:id/config, GET /session/:token, POST /session, PATCH /session/:token/increment, PATCH /session/:token/chat/archive. Vedi 06 - Widget Integration.
Backup (routes/backups.ts, backupDestinations.ts, backupJobs.ts, restore.ts)
| Gruppo | Path | Permessi | License |
|---|---|---|---|
| Logs | /api/system/backups | backup:log:read | - |
| Destinations | /api/backup-destinations | backup:destination:read/write | max_backup_destinations |
| Jobs | /api/backup-jobs | backup:job:read/write | - |
| Restore | /api/backups, /api/backups/restore/:logId[/dry-run] | backup:log:read / backup:restore:write | - |
POST /backup-jobs/:id/run (trigger manuale), POST /backup-destinations/:id/test.
Webhooks - /api/webhooks (routes/webhooks.ts, authMiddleware + requireAdmin + requireFeature("webhooks"))
CRUD + POST /:id/test. HMAC-SHA256, retry exponential backoff (5 tentativi), auto-disable dopo 5 fallimenti.
Push - /api/system/push (routes/push.ts)
GET /vapid-key (pubblico key), POST/DELETE /subscribe (license push_notifications), POST /test (admin).
License - /api/license (routes/license.ts)
GET /license/info (pubblico) → { license, features }.
Slot licenza istanza (v0.28.1, F-LIC-1): GET /api/license/instance (Admin, metadata-only), PUT /api/license/instance ({ licenseKey } - paste + verify + persist + apply senza restart; i rifiuti sono 400 { error, reason } con reason chiuso invalid/expired/plugin_bound/community_tier), DELETE /api/license/instance (ripulisce la paste - l'istanza torna allo stato next-boot). Vedi 08 - Administration.
SSO - /api/sso (routes/sso.ts, authMiddleware + requireAdmin + requireFeature("sso_enabled"))
GET /config, PUT /config, POST /test.
Templates - /api/templates (routes/templates.ts, authMiddleware)
GET lista, GET /:id, POST crea, PUT/DELETE /:id (requireAdmin). Interpolazione {{var}}.
Settings - /api/system/settings (routes/settings.ts, authMiddleware + requireAdmin)
GET /embedding-config, GET /vector-db-config, GET settings, PUT settings ({ updated, rejected }), POST/DELETE /branding/icon (license white_label). Vedi 03 - Configuration.
System - /api/system (routes/system.ts)
GET /is-initialized (pubblico), POST /initialize (setup wizard, solo se non inizializzato), POST /reset-db (admin), POST /reindex-documents (admin, reindex RAG), POST /ocr/prewarm (admin).
Quota & Costi - /api/quota + i surface dei costi (routes/quota.ts, Phases 203/207/209) - F-QUOTA-1
Quota token (Phase 207): per-utente/gruppo, reset orario (la sweep quotaResetJob).
| Metodo | Path | Permesso | Note |
|---|---|---|---|
| GET | /quota/me | JWT | Stato quota proprio (uso finestra vs limite) |
| GET | /quota/rollup | agency:users:manage | Rollup degli utenti gestiti |
| GET | /quota/:userId | agency:users:manage | Stato quota utente |
| PUT | /quota/:userId | requireAdmin | Imposta/modifica le quote token |
| POST | /quota/:userId/reset | agency:users:manage | Reset manuale (la sweep oraria resetta comunque) |
Costi (Phase 203, contabilità per-valuta server-side):
| Metodo | Path | Permesso |
|---|---|---|
| GET | /workspaces/:id/chats/:chatId/cost | requireWorkspaceAccess |
| GET | /workspaces/:id/cost/today | requireWorkspaceAccess |
| GET | /system/analytics/cost?days=N | requireAdmin |
| GET | /system/analytics/cost-by-model | requireAdmin |
Per-user model policy & BYOK (Phase 209): GET /me/provider-keys (key proprie cifrate a riposo), PUT/DELETE /me/provider-keys/:providerId, PUT/DELETE /users/:userId/models/:providerId/:modelName/pricing, PUT /users/:userId/cloud-model-mode. Vedi 17 - Quotas & Costs.
Audit / Event Log - /api/event-logs (routes/eventLogs.ts, authMiddleware + requireAdmin + requireFeature("audit_log_immutable"))
GET con filtri (type/user/workspace/date/action), paginazione cursor.
Analytics - /api/system/analytics (routes/analytics.ts, authMiddleware + requireAdmin)
GET /tokens, /models, /top-users.
Archives - /api/archives (routes/archives.ts + archivePages.ts, archiveConfig.ts, archiveSearch.ts, archiveGraph.ts, archiveExport.ts, archiveIndex.ts, archiveImport.ts, archiveSchemaTemplates.ts)
GET lista, POST (archive:write), GET/PUT/DELETE /:archiveId (archive:delete per delete), POST /from-template, POST /:archiveId/reindex. Pages: GET/POST /:archiveId/pages, GET/PUT/DELETE /:archiveId/pages/:slug. Config, search (hybrid RRF), graph, export, index, import (copy-from-doc, import/:jobId, import/:jobId/callback), schema templates.
OCR - /api/ocr + /api/archives/:id/jobs (routes/ocr.ts, authMiddleware)
Catalogo OCR su /api/ocr. Jobs su archivi: GET /archives/:id/jobs, GET /:jobId, POST /:jobId/approve, POST /:jobId/reject, DELETE /:jobId, GET /:jobId/pages/:pageNumber/image (query token auth).
Synthesis - /api/synthesis (routes/synthesis.ts, authMiddleware)
GET /status, GET /pending/count, POST /trigger (archive:write + feature limit), GET /:runId, POST /:runId/approve, POST /:runId/reject, DELETE /:runId, PATCH /:runId/rename.
Wiki - /api/wiki-write, /api/wikilinks, /api/wiki-edits (routes/wikiChat.ts, wikilinks.ts)
POST /wiki-write/preview, POST /wiki-write/:runId/approve|reject|undo, GET /wiki-write/history/:archiveId, POST /wiki-write/distill. Links: POST /wikilinks/resolve, GET /wikilinks/:archiveId[/:pageSlug], maintenance GET/POST /wikilinks/maintenance/:archiveId[/merge].
Chat retention - /api/system/chat-retention (routes/chatRetention.ts)
PUT (system:write, confirmDataLoss: true, audited). Vedi 03 - Configuration.
Health - / (routes/health.ts)
GET / (pubblico, { uptime }), GET /api/health (pubblico, { status, checks: { database, collector, disk } }), GET /api/health/rag.
Widget Service - porta 3211 (packages/widget)
GET /health, GET /widget/:id.js (loader), GET /widget/:id (HTML iframe), GET /api/config/:id (branding+trigger+lead), POST /api/config/:id/cache-bust, POST /api/sessions (sessione anonima), POST /api/chat/:id/stream (SSE, x-session-token), POST /api/lead/:id (lead capture).
Collector Service - porta 3210 (packages/collector)
GET /api/health, GET /api/ingest/chunks/:documentId, POST /api/ingest (X-Collector-Secret, multipart), POST /api/ingest/query (vector search), DELETE /api/ingest/:documentId, POST /api/ingest/reembed, POST /api/ingest/youtube, POST /api/ingest/wiki-pages, DELETE /api/ingest/wiki-pages/:pageId, POST /api/ingest/archive-page.
Provenienza v0.28.1
| Affermazione | Fonte |
|---|---|
| I gruppi Connectors + l'EDIT arm + l'OAuth callback + la webhook router pubblica | packages/server/src/routes/connectors.ts (inventory row-time, probe 35-02) + CHANGELOG.md v0.28.1 (Added) - F-CONN-2 |
| Quota/costi/BYOK/model-policy (Phases 203/207/209) | docs/API.md:377-405 (row-time) - F-QUOTA-1 |
| Skill custom CRUD + test preview | docs/API.md:358-360 + docs/CUSTOM_SKILLS.md - F-SKILL-1 |
Route slot istanza (GET/PUT/DELETE /api/license/instance) | docs/API.md:157-159 + docs/ADMIN.md - F-LIC-1 |
Riferimento operativo - Simmetric Chat v0.28.1 (docs aggiornate 2026-10-02, census SHA `aca5b8ff`).
Cross-link
- Auth/RBAC dettaglio: 08 - Administration
- Widget embed how-to: 06 - Widget Integration
- MCP lifecycle: 07 - MCP Marketplace