| # **Backend API Documentation – IE Research Platform** | |
| ## **Base URL** | |
| - Development: `http://localhost:3000/api` (or your configured proxy) | |
| - Production: `https://yourdomain.com/api` | |
| All endpoints (unless stated otherwise) return JSON. Authentication uses **JWT** (Bearer token) – include `Authorization: Bearer <token>` header for protected routes. | |
| --- | |
| ## **1. Authentication & User Management** | |
| ### **POST /register** | |
| Register a new user. | |
| - **Body** (JSON): | |
| ```json | |
| { | |
| "username": "string (3-30 chars, alphanumeric + underscore)", | |
| "password": "string (min 6 chars)", | |
| "email": "string (optional, valid email)" | |
| } | |
| ``` | |
| - **Response** (201): `{ "id": number, "username": string, "email": string, "createdAt": "ISO" }` | |
| - **Errors**: 400 (validation), 409 (username taken) | |
| ### **POST /login** | |
| Authenticate user and get JWT. | |
| - **Body**: `{ "username": string, "password": string }` | |
| - **Response** (200): `{ "token": "JWT", "user": { ...user object } }` | |
| ### **GET /users/me** | |
| Get current authenticated user profile. | |
| - **Auth**: Required | |
| - **Response**: `UserProfile` object (id, username, email, fullName, bio, avatarUrl, createdAt, etc.) | |
| ### **PUT /users/me** | |
| Update profile fields. | |
| - **Body**: `{ "fullName": string, "bio": string, "affiliation": string, "orcid": string, "googleScholar": string, "isPrivate": boolean, "securityQuestion": string, "securityAnswer": string }` | |
| - **Response**: updated `UserProfile` | |
| ### **POST /users/me/avatar** | |
| Upload base64 avatar. | |
| - **Body**: `{ "avatar": "data:image/png;base64,..." }` | |
| - **Response**: `{ "avatarUrl": string }` | |
| ### **PUT /users/me/password** | |
| Change password. | |
| - **Body**: `{ "oldPassword": string, "newPassword": string }` | |
| ### **GET /users/{username}** | |
| View public profile (or own if same user, respects privacy). | |
| - **Response**: `UserProfile` (public fields) | |
| ### **POST /users/{username}/follow** / **DELETE /users/{username}/follow** | |
| Follow/unfollow a user. | |
| - **Auth**: Required | |
| - **Response**: 204 No Content | |
| ### **GET /users/{username}/following** | |
| List users that the given user follows. | |
| - **Response**: `{ "following": [{ username, fullName, avatarUrl }] }` | |
| ### **GET /search/users?q=...** | |
| Search users by username/fullName. | |
| - **Response**: array of `{ id, username, fullName, avatarUrl }` | |
| --- | |
| ## **2. Articles & Content** | |
| ### **POST /articles** | |
| Create a new article (published or draft). | |
| - **Auth**: Required (author = current user) | |
| - **Body**: | |
| ```json | |
| { | |
| "title": "string (required)", | |
| "abstract": "string (required)", | |
| "body": "HTML content", | |
| "tags": ["string"], | |
| "status": "published | draft", | |
| "relatedArticleIds": [number] | |
| } | |
| ``` | |
| - **Response**: `Article` object with `id`, `createdAt`, `updatedAt`, `slug`, etc. | |
| ### **GET /articles/{id}** | |
| Get a single article (public if published, or author only if draft). | |
| - **Response**: full `Article` object (title, abstract, body, author, likesCount, commentsCount, views, tags, status, etc.) | |
| ### **GET /articles/search** | |
| Search articles with filters. | |
| - **Query params**: `q` (title/abstract), `author`, `tag`, `dateFrom`, `dateTo`, `status`, `page`, `limit` | |
| - **Response**: `{ result: Article[], total: number }` | |
| ### **GET /users/me/articles** (or `/articles?author={username}`) | |
| Get articles by a specific author. Used in dashboard. | |
| - **Response**: array of `Article` | |
| ### **DELETE /articles/{id}** | |
| Delete article (author only). | |
| - **Response**: 204 | |
| ### **PUT /articles/{id}** | |
| Update article (author only). Body same as creation. | |
| ### **POST /articles/{id}/like** / **DELETE /articles/{id}/like** | |
| Like/unlike an article. | |
| ### **GET /articles/{id}/analytics** | |
| Get analytics for an article (views, likes, comments over time). | |
| - **Auth**: Required for own articles. | |
| - **Query**: `range=7d|30d|90d|1y|all` | |
| - **Response**: `PaperAnalytics` object. | |
| --- | |
| ## **3. Messaging & Chat** | |
| ### **Private Conversations** | |
| **GET /conversations** | |
| List all private conversations for the current user. | |
| - **Response**: array of `{ with: string, lastMessage: string, lastId: number, unread: number, updatedAt: string }` | |
| **GET /conversations/{username}/messages** | |
| Get messages with a specific user (paginated). | |
| - **Query**: `before` (message id), `limit` (default 20) | |
| - **Response**: array of `Message` objects (id, body, sentAt, from, status, replyToId, attachments, etc.) | |
| **POST /conversations/{username}/messages** | |
| Send a message (plain text or with attachments). | |
| - **Body**: | |
| ```json | |
| { | |
| "body": "string", | |
| "messageType": "text|image|file|paper|note|sticker|voice|video|audio|poll|rich_text", | |
| "replyToId": number (optional), | |
| "attachments": [ { "name": "string", "url": "string", "type": "string" } ], | |
| "ciphertext": "string" (if encrypted) | |
| } | |
| ``` | |
| - Supports multipart/form-data when file attachments are uploaded. | |
| ### **Groups** | |
| **GET /groups** | |
| List groups the user is a member of. | |
| - **Response**: array of `Group` objects (id, name, memberCount, lastMessage, unread, isAdmin) | |
| **POST /groups** | |
| Create a new group. | |
| - **Body**: `{ "name": string, "members": [userId] }` | |
| - **Response**: `Group` | |
| **GET /groups/{groupId}/messages** | |
| Get group messages (paginated same as private). | |
| - **Query**: `before`, `limit` | |
| **POST /groups/{groupId}/messages** | |
| Send a message to a group. | |
| **GET /groups/{groupId}/members** | |
| List group members. | |
| **POST /groups/{groupId}/members** | |
| Add a member (admin only). Body `{ "members": [userId] }` | |
| **DELETE /groups/{groupId}/members/{userId}** | |
| Remove member. | |
| **POST /groups/{groupId}/admins/{userId}** | |
| Make user an admin. | |
| **DELETE /groups/{groupId}** | |
| Delete group (admin only). | |
| **POST /groups/{groupId}/pin/{messageId}** / **GET /groups/{groupId}/pinned** | |
| Pin/unpin messages. | |
| ### **General Messages** | |
| **GET /messages/{messageId}/edits** | |
| Get edit history of a message. | |
| - **Response**: array of `{ id, messageId, body, editedAt }` | |
| **POST /messages/{messageId}/reactions** | |
| Add or remove a reaction (emoji). | |
| - **Body**: `{ "emoji": string }` | |
| **PUT /messages/{messageId}** | |
| Edit a message (author only). Body `{ "body": string }` | |
| **DELETE /messages/{messageId}** | |
| Soft delete (replace body with "[deleted]"). | |
| **POST /messages/forward** | |
| Forward one or multiple messages. | |
| - **Body**: `{ "messageIds": [number], "targetChatId": string }` (private username or `g-{groupId}`) | |
| **POST /messages/{messageId}/thread** | |
| Get thread replies (if using message threading). Body `{ "parentId": number }` | |
| ### **Secret Chat (E2EE)** | |
| **POST /secret-chat/init** | |
| Initiate a secret chat (E2EE session). Uses Signal protocol. | |
| ### **Typing indicators, read receipts** | |
| Handled via WebSocket (see WebSocket section). | |
| --- | |
| ## **4. Notifications & Smart Notifications** | |
| ### **GET /notifications** | |
| Get notifications for the current user. | |
| - **Query**: `limit`, `offset` | |
| - **Response**: array of `Notification` (id, type, title, body, read, createdAt, link) | |
| ### **POST /notifications/{id}/read** | |
| Mark single notification as read. | |
| ### **POST /notifications/read-all** | |
| Mark all as read. | |
| ### **WebSocket – real‑time notifications** | |
| - Topic: `/user/queue/notifications` | |
| - Message type: `{ "type": "new_notification", "notification": {...} }` | |
| ### **Smart Notification Settings** | |
| - **GET /users/me/notification-settings** – fetch current settings | |
| - **POST /users/me/notification-settings** – update (body matches `NotificationSettings` interface) | |
| --- | |
| ## **5. Collaboration & Real‑time Editing (Yjs)** | |
| WebSocket signaling for collaborative editor: `ws://localhost:9093` (or configurable). | |
| Uses `y-websocket` protocol. Room names are document IDs. | |
| **API endpoints for document management:** | |
| - **GET /documents/{docId}/references** – get references list for a document | |
| - **POST /documents/{docId}/references** – add a reference (DOI, BibTeX, etc.) | |
| - **PUT /documents/{docId}/references/{refId}** – update | |
| - **DELETE /documents/{docId}/references/{refId}** | |
| **Version history** (if implemented): | |
| - **GET /documents/{docId}/versions** – list versions | |
| - **POST /documents/{docId}/versions** – create snapshot | |
| - **GET /documents/{docId}/versions/{versionId}** – get content | |
| --- | |
| ## **6. Recommendations & Discovery** | |
| ### **GET /recommendations/feed** | |
| Personalized article recommendations for logged‑in user. | |
| - **Query**: `limit=15` | |
| - **Response**: array of `RecommendedArticle` | |
| ### **GET /recommendations/trending** | |
| Global trending articles for non‑authenticated. | |
| - **Query**: `limit=15` | |
| - **Response**: same format. | |
| ### **GET /recommendations/users** | |
| Suggested users to follow. | |
| - **Query**: `limit=5` | |
| - **Response**: array of `SuggestedUser` | |
| ### **GET /discovery/recommendations** | |
| General discovery feed (papers, grants, etc.) | |
| ### **POST /discovery/digest** | |
| Toggle daily digest email. Body `{ "enabled": boolean }` | |
| ### **GET /discovery/summarize/{paperId}** | |
| Get AI‑generated summary of a paper. | |
| - **Query**: `level=tldr|short|detailed` | |
| - **Response**: `PaperSummary` | |
| --- | |
| ## **7. Gap Analysis & Knowledge Graph** | |
| - **GET /gap-analysis/nodes** – fetch graph nodes (papers, concepts, gaps) | |
| - **GET /gap-analysis/edges** – fetch relationships | |
| - **POST /gap-analysis/analyze** – run gap analysis on a topic (AI) | |
| --- | |
| ## **8. Grant Assistant** | |
| - **GET /grants/deadlines** – upcoming deadlines | |
| - **GET /grants/templates** – proposal templates | |
| - **POST /grants/generate** – generate a draft proposal from RFP | |
| - **POST /grants/analyze** – analyse RFP text | |
| --- | |
| ## **9. Peer Review** | |
| - **GET /peer-review/submissions** – list open submissions (anonymised) | |
| - **GET /peer-review/my-reviews** – reviews assigned to me | |
| - **GET /peer-review/my-credentials** – reviewer credentials (ORCID, expertise) | |
| - **POST /peer-review/submit** – submit a paper for review (anonymous) | |
| - **POST /peer-review/submissions/{id}/claim** – claim a review | |
| - **POST /peer-review/submissions/{id}/review** – submit review (scores, comments) | |
| --- | |
| ## **10. Lab Inventory** | |
| - **GET /inventory/chemicals** – list chemicals (with filtering) | |
| - **POST /inventory/chemicals** – add a chemical | |
| - **PUT /inventory/chemicals/{id}** – update | |
| - **DELETE /inventory/chemicals/{id}** | |
| - **GET /inventory/chemicals/{id}/incompatibilities** – list incompatible chemicals | |
| - **GET /inventory/locations** – list all location names | |
| - **POST /inventory/scan** – process barcode scan | |
| --- | |
| ## **11. RAG Assistant (Research Assistant)** | |
| - **POST /ai/rag-chat** – chat with RAG (uses indexed documents) | |
| - Body: `{ "messages": [...], "sources": [...] }` – actual backend expects `messages` array and optionally `sources` metadata. | |
| - Response: `{ "reply": "string", "sources": [...] }` | |
| - **POST /ai/chat** – generic AI chat (LLM proxy) | |
| - Body: `{ "provider": "ollama|openai|java-backend", "model": "string", "messages": [...] }` | |
| - **POST /ai/command-palette/predict** – AI suggestions for command palette | |
| - Body: `{ "query": "string", "context": {...} }` | |
| - Response: `{ "predictions": [ { id, name, description, source, confidence, perform } ] }` | |
| ### **Document indexing (RAG)** | |
| - **POST /documents/{docId}/rag-index** – index a document (PDF, txt, etc.) – server‑side indexing. | |
| - **GET /documents/{docId}/rag-status** – check indexing status. | |
| --- | |
| ## **12. Workspace & SmartGlass** | |
| - **GET /workspace/panels** – user's saved panel layouts (presets) | |
| - **POST /workspace/panels** – save layout | |
| - **DELETE /workspace/panels/{id}** | |
| --- | |
| ## **13. Data Hub & Research Objects** | |
| - **GET /protocols** – list lab protocols | |
| - **POST /protocols** – create new protocol | |
| - **PUT /protocols/{id}** – update | |
| - **POST /protocols/{id}/steps** – add a step | |
| - **PUT /protocols/{id}/steps/{stepId}** – update step | |
| - **POST /protocols/{id}/fork** – fork a protocol | |
| - **GET /repository/objects** – list research objects (datasets, code, etc.) | |
| - **POST /repository/objects** – upload a file (multipart form data) | |
| - **DELETE /repository/objects/{id}** | |
| - **GET /preregistrations** – list preregistrations | |
| - **POST /preregistrations** – submit a preregistration (with timestamp) | |
| --- | |
| ## **14. Projects** | |
| - **GET /projects** – user's projects | |
| - **GET /projects/{projectId}** – details (members, tasks, outputs) | |
| - **PUT /projects/{projectId}** – update | |
| - **POST /projects** – create project | |
| - **POST /projects/{projectId}/members** – add member | |
| - **PUT /projects/{projectId}/members/{userId}** – change role | |
| - **DELETE /projects/{projectId}/members/{userId}** | |
| - **GET /projects/{projectId}/tasks** – kanban tasks | |
| - **POST /projects/{projectId}/tasks** – add task | |
| - **PUT /projects/{projectId}/tasks/{taskId}** – update task (including column) | |
| - **DELETE /projects/{projectId}/tasks/{taskId}** | |
| - **POST /projects/{projectId}/outputs** – link an external output (article, dataset) | |
| --- | |
| ## **15. Two‑Factor Authentication (TOTP)** | |
| - **POST /users/me/2fa/enable** – generate TOTP secret and QR code | |
| - Response: `{ "secret": "string", "qrCode": "data:image/png;base64,..." }` | |
| - **POST /users/me/2fa/verify** – verify a TOTP code to enable 2FA | |
| - Body: `{ "code": "string" }` | |
| - **POST /users/me/2fa/disable** – disable 2FA | |
| - **GET /users/me/2fa/backup-codes** – retrieve backup codes (after verification) | |
| - Query: `?regenerate=true` to generate new ones | |
| --- | |
| ## **16. Password Reset & Security** | |
| - **POST /forgot-password** – request security question | |
| - Body: `{ "username": string }` | |
| - Response: `{ "question": "string" }` | |
| - **POST /reset-password** – reset password using answer | |
| - Body: `{ "username": string, "answer": string, "newPassword": string }` | |
| --- | |
| ## **17. Polls & Quizzes** | |
| - **GET /polls/{pollId}** – get poll/quiz data | |
| - **POST /polls/{pollId}/vote** – record vote(s) | |
| - Body: `{ "optionIds": [number] }` | |
| - **POST /polls** – create a poll (if implemented in your chat) | |
| --- | |
| ## **18. Event & Conference (WebRTC)** | |
| - **GET /conference/{roomId}/token** – get a TURN/STUN token (if using external service) | |
| - WebSocket signaling for WebRTC: `/conference/{roomId}` (using your `useSignaling` hook) | |
| --- | |
| ## **19. Admin & Stats** | |
| - **GET /admin/stats** – platform stats (total users, articles, etc.) – admin only. | |
| - **GET /users/me/analytics** – personalised analytics for dashboard | |
| --- | |
| ## **20. WebSocket Endpoints** | |
| - **Main WebSocket** for real‑time messaging and presence: `ws://localhost:8080/ws` (or relative `/ws`) | |
| - **Collaboration WebSocket** (Yjs): `ws://localhost:9093` | |
| - **Conference signaling WebSocket**: `ws://localhost:8080/conference/{roomId}` | |
| ### **WebSocket Message Types (for main chat)** | |
| - `new_message` (private) – `{ type: "new_message", message: Message }` | |
| - `new_group_message` | |
| - `typing` – `{ type: "typing", from: string, to: string, isTyping: boolean }` | |
| - `message_status` – `{ type: "message_status", messageId: number, status: "sent|delivered|seen" }` | |
| - `reaction` – `{ type: "reaction", messageId: number, userId: number, emoji: string }` | |
| - `message_edited` / `message_deleted` | |
| - `message_pinned` – `{ type: "message_pinned", groupId: number, pinned: PinnedMessage }` | |
| - `new_notification` – `{ type: "new_notification", notification: Notification }` | |
| - `presence` – `{ type: "presence", username: string, isOnline: boolean, lastSeen: string }` | |
| - `presence_ping` – client should send periodically to keep session alive. | |
| --- | |
| ## **Error Handling** | |
| All endpoints return standard HTTP status codes: | |
| - `200` – success | |
| - `201` – created | |
| - `400` – bad request (validation error) | |
| - `401` – unauthorised (missing or invalid token) | |
| - `403` – forbidden (e.g., trying to edit another user's article) | |
| - `404` – resource not found | |
| - `409` – conflict (e.g., duplicate username) | |
| - `500` – internal server error | |
| Error response body: `{ "error": "Description of the problem" }` | |
| --- | |
| ## **Authentication** | |
| Except for login, register, password reset, and public article views, all endpoints require a valid JWT in the `Authorization` header. | |
| The JWT should be obtained from `/login`. The token contains the user ID, username, and expiry. | |
| --- | |
| ## **Data Models (example)** | |
| **UserProfile** | |
| ```typescript | |
| { | |
| id: number; | |
| username: string; | |
| email?: string; | |
| fullName?: string; | |
| bio?: string; | |
| avatarUrl?: string; | |
| affiliation?: string; | |
| orcid?: string; | |
| googleScholar?: string; | |
| followersCount: number; | |
| followingCount: number; | |
| articlesCount: number; | |
| isPrivate: boolean; | |
| isEmailVerified: boolean; | |
| securityQuestion?: string; | |
| twoFactorEnabled: boolean; | |
| createdAt: string; | |
| } | |
| ``` | |
| **Article** | |
| ```typescript | |
| { | |
| id: number; | |
| title: string; | |
| abstract: string; | |
| body: string; | |
| author: UserProfile; | |
| tags: string[]; | |
| status: "published" | "draft"; | |
| views: number; | |
| likesCount: number; | |
| commentsCount: number; | |
| createdAt: string; | |
| updatedAt: string; | |
| } | |
| ``` | |
| **Message** (private) | |
| ```typescript | |
| { | |
| id: number; | |
| body: string; | |
| sentAt: string; | |
| from: string; | |
| fromUserId: number; | |
| to?: string; | |
| replyToId?: number; | |
| replyToBody?: string; | |
| status: "sending"|"sent"|"delivered"|"seen"; | |
| encrypted?: boolean; | |
| ciphertext?: string; | |
| reactions: Reaction[]; | |
| editedAt?: string; | |
| deletedAt?: string; | |
| attachments: UploadedFile[]; | |
| messageType: MessageType; | |
| paperData?: PaperData; | |
| } | |
| ``` | |
Xet Storage Details
- Size:
- 17.1 kB
- Xet hash:
- 2ebf9e031a29a25127e3ce4e31f6cf9843cc0659bdbbfba89b714c14049a137f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.