Skip to content

Pagination

Every list endpoint returns a page object alongside data:

json
{
  "data": [ /* story objects */ ],
  "page": {
    "page": 1,
    "page_size": 2,
    "offset": 0,
    "total_count": 2,
    "total_pages": 1,
    "has_more": false,
    "cursor": null,
    "next_cursor": null
  }
}

The page object

FieldTypeMeaning
pagenumberCurrent page number, starting at 1.
page_sizenumberRecords in this response. Maximum 100.
offsetnumberZero-based offset of the first record.
total_countnumberTotal records matching the query.
total_pagesnumberTotal pages at the current page_size.
has_morebooleanWhether further records exist. Prefer this over comparing page numbers.
cursorstring | nullCursor that produced this page, if any.
next_cursorstring | nullOpaque cursor for the next page. null when exhausted.

Two modes

Three parameters control paging: page, offset, and cursor. If cursor is supplied, offset is ignored.

Cursor — use this for walking a feed

Cursors are stable against inserts. New stories arriving mid-walk won't cause you to skip or repeat records. Use cursors for backfills and sequential ingestion.

bash
# First page
curl -sS -G "https://theneuralledger.com/v1/news" \
  -H "Authorization: Bearer $TNL_API_KEY" \
  --data-urlencode "page_size=100"

# Subsequent pages: pass page.next_cursor back as cursor
curl -sS -G "https://theneuralledger.com/v1/news" \
  -H "Authorization: Bearer $TNL_API_KEY" \
  --data-urlencode "page_size=100" \
  --data-urlencode "cursor=eyJvZmZzZXQiOjUwfQ"

Treat the cursor as opaque. Its encoding is not part of the contract and may change.

Offset — use this for jumpable UI

page or offset suits numbered pagination where a user clicks page 7 directly. On a fast-moving feed, offsets drift as new stories arrive — records can repeat or be skipped between requests.

bash
curl -sS -G "https://theneuralledger.com/v1/news" \
  -H "Authorization: Bearer $TNL_API_KEY" \
  --data-urlencode "page=3" \
  --data-urlencode "page_size=50"

Draining a feed correctly

javascript
async function* allStories(params = {}) {
  let cursor = null;
  do {
    const query = new URLSearchParams({ ...params, page_size: '100' });
    if (cursor) query.set('cursor', cursor);

    const response = await fetch(`https://theneuralledger.com/v1/news?${query}`, {
      headers: { Authorization: `Bearer ${process.env.TNL_API_KEY}` },
    });
    if (response.status === 429) throw new Error('Monthly limit exceeded');
    if (!response.ok) throw new Error(`TNL API ${response.status}`);

    const { data, page } = await response.json();
    yield* data;
    cursor = page.next_cursor;
  } while (cursor);
}

Stop on next_cursor === null, not on an empty data array — and note that each page costs one API call against your monthly allowance.

Pair pagination with field shaping

A 100-record page carrying full body, sources, and claims is large. Add fields or include to keep responses small. See Filtering & field shaping.

The Neural Ledger API