Files
openStack/docs/API.md
T
x3 4fe56265c9
ci / backend (push) Canceled after 0s
ci / frontend (push) Canceled after 0s
feat(frontend): chat tabs, flat SVG icons, upload autosave, per-user rights
- Chat rework: Chats (private DMs with user search, online dots, unread
  badges) and Team chats tabs; shared message component with reactions,
  edit, image attachments, message search and typing indicators
- Flat modern inline SVG icon set (no external dependency) replaces
  emoji chrome across nav, headers, buttons, tabs and settings
- Uploaded avatar/background images apply instantly (auto-save) with
  confirmation note; per-user permission matrix in dashboard members
- Login localized, invite header uses icon, comment header cleaned
2026-09-22 14:41:42 +02:00

5.3 KiB

API Reference

Base URL: http://localhost:3000/api. Auth: Authorization: Bearer <jwt>.

Auth

POST /auth/register

{ "email": "a@example.com", "name": "Ada", "password": "secret123" }

-> 201 { user, token }. Errors: 400 validation, 409 email taken.

POST /auth/login

{ "email": "a@example.com", "password": "secret123" }

-> 200 { user, token }. Errors: 401 invalid credentials.

GET /auth/me

-> 200 { user }.

curl -X POST localhost:3000/api/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"email":"a@example.com","name":"Ada","password":"secret123"}'

Workspaces

Method Path Role Description
GET /workspaces member List my workspaces
POST /workspaces any logged-in Create workspace (caller becomes owner)
GET /workspaces/:id viewer+ Get workspace
PATCH /workspaces/:id admin+ Rename
DELETE /workspaces/:id owner Delete
GET /workspaces/:id/members viewer+ List members
POST /workspaces/:id/members admin+ Invite {email, role} (role: admin/member/viewer)
PATCH /workspaces/:id/members/:userId admin+ Change role
DELETE /workspaces/:id/members/:userId admin+ Remove member

Roles rank: viewer < member < admin < owner. Viewers read only.

Pages

Method Path Description
GET /pages/by-workspace/:workspaceId List pages (flat, client builds tree)
POST /pages Create {workspace_id, parent_id?, title?} (member+)
GET /pages/:id Get page + comments
PATCH /pages/:id Update title/icon/cover/content/position/parent/archive (member+)
DELETE /pages/:id Delete incl. children via FK cascade
GET /pages/search/query?q=&workspace_id= Title search
POST /pages/:id/comments Add comment {body}
DELETE /pages/:pageId/comments/:commentId Delete (author or admin+)

Content fields: content_json (TipTap JSON), content_html (rendered HTML).

Users

  • GET /users/search?email= — lookup for invites (auth required).
  • GET /users/discover?q= — fuzzy discovery (min 2 chars, max 10 hits, no hashes).
  • PATCH /users/me — profile/appearance (name, email, avatar, locale, theme, bg_image, bg_blur).
  • PATCH /users/me/password — { currentPassword, newPassword }.

Books

  • GET /books/by-workspace/:workspaceId, POST /books {workspace_id,title?,icon?}
  • PATCH /books/:id, DELETE /books/:id (pages inside cascade).

Tasks

  • GET /tasks/by-workspace/:workspaceId?status=&from=&to= (calendar range on due_at)
  • POST /tasks {workspace_id, book_id?, page_id?, title, status?, priority?, due_at?}
  • PATCH /tasks/:id, DELETE /tasks/:id

Time tracking

  • GET /time/by-workspace/:workspaceId → { entries, open }
  • POST /time/start {workspace_id, book_id?, page_id?, description?} (409 if running)
  • POST /time/stop {workspace_id} → sets ended_at + duration_seconds
  • PATCH /time/:id, DELETE /time/:id (own or admin+)

Admin (requires is_admin)

  • GET /admin/overview → counts + recent users
  • GET /admin/users, POST /admin/users {name,email,password,is_admin?} (admins create accounts; public registration is disabled once installed), PATCH /admin/users/:id, DELETE /admin/users/:id

Invites & notifications

  • POST /workspaces/:id/members {email,role} → pending invite + notification (workspace admin+ or workspace.invite permission)
  • GET /invites/mine, POST /invites/:id/accept, POST /invites/:id/decline
  • GET /workspaces/:id/permissions, PATCH /workspaces/:id/permissions (per-user allow/deny/inherit overrides, workspace admin+)
  • GET /notifications/mine?unread=1 → { notifications, unread }
  • PATCH /notifications/:id/read, POST /notifications/read-all

Chat / teams / groups / upload

  • GET /chat/:workspaceId, POST /chat/:workspaceId {body,attachment?}, PATCH /chat/message/:id, DELETE /chat/message/:id, GET /chat/:workspaceId/search?q=
  • GET /dm, POST /dm {user_id}, GET /dm/:id/messages, POST /dm/:id/messages, PATCH/DELETE /dm/message/:mid, GET /dm/:id/search?q=
  • POST /reactions/toggle {target_type,target_id,emoji} (chat + DM messages)
  • Socket: chat:join, dm:join, chat:typing, dm:typing, presence:online, chat:message/edited/deleted, dm:message/edited/deleted, reaction:updated
  • GET /teams/by-workspace/:id, POST /teams, PATCH/DELETE /teams/:id, team members CRUD, POST /teams/:id/workspace {name} (team workspace + badge)
  • GET /groups/by-workspace/:id (seeds Team Creators), groups CRUD + members
  • POST /upload (multipart image ≤5MB) → { url: /uploads/... }

Health

  • GET /health -> {ok:true, db:'up'} or 503 {ok:false, db:'down'}.

Real-time (Socket.IO)

Connect: io(url, { auth: { token } }).

  • page:join { pageId } — join room; server checks workspace membership.
  • page:edit { pageId, content_json, content_html } — persist + broadcast to others. Viewers are ignored server-side.
  • typing { pageId, name } — broadcast typing indicator.
  • Server events: page:updated { page, from? }, page:deleted { id }, comment:added { comment }, presence:update { members: [{userId,email,name}] }, error:message { error }.