cursors, page size, and reading only what changed
Pagination and filtering
Every list route is cursor-paged and returns the same envelope.
{
"data": [],
"next_cursor": "eyJzIjoiOEU0RjJBMUIifQ"
}A cursor is an opaque string. Send it back as ?cursor= to get the next page. When next_cursor comes back null, you have the whole list.
Walking a list
cursor=""
while :; do
page=$(curl -s "https://api.inittasks.com/v1/todos?limit=200${cursor:+&cursor=$cursor}" \
-H "Authorization: Bearer $INITTASKS_TOKEN")
printf '%s\n' "$page" | jq -c '.data[]'
cursor=$(printf '%s' "$page" | jq -r '.next_cursor // empty')
[ -n "$cursor" ] || break
donelimit defaults to 50 and caps at 200.
Never build a cursor, parse one, or store one as a bookmark between runs. It encodes a position in one ordering, and the ordering can change under you.
Reading only what changed
?updated_since= takes an RFC 3339 instant and filters on the server-side update time.
curl -s "https://api.inittasks.com/v1/todos?updated_since=2026-09-15T17:00:00Z" \
-H "Authorization: Bearer $INITTASKS_TOKEN"Keep the timestamp of your last successful sweep and pass it next time. A full re-read on a timer is the usual reason an integration hits a rate limit.
The update time is not encrypted, which is why the server can filter on it. Nothing about your content can be filtered server-side. See encryption.
Filtering on content
/v1/search and /v1/filters/{id}/todos decrypt inside your request and match there. They work, and they are not a database index. Expect them to cost more than a list, and expect account_too_large on very large accounts.
Ordering
Lists come back in the order the apps show them, which is a stored sort key rather than a timestamp. Two rows can share a position only until the next write settles it.
If you need a stable order for your own processing, sort on id after you have the whole list.
Next
- Rate limits for how often you may sweep.
- Reference for which routes are paged.