Skip to main content
The Bookmarks API is the core of Bkmark. You can store any URL as a bookmark, attach tags and groups, mark items as favorites or archived, and manage an entire bookmark library programmatically. All endpoints require a valid Bearer token in the Authorization header — see the Authentication guide to obtain one.
All endpoints are relative to the base URL https://api.bkmark.it/api/v1. Pagination uses cursor-based navigation: pass the nextCursor value from one response as the cursor parameter in your next request. When nextCursor is null, you have reached the last page.

GET /api/v1/bookmarks

List bookmarks for the authenticated user. Results are paginated and can be filtered by group, tag, type, source, and read/favorite/archive status.
cursor
string
Pagination cursor. Pass the nextCursor value from a previous response to fetch the next page.
limit
number
default:"20"
Number of items to return per page. Accepted range: 1–100.
groupId
string
Filter to bookmarks that belong to this group UUID.
tagId
string
Filter to bookmarks that have this tag UUID applied.
Full-text search query. Searches across title, description, and URL.
isFavorite
boolean
When true, returns only favorited bookmarks.
isArchived
boolean
When true, returns only archived bookmarks.
isUnread
boolean
When true, returns only bookmarks that have never been marked as read (i.e., readAt is null).
type
string
Filter by bookmark type. One of: link, note, code, image.
source
string
Filter by the source that created the bookmark. One of: web, extension, api, import, slack.
sortField
string
default:"createdAt"
Field to sort by. One of: createdAt, title, url.
sortDir
string
default:"desc"
Sort direction. One of: asc, desc.
curl "https://api.bkmark.it/api/v1/bookmarks?limit=10&isFavorite=true&sortField=createdAt&sortDir=desc" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
{
  "data": [
    {
      "id": "3f7a1c2e-84b0-4d9e-a3f2-1c2e3f7a84b0",
      "url": "https://www.typescriptlang.org/docs/handbook/2/types-from-types.html",
      "title": "Types from Types — TypeScript Handbook",
      "description": "A deep dive into template literal types, conditional types, and mapped types.",
      "type": "link",
      "source": "extension",
      "isFavorite": true,
      "isArchived": false,
      "readAt": null,
      "tags": [
        { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "typescript", "color": "blue" },
        { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "reading", "color": "amber" }
      ],
      "groups": [
        { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "name": "Engineering" }
      ],
      "createdAt": "2025-03-15T09:22:11.000Z",
      "updatedAt": "2025-03-15T09:22:11.000Z"
    }
  ],
  "nextCursor": "d4e5f6a7-b8c9-0123-defa-234567890123"
}

POST /api/v1/bookmarks

Create a new bookmark. If you omit title or description, Bkmark automatically fetches and parses the URL to populate them. Tags named in tagNames are created on the fly if they don’t already exist.
url
string
required
The URL to bookmark. Required for link and image types.
title
string
Title override. If omitted, Bkmark fetches it from the URL’s <title> tag.
description
string
Short description or note. Auto-populated from the page’s meta description if omitted.
type
string
default:"link"
Bookmark type. One of: link, note, code, image.
tagNames
string[]
Array of tag names to apply. Tags that don’t exist are created automatically.
groupIds
string[]
Array of group UUIDs to add this bookmark to.
source
string
The originating surface. One of: web, extension, api, import, slack. Defaults to api for programmatic requests.
force
boolean
Set to true to bypass duplicate URL detection and create a second bookmark for the same URL.
If the URL already exists in the library and force is not set, the API returns 409 Conflict with error code duplicate_url. Use force: true if you intentionally want a duplicate entry.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://react.dev/learn/thinking-in-react",
    "title": "Thinking in React",
    "description": "The React mental model explained with a practical example.",
    "type": "link",
    "tagNames": ["react", "frontend"],
    "groupIds": ["c3d4e5f6-a7b8-9012-cdef-123456789012"],
    "source": "api"
  }'
