Bookmark query syntax
The /api/v1/bookmarks endpoint supports a flexible, JSON-style query language that mirrors what the dashboard uses. This guide explains every knob you can turn so you can build reliable automations without guessing.
Pagination
limit— number of rows per page. Must be an integer between1and100(default50).page— 1-based page index (minimum1, default1).
Example: GET /api/v1/bookmarks?limit=25&page=2
Full-text search
Use the search parameter to perform a case-insensitive match across title, link, author, and notes.
/api/v1/bookmarks?search=machine%20learning
Filtering syntax
Filters use bracket notation inspired by Node/Express query parsers.
filter[field][operator]=value
filter[_or][0][field][operator]=value
filter[_and][1][field][operator]=value
Supported operators:
| Operator | Meaning | Example |
|---|---|---|
_eq | equals | filter[read][_eq]=false |
_neq | not equals | filter[source_type][_neq]=rss |
_contains | case-insensitive substring | filter[title][_contains]=queso |
_ncontains | does not contain | filter[notes][_ncontains]=TODO |
_null | is null | filter[source_id][_null]=true |
_nnull | is not null | filter[source_id][_nnull]=true |
_empty | empty string or null | filter[meta_image][_empty]=true |
_nempty | not empty | filter[meta_image][_nempty]=true |
_gt | greater than | filter[estimated_time][_gt]=10 |
_gte | greater or equal | filter[estimated_time][_gte]=5 |
_lt | less than | filter[estimated_time][_lt]=60 |
_lte | less or equal | filter[estimated_time][_lte]=30 |
Logical groups let you combine clauses:
filter[_or][0][read][_eq]=false
filter[_or][1][tags][_contains]=design
Sorting
Pass sort=<field> to order results. Prefix with - for descending (sort=-date_created).
Allowed fields: date_created, date_updated, title, read, estimated_time.
Unsupported fields return 400 Bad Request so you know immediately something is wrong.
Field selection
Use fields[]=field_name (repeatable) to trim the payload to specific attributes. All field names from the list below are supported:
id, date_created, date_updated, title, link, author, estimated_time, is_quote, is_til, tags, read, notes, snapshot, meta_image, source_type, source_id.
Example: /api/v1/bookmarks?fields[]=id&fields[]=tags returns only the bookmark IDs and tag arrays. When requesting exactly id + tags, you may bump limit up to 1000 for bulk tag syncs. (TODO: dedicated /tags endpoint so this shortcut can go away.)
Meta counters
Include meta=total_count and/or meta=filter_count to request extra metadata alongside data.
/api/v1/bookmarks?meta=total_count&meta=filter_count
Without explicit meta params the response defaults to total count (post-filter when filters/search are present, otherwise full count).
Aggregations
Set a single aggregate[function]=field argument to compute metrics instead of returning rows.
Supported combinations:
count— fields:id,read,source_type,estimated_timecountDistinct— same fields ascountsum,avg,min,max— field:estimated_time
Example (count unread bookmarks):
/api/v1/bookmarks?filter[read][_eq]=false&aggregate[count]=id
Aggregations respect search and filter clauses. Invalid fields or functions return 400 Bad Request.
Putting it together
Combined example that surfaces unread design articles saved this month, newest first:
/api/v1/bookmarks?
limit=25&
sort=-date_created&
filter[_and][0][read][_eq]=false&
filter[_and][1][tags][_contains]=design&
filter[_and][2][date_created][_gte]=2024-05-01
You can always test queries in the dashboard first, capture the network request, and reuse the query string in your automation.