openapi: 3.1.0 info: title: BrowserBookmark API version: 0.1.0 description: Internal bookmark manager API (Web + Extension) servers: - url: http://localhost:3001 tags: - name: Health - name: Auth - name: Bookmarks - name: Folders - name: ImportExport - name: Sync - name: Admin components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: Error: type: object properties: message: type: string required: [message] User: type: object properties: id: type: string format: uuid email: type: string format: email role: type: string enum: [user, admin] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, email, role, createdAt, updatedAt] Folder: type: object properties: id: type: string format: uuid userId: type: string format: uuid parentId: anyOf: - type: string format: uuid - type: 'null' name: type: string visibility: type: string enum: [public, private] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, userId, parentId, name, visibility, createdAt, updatedAt] Bookmark: type: object properties: id: type: string format: uuid userId: type: string format: uuid folderId: anyOf: - type: string format: uuid - type: 'null' title: type: string url: type: string urlNormalized: type: string urlHash: type: string visibility: type: string enum: [public, private] source: type: string enum: [manual, import] updatedAt: type: string format: date-time deletedAt: anyOf: - type: string format: date-time - type: 'null' required: [id, userId, folderId, title, url, urlNormalized, urlHash, visibility, source, updatedAt, deletedAt] FolderPatch: type: object properties: parentId: anyOf: - type: string format: uuid - type: 'null' name: type: string visibility: type: string enum: [public, private] BookmarkPatch: type: object properties: folderId: anyOf: - type: string format: uuid - type: 'null' title: type: string url: type: string visibility: type: string enum: [public, private] security: [] paths: /health: get: tags: [Health] summary: Health check operationId: healthCheck responses: '200': description: OK content: application/json: schema: type: object properties: ok: type: boolean required: [ok] /auth/register: post: tags: [Auth] summary: Register operationId: register requestBody: required: true content: application/json: schema: type: object properties: email: type: string format: email password: type: string minLength: 8 required: [email, password] responses: '200': description: OK content: application/json: schema: type: object properties: token: type: string user: $ref: '#/components/schemas/User' required: [token, user] /auth/login: post: tags: [Auth] summary: Login operationId: login requestBody: required: true content: application/json: schema: type: object properties: email: type: string format: email password: type: string required: [email, password] responses: '200': description: OK content: application/json: schema: type: object properties: token: type: string user: $ref: '#/components/schemas/User' required: [token, user] /auth/me: get: tags: [Auth] summary: Current user operationId: me security: - bearerAuth: [] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/User' /folders: get: tags: [Folders] summary: List my folders operationId: listFolders security: - bearerAuth: [] responses: '200': description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Folder' post: tags: [Folders] summary: Create folder operationId: createFolder security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: parentId: anyOf: - type: string format: uuid - type: 'null' name: type: string visibility: type: string enum: [public, private] required: [parentId, name, visibility] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Folder' /folders/{id}: patch: tags: [Folders] summary: Update folder operationId: updateFolder security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FolderPatch' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Folder' delete: tags: [Folders] summary: Delete folder operationId: deleteFolder security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: '200': description: OK content: application/json: schema: type: object properties: ok: type: boolean required: [ok] /bookmarks/public: get: tags: [Bookmarks] summary: List public bookmarks (anonymous allowed) operationId: listPublicBookmarks parameters: - in: query name: q schema: type: string required: false responses: '200': description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Bookmark' /bookmarks: get: tags: [Bookmarks] summary: List my bookmarks operationId: listMyBookmarks security: - bearerAuth: [] parameters: - in: query name: q schema: type: string required: false responses: '200': description: OK content: application/json: schema: type: array items: $ref: '#/components/schemas/Bookmark' post: tags: [Bookmarks] summary: Create bookmark (auto-dedupe) operationId: createBookmark security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: folderId: anyOf: - type: string format: uuid - type: 'null' title: type: string url: type: string visibility: type: string enum: [public, private] required: [folderId, title, url, visibility] responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Bookmark' /bookmarks/{id}: patch: tags: [Bookmarks] summary: Update bookmark operationId: updateBookmark security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BookmarkPatch' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Bookmark' delete: tags: [Bookmarks] summary: Soft delete bookmark operationId: deleteBookmark security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Bookmark' /bookmarks/import/html: post: tags: [ImportExport] summary: Import bookmarks from Chrome/Edge HTML operationId: importBookmarksHtml security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary required: [file] responses: '200': description: OK content: application/json: schema: type: object properties: imported: type: integer merged: type: integer required: [imported, merged] /bookmarks/export/html: get: tags: [ImportExport] summary: Export my bookmarks as HTML operationId: exportBookmarksHtml security: - bearerAuth: [] responses: '200': description: Netscape Bookmark HTML content: text/html: schema: type: string /sync/push: post: tags: [Sync] summary: Push local changes to cloud (LWW) operationId: syncPush security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: bookmarks: type: array items: $ref: '#/components/schemas/Bookmark' folders: type: array items: $ref: '#/components/schemas/Folder' required: [bookmarks, folders] responses: '200': description: OK content: application/json: schema: type: object properties: ok: type: boolean required: [ok] /sync/pull: get: tags: [Sync] summary: Pull cloud changes since timestamp (LWW) operationId: syncPull security: - bearerAuth: [] parameters: - in: query name: since schema: type: string format: date-time required: false responses: '200': description: OK content: application/json: schema: type: object properties: bookmarks: type: array items: $ref: '#/components/schemas/Bookmark' folders: type: array items: $ref: '#/components/schemas/Folder' serverTime: type: string format: date-time required: [bookmarks, folders, serverTime]