Returns 201 Created with the newly created bookmark object.
{
  "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "url": "https://react.dev/learn/thinking-in-react",
  "title": "Thinking in React",
  "description": "The React mental model explained with a practical example.",
  "type": "link",
  "source": "api",
  "isFavorite": false,
  "isArchived": false,
  "readAt": null,
  "tags": [
    { "id": "f6a7b8c9-d0e1-2345-fabc-456789012345", "name": "react", "color": "cyan" },
    { "id": "a7b8c9d0-e1f2-3456-abcd-567890123456", "name": "frontend", "color": null }
  ],
  "groups": [
    { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "name": "Engineering" }
  ],
  "createdAt": "2025-04-01T14:05:33.000Z",
  "updatedAt": "2025-04-01T14:05:33.000Z"
}

GET /api/v1/bookmarks/:id

Retrieve a single bookmark by its UUID.
id
string
required
The UUID of the bookmark to retrieve.
curl "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
{
  "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "url": "https://react.dev/learn/thinking-in-react",
  "title": "Thinking in React",
  "description": "The React mental model explained with a practical example.",
  "type": "link",
  "source": "api",
  "isFavorite": false,
  "isArchived": false,
  "readAt": null,
  "tags": [
    { "id": "f6a7b8c9-d0e1-2345-fabc-456789012345", "name": "react", "color": "cyan" }
  ],
  "groups": [
    { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "name": "Engineering" }
  ],
  "createdAt": "2025-04-01T14:05:33.000Z",
  "updatedAt": "2025-04-01T14:05:33.000Z"
}

PATCH /api/v1/bookmarks/:id

Update a bookmark’s metadata. All body fields are optional — only send what you want to change.
id
string
required
The UUID of the bookmark to update.
title
string
New title for the bookmark.
description
string
New description.
isFavorite
boolean
Set to true to favorite the bookmark, false to unfavorite it.
isArchived
boolean
Set to true to archive the bookmark, false to unarchive it.
readAt
string
ISO 8601 timestamp to mark the bookmark as read (e.g. "2025-04-01T15:00:00.000Z"). Send null to mark it as unread again.
curl -X PATCH "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Thinking in React — Official Guide",
    "isFavorite": true,
    "readAt": "2025-04-02T09:00:00.000Z"
  }'
Returns 200 OK with the updated bookmark object.

DELETE /api/v1/bookmarks/:id

Delete a bookmark. By default this is a soft delete — the bookmark moves to trash and can be restored. Add ?permanent=true to bypass trash and delete immediately.
id
string
required
The UUID of the bookmark to delete.
permanent
boolean
Set to true to permanently delete the bookmark instead of moving it to trash. This action is irreversible.
# Soft delete (moves to trash)
curl -X DELETE "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Permanent delete (no recovery)
curl -X DELETE "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234?permanent=true" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Returns 204 No Content on success.

POST /api/v1/bookmarks/:id/tags

Replace all tags on a bookmark in one call. Any tag names that don’t exist are created automatically. Sending an empty array removes all tags from the bookmark.
id
string
required
The UUID of the bookmark.
tagNames
string[]
required
Complete list of tag names the bookmark should have after this call. Replaces the existing tag set entirely.
This is a replace operation, not an append. If the bookmark currently has tags ["dev", "reading"] and you POST ["ai"], the result is only ["ai"]. To add a tag without removing others, first fetch the current tags and include them in your new list.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234/tags" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{ "tagNames": ["react", "frontend", "reading"] }'
Returns 200 OK with the updated bookmark object.

POST /api/v1/bookmarks/:id/groups

Replace all group assignments for a bookmark. Sending an empty array removes the bookmark from all groups.
id
string
required
The UUID of the bookmark.
groupIds
string[]
required
Complete list of group UUIDs the bookmark should belong to after this call. Replaces the existing group assignments entirely.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks/e5f6a7b8-c9d0-1234-efab-345678901234/groups" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{ "groupIds": ["c3d4e5f6-a7b8-9012-cdef-123456789012", "d4e5f6a7-b8c9-0123-defa-234567890123"] }'
Returns 200 OK with the updated bookmark object.

