All list endpoints return paginated results using cursor-based pagination. This approach is stable even when items are added or removed between requests.
How it works
Every list response includes pagination metadata:
{
"object": "list",
"results": [...],
"has_more": true,
"next_cursor": "eyJpZCI6MTIzNH0="
}
| Field | Type | Description |
|---|
results | array | The page of results. |
has_more | boolean | true if there are more results after this page. |
next_cursor | string | null | Pass this as cursor to get the next page. null when there are no more results. |
Paginating through results
To get all items, keep requesting with the cursor parameter until has_more is false:
# First page
curl "https://api.getmatter.com/public/v1/items?limit=50" \
-H "Authorization: Bearer $MATTER_TOKEN"
# Next page (use next_cursor from previous response)
curl "https://api.getmatter.com/public/v1/items?limit=50&cursor=eyJpZCI6MTIzNH0=" \
-H "Authorization: Bearer $MATTER_TOKEN"
import requests
url = "https://api.getmatter.com/public/v1/items"
headers = {"Authorization": f"Bearer {token}"}
params = {"limit": 50}
all_items = []
while True:
response = requests.get(url, headers=headers, params=params).json()
all_items.extend(response["results"])
if not response["has_more"]:
break
params["cursor"] = response["next_cursor"]
print(f"Fetched {len(all_items)} items")
Page size
Control page size with the limit parameter:
| Parameter | Default | Min | Max |
|---|
limit | 25 | 1 | 100 |
Incremental sync
Use updated_since to fetch only items that changed after a given timestamp. This is the most efficient way to keep a local copy of your library in sync.
# Get everything changed since your last sync
curl "https://api.getmatter.com/public/v1/items?updated_since=2026-03-29T00:00:00Z" \
-H "Authorization: Bearer $MATTER_TOKEN"
An item’s updated_at reflects any change to the item or its associated data — status changes, reading progress, favorites, tag additions/removals, new annotations, and content re-extraction all advance the timestamp. For inbox items that have never been interacted with, updated_at is the time the item appeared in your inbox.
The updated_since parameter filters by updated_at and works with all other filters (status, tag, etc.). Combine it with pagination to sync large deltas:
from datetime import datetime
last_sync = "2026-03-29T00:00:00Z"
params = {"updated_since": last_sync, "limit": 100}
changed_items = []
while True:
response = requests.get(url, headers=headers, params=params).json()
changed_items.extend(response["results"])
if not response["has_more"]:
break
params["cursor"] = response["next_cursor"]
# Save the current time as your new sync checkpoint
new_sync = datetime.utcnow().isoformat() + "Z"
Store the timestamp before you start syncing. If the sync fails partway through, you can retry from the same checkpoint without missing changes.
Multi-value filters
Several filter parameters accept comma-separated values to match any of the given options:
# Items in queue OR archive
curl "https://api.getmatter.com/public/v1/items?status=queue,archive" \
-H "Authorization: Bearer $MATTER_TOKEN"
# Articles OR podcasts
curl "https://api.getmatter.com/public/v1/items?content_type=article,podcast" \
-H "Authorization: Bearer $MATTER_TOKEN"
# Items with any of these tags
curl "https://api.getmatter.com/public/v1/items?tag=tag_n5j2x,tag_k3m9p" \
-H "Authorization: Bearer $MATTER_TOKEN"
Multi-value filters use OR logic — an item matches if it has any of the specified values.
Ordering
By default, items are ordered by updated_at descending (most recently changed first). This is optimized for incremental sync workflows.
You can also request position ordering to get items in the same order shown in the app:
# Queue in manual order (as arranged in the app)
curl "https://api.getmatter.com/public/v1/items?status=queue&order=library_position" \
-H "Authorization: Bearer $MATTER_TOKEN"
# All library items (queue + archive) in manual order
curl "https://api.getmatter.com/public/v1/items?order=library_position" \
-H "Authorization: Bearer $MATTER_TOKEN"
# Inbox in feed order
curl "https://api.getmatter.com/public/v1/items?order=inbox_position" \
-H "Authorization: Bearer $MATTER_TOKEN"
order value | Description |
|---|
updated | Sort by last-updated timestamp (default). Works with all status filters and updated_since. |
library_position | Sort by library position (manual queue ordering). Items without a library entry sort last. |
inbox_position | Sort by inbox feed position (newest first). Items not in the inbox sort last. |
No status filter is required for position orderings — items without a position sort last.
Position fields and incremental sync
Every item includes library_position and inbox_position fields, regardless of the order parameter used. This means you can use order=updated with updated_since for efficient incremental sync, and still use the position fields to sort items locally into app order:
# Incremental sync — fetches only changed items
params = {"updated_since": last_sync, "limit": 100}
changed = fetch_all_pages(params)
# Update local cache with changed items
for item in changed:
local_db[item["id"]] = item
# Display in app order using position fields
queue_items = sorted(
[i for i in local_db.values() if i["status"] == "queue"],
key=lambda i: i["library_position"] or 0,
reverse=True,
)
Annotations, tags, and other list endpoints always use updated_at ordering.