nodestash

Pagination

Navigate through large result sets with cursor-based pagination

All list endpoints use cursor-based pagination for consistent, efficient traversal of large datasets.

How It Works

Instead of page numbers, cursors point to a specific position in the result set. This avoids issues with data changing between page requests.

Query Parameters

ParameterTypeDefaultDescription
limitinteger25Number of results per page (max: 100)
cursorstringOpaque cursor from a previous response

Response Format

List responses include a pagination object in meta:

{
  "data": [...],
  "meta": {
    "request_id": "req_abc123def456ghi789jkl012",
    "pagination": {
      "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wMS0xNVQxMDozMDowMFoiLCJpZCI6ImN0XzVoSjNrTTlwUXJWd1h5WmFCMmNENCJ9",
      "has_more": true
    }
  }
}
FieldTypeDescription
next_cursorstring | nullCursor to fetch the next page, null if no more results
has_morebooleantrue if there are more results after this page

Basic Pagination

# First page
curl "https://api.nodestash.io/v1/contacts?limit=25" \
  -H "Authorization: Bearer $NODESTASH_API_KEY"

# Next page (use next_cursor from previous response)
curl "https://api.nodestash.io/v1/contacts?limit=25&cursor=eyJjcmVh..." \
  -H "Authorization: Bearer $NODESTASH_API_KEY"
// First page
const page1 = await client.contacts.list({ limit: 25 })
console.log(page1.data)                  // Contact[]
console.log(page1.pagination.has_more)   // true
console.log(page1.pagination.next_cursor) // "eyJjcmVh..."

// Next page
if (page1.pagination.has_more) {
  const page2 = await client.contacts.list({
    limit: 25,
    cursor: page1.pagination.next_cursor!,
  })
}

Manual Page-by-Page Loop

#!/bin/bash
cursor=""
page=1

while true; do
  if [ -z "$cursor" ]; then
    response=$(curl -s "https://api.nodestash.io/v1/contacts?limit=100" \
      -H "Authorization: Bearer $NODESTASH_API_KEY")
  else
    response=$(curl -s "https://api.nodestash.io/v1/contacts?limit=100&cursor=$cursor" \
      -H "Authorization: Bearer $NODESTASH_API_KEY")
  fi

  echo "Page $page: $(echo $response | jq '.data | length') contacts"

  has_more=$(echo $response | jq -r '.meta.pagination.has_more')
  cursor=$(echo $response | jq -r '.meta.pagination.next_cursor')

  if [ "$has_more" = "false" ]; then
    break
  fi

  page=$((page + 1))
done
let cursor: string | undefined
let page = 1

do {
  const result = await client.contacts.list({ limit: 100, cursor })
  console.log(`Page ${page}: ${result.data.length} contacts`)

  cursor = result.pagination.next_cursor ?? undefined
  page++
} while (cursor)

Auto-Pagination with Async Iterators

The TypeScript SDK provides a listAll() method that automatically handles pagination using async generators:

// Iterate through every contact — pagination is handled automatically
for await (const contact of client.contacts.listAll()) {
  console.log(`${contact.first_name} ${contact.last_name}`)
}

// With filters and custom page size
for await (const deal of client.deals.listAll({
  pipeline_id: 'pp_abc123',
  sort: '-value',
  limit: 100,
})) {
  console.log(`${deal.title}: ${deal.value} ${deal.currency}`)
}

// Collect all results into an array
const allContacts: Contact[] = []
for await (const contact of client.contacts.listAll()) {
  allContacts.push(contact)
}

listAll() fetches pages lazily — it only requests the next page when the current one is exhausted. This keeps memory usage low even for large datasets.

Combining Pagination with Filters

Filters and sorting work seamlessly with pagination:

curl "https://api.nodestash.io/v1/contacts?tags=vip&sort=-created_at&limit=50" \
  -H "Authorization: Bearer $NODESTASH_API_KEY"
const { data, pagination } = await client.contacts.list({
  tags: 'vip',
  sort: '-created_at',
  limit: 50,
})

Best Practices

  • Use listAll() in the SDK — it handles pagination automatically and is the simplest approach
  • Set a reasonable limit — use 100 for bulk operations, 25 for UI pagination
  • Don't store cursors long-term — cursors are opaque and may expire
  • Combine with filters — narrow your results before paginating to reduce total pages

On this page