Hub API proposal (draft before implementation)
Base URL
Your can find Bearicorn API hosted on yourbearicorndomain.com/api
Authentication model
The current backend uses a cookie/JWT session flow via /api/login and /api/logout, with permission guards on endpoints.
The intended flow:
- Client authenticates via
POST /api/login. - Server sets an HttpOnly session/JWT cookie.
- All subsequent requests are authenticated by that cookie.
Response style
The current code typically returns plain DTO objects or 204 No Content.
201 Createdusually returns{ "id": number }204 No Contentreturns an empty body200 OKreturns DTO objects or arrays
This draft keeps that style on purpose.
Error model (simple, consistent shape)
Example error response:
{
"statusCode": 403,
"message": "User not authorized for the room",
"error": "Forbidden"
}2. Auth & session endpoints
2.1 Login
POST /api/login
Authenticate a user and start a session.
Request example
{
"email": "[email protected]",
"password": "Sup3rSecret!"
}Response 200 example
{
"jwtHash": "sha256-hash-of-jwt"
}2.2 Logout
POST /api/logout
End the current session (clear cookie).
Response 204
No body.
3. Users (existing endpoints)
This section describes what is already in the codebase.
3.1 Create user (invite flow)
POST /api/user
Create a new invited user.
Request example
{
"email": "[email protected]",
"fullName": "New User",
"password": "TempPass123!"
}Response 201
{
"id": 123
}3.2 Activate invited user
POST /api/user/activate
Activate the invited user (provide keys + final credentials).
Request example
{
"fullName": "New User",
"password": "FinalStrongPass!",
"privateKey": "<encrypted-private-key>",
"publicKey": "<public-key>",
"privateKeyChecksum": "checksum"
}Response 201
{
"id": 123
}3.3 Get current user
GET /api/user/me
Return details about the currently authenticated user.
Response 200 example
{
"id": 7,
"fullName": "John Doe",
"email": "[email protected]",
"privateKey": "<encrypted-private-key>",
"publicKey": "<public-key>",
"roles": ["ADMIN"],
"tokens": ["USER__ME", "CHAT__WRITE"],
"jwtHash": "sha256-hash-of-jwt",
"photoId": "42"
}3.4 Update current user (profile + avatar)
POST /api/user/me
Update the current user profile. This is a multipart/form-data request.
Request example
Content-Type: multipart/form-data- fields:
fullName: stringphoto: file(optional)
Response 204
No body.
3.5 Search users
GET /api/user?search=...
Search users by a string, or load by IDs.
Query params (aligned with DTO)
search: string(or alternativelyids[])omit: string[](optional)
Response 200 example
[
{
"id": 7,
"fullName": "John Doe",
"email": "[email protected]",
"publicKey": "<public-key>",
"photoId": "42"
}
]3.6 List all users (admin)
GET /api/user/all
Return all users with admin-facing fields.
Response 200 example
[
{
"id": 7,
"fullName": "John Doe",
"email": "[email protected]",
"publicKey": "<public-key>",
"photoId": "42",
"roles": ["ADMIN"],
"createdAt": "2026-01-10T12:00:00.000Z",
"createdBy": 1
}
]3.7 Get user detail
GET /api/user/:id
Return a single user's public detail.
Response 200 example
{
"id": 9,
"fullName": "Jane Smith",
"email": "[email protected]",
"publicKey": "<public-key>",
"photoId": "77"
}4. Users (proposed missing endpoints)
These are not in controllers yet, but they are the typical operations you explicitly asked for.
4.1 Admin edit user
PUT /api/user/:id
Admin updates basic user fields.
Request example
{
"fullName": "Jane Smith",
"email": "[email protected]",
"state": "ACTIVE"
}Response 204
No body.
4.2 Delete user (soft delete)
DELETE /api/user/:id
Soft-delete a user (for example transition to DELETED).
Response 204
No body.
4.3 Change user roles / permissions
PUT /api/user/:id/roles
Change user roles (ADMIN, USER, INVITEE).
Request example
{
"roles": ["USER"]
}Response 204
No body.
4.4 Reset password flows
A clean design usually separates request/confirm and supports admin reset.
A) Self-service: request reset
POST /api/user/password/reset/request
Request
{
"email": "[email protected]"
}Response 204
No body (do not leak whether the user exists).
B) Self-service: confirm reset
POST /api/user/password/reset/confirm
Request
{
"token": "reset-token",
"newPassword": "NewStrongPass123!"
}Response 204
No body.
C) Admin reset for a specific user
POST /api/user/:id/password/reset
Request example
{
"newPassword": "TempPass123!",
"invalidateSessions": true
}Response 204
No body.
5. Rooms (chat) endpoints
Rooms and messages already have a solid baseline in the code. The contract below mirrors the current controllers.
5.1 Create room
POST /api/room
Create a room and configure access for other users.
Request example
{
"name": "Incident 2026-01-24",
"messageExpiration": 86400,
"isPublic": false,
"encryptionKey": "<room-key-for-creator>",
"otherUsers": [
{
"userId": 9,
"encryptionKey": "<room-key-for-user-9>"
}
]
}Response 201
{
"id": 55
}5.2 List rooms
GET /api/room
List rooms for the current user, including unread counts.
Response 200 example
[
{
"id": 55,
"name": "Incident 2026-01-24",
"lastActivity": "2026-01-24T10:00:00.000Z",
"unreadCount": 3,
"users": [{ "userId": 7 }, { "userId": 9 }],
"blockedBy": null
}
]5.3 Get room detail
GET /api/room/:id
Return room detail, including the encryption key for the current user.
Response 200 example
{
"id": 55,
"name": "Incident 2026-01-24",
"encryptionKey": "<room-key-for-current-user>",
"isEditor": true,
"isOwner": true,
"yolo": {},
"messageExpiration": 86400,
"isPublic": false,
"users": [
{ "userId": 7, "accessLevel": "OWNER" },
{ "userId": 9, "accessLevel": "EDITOR" }
],
"lastActivity": "2026-01-24T10:00:00.000Z",
"unreadCount": 3,
"blockedBy": null
}5.4 Update room
POST /api/room/:id
Update room fields (name, messageExpiration, yolo).
Request example
{
"name": "Incident 2026-01-24 (resolved)",
"messageExpiration": 604800,
"yolo": {
"color": "red"
}
}Response 204
No body.
5.5 Delete room
DELETE /api/room/:id
Delete a room.
Response 204
No body.
5.6 Mark room as read
POST /api/room/:id/read
Mark all messages in the room as read.
Response 204
No body.
6. Room permissions endpoints
Room permissions follow the same pattern used by buckets and two-factor records.
6.1 Add user to room
POST /api/room/:id/user/:userId
Grant room access to another user.
Request example
{
"encryptionKey": "<room-key-for-target-user>",
"accessLevel": "EDITOR"
}Response 204
No body.
6.2 Change room access level
PUT /api/room/:id/user/:userId
Change access level for a room member.
Request example
{
"accessLevel": "VIEWER"
}Response 204
No body.
6.3 Remove user from room
DELETE /api/room/:id/user/:userId
Remove a user's access to a room.
Response 204
No body.
6.4 Leave room (current user)
DELETE /api/room/:id/user/me
Current user removes their own access.
Response 204
No body.
7. Messages endpoints (post, edit, delete)
7.1 Create message
POST /api/room/:roomId/message
Create a message in a room.
Request example
{
"messageType": "TEXT",
"body": "I need a review on PR #42",
"replyToMessageId": null,
"fileId": null,
"mentionIds": [9]
}Response 201
{
"id": 9001
}7.2 Update message
POST /api/room/:roomId/message/:id
Edit an existing message.
Request example
{
"body": "I need a review on PR #42 (urgent)",
"mentionIds": [9]
}Response 204
No body.
7.3 Delete message
DELETE /api/room/:roomId/message/:id
Delete a message.
Response 204
No body.
7.4 List messages (pagination via take + until)
GET /api/room/:roomId/message?take=50&until=2026-01-24T10:00:00.000Z&sendEncKey=true
Response 200 example
{
"messages": [
{
"id": 9001,
"messageType": "TEXT",
"body": "I need a review on PR #42",
"fileId": null,
"createdAt": "2026-01-24T10:01:00.000Z",
"createdBy": 7,
"versionedAt": null,
"replyToMessage": null,
"replyToMessageDeleted": null,
"reactions": [],
"expiresAt": null
}
],
"timestamp": "2026-01-24T10:02:00.000Z",
"encryptionKey": "<room-key-for-current-user>"
}7.5 Poll updates since a timestamp
GET /api/room/:roomId/message/update?since=2026-01-24T10:00:00.000Z
Response 200 example
{
"created": [],
"updated": [],
"deleted": [8999],
"timestamp": "2026-01-24T10:05:00.000Z"
}7.6 Message info (read receipts / history metadata)
GET /api/room/:roomId/message/:id
Response 200 example
{
"createdAt": "2026-01-24T10:01:00.000Z",
"createdBy": 7,
"versionedAt": "2026-01-24T10:03:00.000Z",
"readBy": [7, 9]
}8. Buckets & files endpoints
In Hub, files live inside buckets, so bucket remains the parent resource.
8.1 Create bucket
POST /api/bucket
Request example
{
"name": "Legal",
"treeStructure": "<encrypted-tree-json>",
"encryptionKey": "<bucket-key-for-creator>"
}Response 201
{
"id": 12
}8.2 List buckets
GET /api/bucket
Response 200 example
[
{
"id": 12,
"name": "Legal",
"treeStructure": "<encrypted-tree-json>",
"encryptionKey": "<bucket-key-for-current-user>",
"yolo": {},
"isEditor": true,
"isOwner": true
}
]8.3 Get bucket detail
GET /api/bucket/:id
Response 200 example
{
"id": 12,
"name": "Legal",
"treeStructure": "<encrypted-tree-json>",
"encryptionKey": "<bucket-key-for-current-user>",
"yolo": {},
"isEditor": true,
"isOwner": true,
"users": [
{ "userId": 7, "accessLevel": "OWNER" },
{ "userId": 9, "accessLevel": "EDITOR" }
],
"createdAt": "2026-01-20T08:00:00.000Z",
"createdBy": 1,
"versionedAt": "2026-01-22T09:00:00.000Z"
}8.4 Update bucket
POST /api/bucket/:id
Request example
{
"name": "Legal (2026)",
"treeStructure": "<encrypted-tree-json-v2>",
"yolo": {
"icon": "scale"
}
}Response 204
No body.
9. Bucket permissions endpoints
9.1 Add user to bucket
POST /api/bucket/:id/user/:userId
Request example
{
"encryptionKey": "<bucket-key-for-target-user>",
"accessLevel": "EDITOR"
}Response 204
No body.
9.2 Change bucket access level
PUT /api/bucket/:id/user/:userId
Request example
{
"accessLevel": "VIEWER"
}Response 204
No body.
9.3 Remove user from bucket
DELETE /api/bucket/:id/user/:userId
Response 204
No body.
9.4 Leave bucket (current user)
DELETE /api/bucket/:id/user/me
Response 204
No body.
10. Files: upload, detail, rename, delete
10.1 Upload file (TUS)
POST /api/tus
Uploads follow the TUS protocol. Metadata is required and mirrors the existing DTO shape:
bucketIdfileNamemimeTypedecryptedSizeoverrideFileId(optional; used to replace an existing file)
Example TUS metadata header
Upload-Metadata: bucketId MTI=,fileName Zml1dmEucGRm,mimeType YXBwbGljYXRpb24vcGRm,decryptedSize MTA0ODU2Note: values are base64-encoded per the TUS specification.
Response
- Standard TUS response (
201 Created+Locationheader)
10.2 Get file detail
GET /api/bucket/:bucketId/file/:fileId
Response 200 example
{
"id": 501,
"name": "contract.pdf",
"mimeType": "application/pdf",
"size": 345678,
"decryptedSize": 345678,
"createdAt": "2026-01-24T09:00:00.000Z",
"createdBy": 7,
"versionedAt": "2026-01-24T09:05:00.000Z",
"versionedBy": 7
}10.3 Rename / edit file
POST /api/bucket/:bucketId/file/:fileId
Rename a file.
Request example
{
"name": "contract-final.pdf"
}Response 204
No body.
10.4 Download file
GET /api/bucket/:bucketId/file/:fileId/download
Download the binary content. (Implementation may rewrite this path to the TUS handler.)
Response
200 OK+ binary data
10.5 Delete file
DELETE /api/bucket/:bucketId/file/:fileId
Delete a file.
Response 204
No body.
11. Files: proposed file-level permissions endpoints
Even if permissions are currently bucket-level, file-level ACLs may be useful in the future.
11.1 Add user access to file
POST /api/bucket/:bucketId/file/:fileId/user/:userId
Request example
{
"accessLevel": "VIEWER",
"encryptionKey": "<file-key-for-target-user>"
}Response 204
No body.
11.2 Change user access on file
PUT /api/bucket/:bucketId/file/:fileId/user/:userId
Request example
{
"accessLevel": "EDITOR"
}Response 204
No body.
11.3 Remove user access from file
DELETE /api/bucket/:bucketId/file/:fileId/user/:userId
Response 204
No body.
12. Documents endpoints (editable text files)
Documents are text resources stored inside buckets.
12.1 Create document
POST /api/bucket/:bucketId/document
Request example
{
"name": "Runbook",
"body": "# Incident procedure\n\n1. Determine the scope"
}Response 201
{
"id": 801
}12.2 Get document detail
GET /api/bucket/:bucketId/document/:documentId
Response 200 example
{
"id": 801,
"name": "Runbook",
"body": "# Incident procedure\n\n1. Determine the scope",
"createdAt": "2026-01-24T08:00:00.000Z",
"createdBy": 7,
"versionedAt": "2026-01-24T08:30:00.000Z",
"versionedBy": 9
}12.3 Update document
POST /api/bucket/:bucketId/document/:documentId
Partial update (name and/or body).
Request example
{
"body": "# Incident procedure\n\n1. Determine the scope\n2. Inform the customer"
}Response 204
No body.
12.4 Delete document
DELETE /api/bucket/:bucketId/document/:documentId
Response 204
No body.
12.5 Document history
GET /api/bucket/:bucketId/document/:documentId/history
Response 200 example
[
{
"uid": "550e8400-e29b-41d4-a716-446655440000",
"state": "ACTIVE",
"versionedAt": "2026-01-24T08:30:00.000Z",
"versionedBy": 9,
"nameChanged": false,
"bodyChanged": true,
"name": "Runbook"
}
]13. Notifications endpoints
Not explicitly requested, but they are part of the user-facing behavior already present in the app.
13.1 List notifications
GET /api/notification
Response 200 example (simplified)
{
"read": [],
"unread": [],
"pinned": []
}13.2 Overview (counts)
GET /api/notification/overview
Response 200 example
{
"unread": 3,
"pinned": 1
}13.3 Mark all as read
POST /api/notification/read
Response 204
No body.
13.4 Mark a single notification state
- POST
/api/notification/:id/read - POST
/api/notification/:id/unread - POST
/api/notification/:id/pin - POST
/api/notification/:id/unpin
Response 204
No body.
14. Recommended next steps (implementation plan)
Because the goal is “documentation first, implementation second”, a good sequence would be:
- Add DTOs for the proposed missing admin endpoints:
UpdateUserRequestUpdateUserRolesRequestPasswordResetRequest/Confirm/...
- Decide whether file permissions are:
- inherited from the bucket (simpler), or
- explicit per-file/per-document ACLs.
- Confirm update semantics:
- current style often uses
POST /resource/:id, - alternative is
PUT/PATCHfor stricter REST semantics.
- current style often uses
- Then implement controllers and services to match this document.
15. Quick index of core endpoints
Users
POST /api/userDELETE /api/user/:id(proposed)PUT /api/user/:id/roles(proposed)POST /api/user/password/reset/request(proposed)
Rooms & messages
POST /api/roomPOST /api/room/:roomId/messagePOST /api/room/:roomId/message/:idDELETE /api/room/:roomId/message/:id
Files & documents
POST /api/tusGET /api/bucket/:bucketId/file/:fileIdPOST /api/bucket/:bucketId/file/:fileIdPOST /api/bucket/:bucketId/documentPOST /api/bucket/:bucketId/document/:documentId
This document is intentionally a draft. The purpose is to let FE/BE align on the contract before the implementation details are finalized.