|
@@ -0,0 +1,126 @@
|
|
|
|
|
+# Referência de API
|
|
|
|
|
+
|
|
|
|
|
+Base URL: `http://localhost:3001`
|
|
|
|
|
+
|
|
|
|
|
+**Níveis de auth:**
|
|
|
|
|
+- **Pública** — sem token
|
|
|
|
|
+- **Usuário** — requer JWT válido (qualquer nível)
|
|
|
|
|
+- **Admin** — requer JWT com `nivel = "3"`
|
|
|
|
|
+
|
|
|
|
|
+> **Formato de resposta:** os domínios **Auth** e **Usuários** envolvem a resposta em um wrapper `{ status, msg, ... }`. Os demais retornam o objeto direto (ex: `{ items }`, `{ ok: true }`).
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Health
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Descrição |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| GET | `/health` | Pública | Status dos serviços (API, banco, Qdrant, Ollama) |
|
|
|
|
|
+
|
|
|
|
|
+**Resposta:**
|
|
|
|
|
+```json
|
|
|
|
|
+{ "ok": true, "checks": { "api": true, "db": true, "qdrant": true, "ollama": true } }
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Auth (`/api/auth`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| POST | `/api/auth/login` | Pública | `{ login, senha }` | `200 { status, msg, usuario, accessToken?, refreshToken? }` |
|
|
|
|
|
+| POST | `/api/auth/logout` | Pública | `{ refreshToken }` | `200 { status, msg }` |
|
|
|
|
|
+| POST | `/api/auth/refresh` | Pública | `{ refreshToken }` | `200 { status, accessToken }` |
|
|
|
|
|
+
|
|
|
|
|
+- `login` aceita e-mail ou login; os campos também são aceitos em PascalCase (`Login`/`Senha`).
|
|
|
|
|
+- `accessToken`/`refreshToken` só são emitidos quando `JWT_SECRET` está configurado.
|
|
|
|
|
+- O login pode retornar `429` após 5 tentativas incorretas (bloqueio de 15 minutos).
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Chat (`/api/chat`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| POST | `/api/chat` | Usuário | `{ message, conversationId?, sessionId?, model?, options? }` | `{ answer, sources }` |
|
|
|
|
|
+| POST | `/api/chat/stream` | Usuário | `{ message, conversationId? }` | Stream SSE |
|
|
|
|
|
+
|
|
|
|
|
+- O campo de texto é **`message`** (não `content`).
|
|
|
|
|
+- `options` aceita `{ temperature?, top_p? }`.
|
|
|
|
|
+- **Stream SSE:** cada linha tem o formato `data: { "type": "delta" | "sources" | "error", ... }`, terminada por `data: [DONE]`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Conversas (`/api/conversations`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body / Params | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| GET | `/api/conversations` | Usuário | `?limit&offset` | `{ items }` |
|
|
|
|
|
+| POST | `/api/conversations` | Usuário | `{ title? }` | `{ id, title }` |
|
|
|
|
|
+| GET | `/api/conversations/:id/messages` | Usuário | — | `{ items }` ou `404 { error: "not_found" }` |
|
|
|
|
|
+| PATCH | `/api/conversations/:id` | Usuário | `{ title }` | `{ ok: true }` |
|
|
|
|
|
+| DELETE | `/api/conversations/:id` | Usuário | — | `200 { ok: true }` |
|
|
|
|
|
+| GET | `/api/conversations/:id/export` | Usuário | — | `{ markdown }` ou `404` |
|
|
|
|
|
+
|
|
|
|
|
+- Cada item de `GET /api/conversations` traz `Id`, `Title`, `CreatedAt`, `UpdatedAt`, `MessageCount`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Documentos (`/api/documents`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body / Params | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| GET | `/api/documents` | Usuário | `?limit&offset` | `{ items, nextOffset }` |
|
|
|
|
|
+| DELETE | `/api/documents/source/:source` | Admin | — | `{ ok: true }` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Ingest (`/api/ingest`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| POST | `/api/ingest` | Admin | `{ documents: [{ text, source?, id?, metadata? }] }` | `{ upserted }` |
|
|
|
|
|
+| POST | `/api/ingest/file` | Admin | `multipart/form-data` com campo `file` (+ `source?`), máx 25 MB | `{ upserted, documents, extractedChars }` |
|
|
|
|
|
+| POST | `/api/ingest/url` | Admin | `{ url, source? }` | `{ upserted, source, extractedChars }` |
|
|
|
|
|
+
|
|
|
|
|
+- Em `POST /api/ingest`, o campo raiz é o array **`documents`**, e o texto de cada item é **`text`**.
|
|
|
|
|
+- Em `POST /api/ingest/url`, a `url` deve começar com `https://`.
|
|
|
|
|
+- **Formatos de arquivo suportados:** TXT, PDF e DOCX (processados via Mammoth/pdf-parse).
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Busca (`/api/search`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| POST | `/api/search` | Usuário | `{ query, topK? }` | `{ results }` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Usuários (`/api/users`)
|
|
|
|
|
+
|
|
|
|
|
+| Método | Rota | Auth | Body | Retorno |
|
|
|
|
|
+|---|---|---|---|---|
|
|
|
|
|
+| GET | `/api/users` | Admin | — | `{ status, items }` |
|
|
|
|
|
+| POST | `/api/users` | Admin | `{ Nome, Login, Email, Senha, Nivel, Setor }` | `201 { status, usuario }` |
|
|
|
|
|
+| PUT | `/api/users/:id` | Admin | `{ Nome?, Email?, Nivel?, Setor? }` | `{ status, usuario }` |
|
|
|
|
|
+| PATCH | `/api/users/:id/status` | Admin | — | `{ status, novoStatus }` |
|
|
|
|
|
+| PATCH | `/api/users/:id/senha` | Próprio ou Admin | `{ senhaAtual, senhaNova }` | `200 { status, msg }` |
|
|
|
|
|
+
|
|
|
|
|
+- Campos de body em **PascalCase**. Em `POST`, todos são obrigatórios; `Nivel` aceita `"1"`, `"2"` ou `"3"`.
|
|
|
|
|
+- `PUT` atualiza parcialmente e **não** aceita alterar `Login`. Exige ao menos um campo.
|
|
|
|
|
+- `PATCH /:id/senha` pode ser chamado pelo próprio usuário ou por um admin. Pode retornar `409` (login já cadastrado) no `POST`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Erros comuns
|
|
|
|
|
+
|
|
|
|
|
+| Status | Significado |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| `400` | Body/params inválidos (falha de validação zod) |
|
|
|
|
|
+| `401` | Token ausente, inválido ou expirado; credenciais incorretas |
|
|
|
|
|
+| `403` | Autenticado, mas sem permissão (nível insuficiente) |
|
|
|
|
|
+| `404` | Recurso não encontrado |
|
|
|
|
|
+| `409` | Conflito (ex: login já cadastrado) |
|
|
|
|
|
+| `429` | Excesso de requisições / login bloqueado por tentativas |
|
|
|
|
|
+| `500` | Erro interno do servidor |
|