POST /api/v1/bookmarks/bulk

Apply a single action to up to 500 bookmarks in one request. Use this to batch-tag, move, archive, favorite, or delete bookmarks without looping over individual endpoints.
bookmarkIds
string[]
required
Array of bookmark UUIDs to act on. Maximum 500 items.
action
string
required
The operation to perform. See the table below for available actions and their extra fields.
tagNames
string[]
Required when action is tag. Tag names to add to all selected bookmarks.
groupIds
string[]
Required when action is move. Group UUIDs to move all selected bookmarks into.
delete_permanent and export cannot be undone. Double-check your bookmarkIds array before issuing these actions.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks/bulk" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "bookmarkIds": [
      "e5f6a7b8-c9d0-1234-efab-345678901234",
      "f6a7b8c9-d0e1-2345-fabc-456789012345"
    ],
    "action": "tag",
    "tagNames": ["archived-project"]
  }'
{
  "affected": 2
}

GET /api/v1/bookmarks/export

Export your entire bookmark library as a JSON file. The response body is a JSON array of bookmark objects in the same shape as the list endpoint.
curl "https://api.bkmark.it/api/v1/bookmarks/export" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -o my-bookmarks.json
Returns 200 OK with Content-Type: application/json.

POST /api/v1/bookmarks/import

Import bookmarks from a supported format. You can migrate from a browser export, Pocket, Raindrop.io, or a previous Bkmark export.
format
string
required
Source format. One of: json (Bkmark export), html (browser bookmark export), pocket, raindrop.
data
string
required
The raw file contents as a string (JSON string or HTML string depending on format).
skipDuplicates
boolean
When true, bookmarks whose URLs already exist in your library are silently skipped instead of triggering a conflict error.
This endpoint is rate-limited to 5 imports per hour per user to protect system performance during large batch jobs.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks/import" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "format": "pocket",
    "data": "<html>...exported pocket HTML...</html>",
    "skipDuplicates": true
  }'
{
  "imported": 248,
  "skipped": 12,
  "failed": 0
}

GET /api/v1/bookmarks/trash

List soft-deleted bookmarks. Supports the same cursor-based pagination as the main list endpoint.
curl "https://api.bkmark.it/api/v1/bookmarks/trash?limit=25" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
{
  "data": [
    {
      "id": "b8c9d0e1-f2a3-4567-bcde-678901234567",
      "url": "https://old-resource.example.com/deprecated-guide",
      "title": "Deprecated Guide",
      "description": null,
      "type": "link",
      "source": "web",
      "isFavorite": false,
      "isArchived": false,
      "readAt": null,
      "tags": [],
      "groups": [],
      "createdAt": "2024-11-20T08:00:00.000Z",
      "updatedAt": "2025-03-28T17:44:00.000Z"
    }
  ],
  "nextCursor": null
}

GET /api/v1/bookmarks/trash-count

Return the number of bookmarks currently in trash. Useful for displaying a badge in your UI.
curl "https://api.bkmark.it/api/v1/bookmarks/trash-count" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
{
  "count": 7
}

POST /api/v1/bookmarks/:id/restore

Restore a soft-deleted bookmark from trash back to your active library. The bookmark’s original tags and group assignments are preserved.
id
string
required
The UUID of the trashed bookmark to restore.
curl -X POST "https://api.bkmark.it/api/v1/bookmarks/b8c9d0e1-f2a3-4567-bcde-678901234567/restore" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Returns 200 OK with the restored bookmark object.

DELETE /api/v1/bookmarks/:id/permanent

Permanently delete a specific bookmark. Unlike DELETE /bookmarks/:id, this endpoint always performs a hard delete regardless of query parameters. The bookmark is unrecoverable after this call.
id
string
required
The UUID of the bookmark to permanently delete.
This action is irreversible. The bookmark and all its associations (tags, group memberships) are removed permanently.
curl -X DELETE "https://api.bkmark.it/api/v1/bookmarks/b8c9d0e1-f2a3-4567-bcde-678901234567/permanent" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Returns 204 No Content on success.