- Notification bell with invites (accept/decline refreshes workspaces) and unread badge (polling + socket push); team chat view realtime - Avatar/background uploads in settings + glassmorphism widgets toggle; background layer resolves /uploads URLs; full-bleed blurred backdrop - Sidebar: visible creation errors, working sub-pages (parent_id), TEAM badge workspaces, refresh button, chat nav; admin creates users - Tasks: per-team boards, assignee select with avatars; admin tabs for users/teams/groups (team workspaces, permission checkboxes) - Register view removed (admin-only accounts); login localized; prettier emoji set; scaling/overflow + mobile fixes
4.7 KiB
4.7 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 ondue_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}→ setsended_at+duration_secondsPATCH /time/:id,DELETE /time/:id(own or admin+)
Admin (requires is_admin)
GET /admin/overview→ counts + recent usersGET /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+ orworkspace.invitepermission)GET /invites/mine,POST /invites/:id/accept,POST /invites/:id/declineGET /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},DELETE /chat/message/:idGET /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(seedsTeam Creators), groups CRUD + membersPOST /upload(multipart image ≤5MB) →{ url: /uploads/... }
Health
GET /health->{ok:true, db:'up'}or503 {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 }.