Bookmarks
Bookmarks Endpoints
Section titled “Bookmarks Endpoints”Bookmark endpoints provide CRUD operations for managing encrypted bookmarks.
List Bookmarks
Section titled “List Bookmarks”GET /api/v1/bookmarks
Returns all bookmarks for the authenticated user.
Authentication
Section titled “Authentication”Required (Cookie)
curl https://app.bitmarks.sh/api/v1/bookmarks \ -b "bitmarks_session=YOUR_TOKEN"const response = await fetch('https://app.bitmarks.sh/api/v1/bookmarks', { credentials: 'include'});const { data, meta } = await response.json();Response
Section titled “Response”Status: 200 OK
{ "data": [ { "id": "bm_abc123", "encrypted_data": "eyJhbGciOi...", "data_hash": "a1b2c3d4...", "created_at": 1735430400000, "updated_at": 1735430400000, "deleted_at": null } ], "meta": { "total": 150, "page": 1, "limit": 100 }}Query Parameters
Section titled “Query Parameters”| Param | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 100 | Items per page (max: 1000) |
Get Bookmark
Section titled “Get Bookmark”GET /api/v1/bookmarks/:id
Returns a single bookmark by ID.
Authentication
Section titled “Authentication”Required (Cookie)
Path Parameters
Section titled “Path Parameters”| Param | Type | Description |
|---|---|---|
id | string | Bookmark ID |
curl https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123 \ -b "bitmarks_session=YOUR_TOKEN"const response = await fetch('https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123', { credentials: 'include'});const bookmark = await response.json();Response
Section titled “Response”Status: 200 OK
{ "id": "bm_abc123", "encrypted_data": "eyJhbGciOi...", "data_hash": "a1b2c3d4...", "created_at": 1735430400000, "updated_at": 1735430400000, "deleted_at": null}Error Response
Section titled “Error Response”Status: 404 Not Found
{ "error": "Bookmark not found"}Create Bookmark
Section titled “Create Bookmark”POST /api/v1/bookmarks
Creates a new bookmark with encrypted data.
Authentication
Section titled “Authentication”Required (Cookie)
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
encrypted_data | string | Yes | Base64-encoded encrypted bookmark JSON |
data_hash | string | Yes | SHA-256 hash of plaintext data |
curl -X POST https://app.bitmarks.sh/api/v1/bookmarks \ -H "Content-Type: application/json" \ -b "bitmarks_session=YOUR_TOKEN" \ -d '{ "encrypted_data": "eyJhbGciOi...", "data_hash": "a1b2c3d4e5f6..." }'import { encryptObject, hashData } from '@bitmarks.sh/core';
// Encrypt the bookmarkconst bookmark = { id: 'bm_' + crypto.randomUUID(), title: 'Example', url: 'https://example.com', source: 'bookmarks'};
const encrypted = await encryptObject(bookmark, encryptionKey);const hash = await hashData(JSON.stringify(bookmark));
const response = await fetch('https://app.bitmarks.sh/api/v1/bookmarks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ encrypted_data: encrypted, data_hash: hash })});Response
Section titled “Response”Status: 201 Created
{ "id": "bm_abc123", "encrypted_data": "eyJhbGciOi...", "data_hash": "a1b2c3d4...", "created_at": 1735430400000, "updated_at": 1735430400000, "deleted_at": null}Error Response
Section titled “Error Response”Status: 400 Bad Request
{ "error": "Invalid request body"}Update Bookmark
Section titled “Update Bookmark”PUT /api/v1/bookmarks/:id
Updates an existing bookmark with new encrypted data.
Authentication
Section titled “Authentication”Required (Cookie)
Path Parameters
Section titled “Path Parameters”| Param | Type | Description |
|---|---|---|
id | string | Bookmark ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
encrypted_data | string | Yes | Base64-encoded encrypted bookmark JSON |
data_hash | string | Yes | SHA-256 hash of plaintext data |
curl -X PUT https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123 \ -H "Content-Type: application/json" \ -b "bitmarks_session=YOUR_TOKEN" \ -d '{ "encrypted_data": "eyJuZXdEYXRh...", "data_hash": "newHash123..." }'const response = await fetch('https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ encrypted_data: newEncryptedData, data_hash: newHash })});Response
Section titled “Response”Status: 200 OK
{ "id": "bm_abc123", "encrypted_data": "eyJuZXdEYXRh...", "data_hash": "newHash123...", "created_at": 1735430400000, "updated_at": 1735430500000, "deleted_at": null}Error Responses
Section titled “Error Responses”Status: 400 Bad Request
{ "error": "Invalid request body"}Status: 404 Not Found
{ "error": "Bookmark not found"}Delete Bookmark
Section titled “Delete Bookmark”DELETE /api/v1/bookmarks/:id
Soft deletes a bookmark (sets deleted_at timestamp).
Authentication
Section titled “Authentication”Required (Cookie)
Path Parameters
Section titled “Path Parameters”| Param | Type | Description |
|---|---|---|
id | string | Bookmark ID |
curl -X DELETE https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123 \ -b "bitmarks_session=YOUR_TOKEN"const response = await fetch('https://app.bitmarks.sh/api/v1/bookmarks/bm_abc123', { method: 'DELETE', credentials: 'include'});Response
Section titled “Response”Status: 200 OK
{ "success": true}Error Response
Section titled “Error Response”Status: 404 Not Found
{ "error": "Bookmark not found"}Encrypted Bookmark Schema
Section titled “Encrypted Bookmark Schema”interface Bookmark { id: string; // Unique identifier title: string; // Bookmark title url?: string; // URL (optional for folders) parentId?: string; // Parent folder ID dateAdded?: string; // ISO 8601 creation date dateModified?: string; // ISO 8601 modification date folder?: string; // Folder name path?: string; // Full path (e.g., "Bookmarks/Work/Dev") tags?: string[]; // User-defined tags favicon?: string; // Favicon URL or data URI domain?: string; // Extracted domain source: 'bookmarks' | 'history' | 'groups' | 'stars';
// GitHub star specific fields name?: string; // Repository name full_name?: string; // owner/repo stargazers_count?: number; // Star count description?: string | null; // Repo description owner?: { login: string; avatar_url: string; };}Working with Encrypted Data
Section titled “Working with Encrypted Data”Encrypting Before Send
Section titled “Encrypting Before Send”import { encryptObject, hashData } from '@bitmarks.sh/core';
async function createBookmark(bookmark, key) { const plaintext = JSON.stringify(bookmark); const encrypted = await encryptObject(bookmark, key); const hash = await hashData(new TextEncoder().encode(plaintext));
return fetch('/api/v1/bookmarks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ encrypted_data: encrypted, data_hash: hash }) });}Decrypting After Receive
Section titled “Decrypting After Receive”import { decryptObject } from '@bitmarks.sh/core';
async function getBookmarks(key) { const response = await fetch('/api/v1/bookmarks', { credentials: 'include' });
const { data } = await response.json();
return Promise.all( data.map(async (item) => { const decrypted = await decryptObject(item.encrypted_data, key); return { ...item, bookmark: decrypted }; }) );}