Skip to main content

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 between 1 and 100 (default 50).
  • page — 1-based page index (minimum 1, default 1).

Example: GET /api/v1/bookmarks?limit=25&page=2

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:

OperatorMeaningExample
_eqequalsfilter[read][_eq]=false
_neqnot equalsfilter[source_type][_neq]=rss
_containscase-insensitive substringfilter[title][_contains]=queso
_ncontainsdoes not containfilter[notes][_ncontains]=TODO
_nullis nullfilter[source_id][_null]=true
_nnullis not nullfilter[source_id][_nnull]=true
_emptyempty string or nullfilter[meta_image][_empty]=true
_nemptynot emptyfilter[meta_image][_nempty]=true
_gtgreater thanfilter[estimated_time][_gt]=10
_gtegreater or equalfilter[estimated_time][_gte]=5
_ltless thanfilter[estimated_time][_lt]=60
_lteless or equalfilter[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_time
  • countDistinct — same fields as count
  • sum, 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.