API Documentation
v1Build integrations with the ClipJot REST API.
On this page
Overview
The ClipJot API provides programmatic access to your bookmarks. All endpoints use POST method and accept/return JSON.
Base URL
https://clipjot.net/api/v1 Request Format
All requests must include:
-
Content-Type: application/jsonheader -
Authorization: Bearer <token>header (except public endpoints) - JSON request body
Authentication
Most API endpoints require authentication via Bearer token. Tokens can be obtained through OAuth login or by creating an API token in Settings.
Token Types
- Session tokens - Created during OAuth login, used by web UI and mobile apps
- API tokens - Created in Settings > API Tokens, for scripts and integrations
Token Scopes
-
read- Can read bookmarks and tags -
write- Can read, create, update, and delete bookmarks and tags
Example Request
curl -X POST https://your-domain.com/api/v1/bookmarks/list \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
/api/v1/user/profile Get current user profile
Returns the authenticated user's profile information including email, account type, and creation date.
Response
| Field | Type | Description |
|---|---|---|
email |
string |
User's email address |
is_premium |
boolean |
Whether user has premium account |
created_at |
string |
ISO 8601 timestamp of account creation |
curl -X POST https://your-domain.com/api/v1/user/profile \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{}' /api/v1/auth/invite Authenticate with invite code
Exchange an invite code for a session token. This is a public endpoint that does not require authentication.
Request Body
| Field | Type | Description |
|---|---|---|
code * |
string |
8-character invite code (uppercase alphanumeric) |
Response
| Field | Type | Description |
|---|---|---|
token |
string |
Session token for API authentication |
user |
object |
User object with id and email |
curl -X POST https://your-domain.com/api/v1/auth/invite \
-H "Content-Type: application/json" \
-d '{"code": "ABC12345"}' /api/v1/logout Logout and revoke session
Revokes the current session token, logging out the user.
Response
| Field | Type | Description |
|---|---|---|
logged_out |
boolean |
Always true on success |
message |
string |
Confirmation message |
curl -X POST https://your-domain.com/api/v1/logout \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}' Bookmarks
/api/v1/bookmarks/add Create a new bookmark
Add a new bookmark with optional title, comment, and tags. Tags are created automatically if they don't exist.
Request Body
| Field | Type | Description |
|---|---|---|
url * |
string |
The URL to bookmark |
title |
string |
Display title (optional) |
comment |
string |
Personal note or comment (optional) |
tags |
array |
List of tag names (optional) |
Response
| Field | Type | Description |
|---|---|---|
id |
integer |
Unique bookmark ID |
url |
string |
The bookmarked URL |
title |
string |
Display title |
comment |
string |
Personal note |
tags |
array |
List of tag objects |
created_at |
string |
ISO 8601 timestamp |
updated_at |
string |
ISO 8601 timestamp |
curl -X POST https://your-domain.com/api/v1/bookmarks/add \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/article",
"title": "Interesting Article",
"comment": "Read this later",
"tags": ["reading", "tech"]
}' /api/v1/bookmarks/edit Update an existing bookmark
Update the title, comment, or tags of an existing bookmark. Only provided fields are updated.
Request Body
| Field | Type | Description |
|---|---|---|
id * |
integer |
Bookmark ID to update |
title |
string |
New title (optional) |
comment |
string |
New comment (optional) |
tags |
array |
New tag list (replaces existing tags) |
Response
| Field | Type | Description |
|---|---|---|
id |
integer |
Bookmark ID |
url |
string |
The bookmarked URL |
title |
string |
Updated title |
comment |
string |
Updated comment |
tags |
array |
Updated tag list |
updated_at |
string |
ISO 8601 timestamp |
curl -X POST https://your-domain.com/api/v1/bookmarks/edit \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": 123,
"title": "Updated Title",
"tags": ["important", "work"]
}' /api/v1/bookmarks/delete Delete a bookmark
Permanently delete a bookmark by ID.
Request Body
| Field | Type | Description |
|---|---|---|
id * |
integer |
Bookmark ID to delete |
Response
| Field | Type | Description |
|---|---|---|
deleted |
boolean |
Always true on success |
curl -X POST https://your-domain.com/api/v1/bookmarks/delete \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": 123}' /api/v1/bookmarks/search Search bookmarks
Search bookmarks by query string with pagination. Searches URL, title, and comment fields.
Request Body
| Field | Type | Description |
|---|---|---|
query |
string |
Search query (searches URL, title, comment) |
tag |
string |
Filter by tag name |
page |
integer |
Page number (default: 1) |
per_page |
integer |
Results per page (default: 50, max: 100) |
Response
| Field | Type | Description |
|---|---|---|
bookmarks |
array |
List of bookmark objects |
total |
integer |
Total matching bookmarks |
page |
integer |
Current page number |
per_page |
integer |
Results per page |
has_more |
boolean |
Whether more results exist |
curl -X POST https://your-domain.com/api/v1/bookmarks/search \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "python tutorial",
"page": 1,
"per_page": 20
}' /api/v1/bookmarks/list List all bookmarks
Get all bookmarks with cursor-based pagination. Use for full sync or bulk operations.
Request Body
| Field | Type | Description |
|---|---|---|
cursor |
string |
Pagination cursor from previous response |
limit |
integer |
Max results (default: 100, max: 500) |
Response
| Field | Type | Description |
|---|---|---|
bookmarks |
array |
List of bookmark objects |
has_more |
boolean |
Whether more results exist |
next_cursor |
string |
Cursor for next page (if has_more is true) |
curl -X POST https://your-domain.com/api/v1/bookmarks/list \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"limit": 100}' /api/v1/bookmarks/sync Incremental sync with long polling
Get new bookmarks since a cursor position. Supports long polling to wait for changes.
Request Body
| Field | Type | Description |
|---|---|---|
cursor |
integer |
Last seen bookmark ID (0 for initial sync) |
limit |
integer |
Max results (default: 50, max: 100) |
wait |
boolean |
Enable long polling (wait up to 30s for new data) |
Response
| Field | Type | Description |
|---|---|---|
bookmarks |
array |
New bookmarks since cursor |
cursor |
integer |
New cursor position |
has_more |
boolean |
Whether more results exist |
waited |
boolean |
Whether request waited (long polling) |
# Initial sync
curl -X POST https://your-domain.com/api/v1/bookmarks/sync \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"cursor": 0}'
# Long polling for changes
curl -X POST https://your-domain.com/api/v1/bookmarks/sync \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"cursor": 123, "wait": true}' Import & Export
/api/v1/export Export all bookmarks
Export all bookmarks as JSON. Includes tags for each bookmark.
Response
| Field | Type | Description |
|---|---|---|
bookmarks |
array |
All bookmarks with tags |
exported_at |
string |
ISO 8601 timestamp |
count |
integer |
Total bookmark count |
curl -X POST https://your-domain.com/api/v1/export \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}' > bookmarks.json /api/v1/import Import bookmarks
Import bookmarks from JSON. Supports merge (skip duplicates) or replace mode.
Request Body
| Field | Type | Description |
|---|---|---|
bookmarks * |
array |
Array of bookmark objects to import |
mode |
string |
'merge' (default) or 'replace' |
Response
| Field | Type | Description |
|---|---|---|
imported |
integer |
Number of bookmarks imported |
skipped |
integer |
Number of duplicates skipped |
errors |
array |
List of import errors |
curl -X POST https://your-domain.com/api/v1/import \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bookmarks": [
{"url": "https://example.com", "title": "Example", "tags": ["test"]}
],
"mode": "merge"
}' Errors
When an error occurs, the API returns a JSON object with error details:
{"error": "Human-readable message", "code": "ERROR_CODE"} | Code | HTTP Status | Description |
|---|---|---|
INVALID_TOKEN |
401 | The provided token is invalid, expired, or missing. |
PERMISSION_DENIED |
403 | The token does not have the required scope for this operation. |
VALIDATION_ERROR |
400 | The request body is missing required fields or contains invalid data. |
NOT_FOUND |
404 | The requested resource (bookmark, tag, etc.) was not found. |
RATE_LIMITED |
429 | Too many requests. Check the Retry-After header. |
LIMIT_EXCEEDED |
403 | Account limit reached (e.g., max bookmarks for free tier). |
Rate Limits
The API is rate limited to 100 requests per 60 seconds per token.
When rate limited, the API returns a 429 status code. Check the Retry-After header for how long to wait.
Rate Limit Headers
-
X-RateLimit-Limit- Maximum requests per window -
X-RateLimit-Remaining- Requests remaining in current window -
X-RateLimit-Reset- Unix timestamp when the window resets -
Retry-After- Seconds to wait (only on 429 response)