GuidesPagination

Pagination

All list endpoints use cursor-based pagination. This provides consistent results even when new records are added while you paginate.

Query Parameters

ParameterTypeDefaultDescription
limitinteger20Number of records per page (max 100)
cursorstringCursor from next_cursor in previous response

Response Format

{
  "object": "list",
  "data": [
    { "id": "job_01HV...", ... },
    { "id": "job_01HW...", ... }
  ],
  "has_more": true,
  "next_cursor": "job_01HW..."
}
FieldDescription
dataArray of records for this page
has_moretrue if more records exist beyond this page
next_cursorPass as cursor parameter to fetch the next page. null when has_more is false.

Example: Paginating All Jobs

# First page
curl "https://api.firsthandapi.com/v1/jobs?limit=10" \
  -H "Authorization: Bearer fh_live_..."
 
# Next page (use next_cursor from previous response)
curl "https://api.firsthandapi.com/v1/jobs?limit=10&cursor=job_01HW..." \
  -H "Authorization: Bearer fh_live_..."

TypeScript Example

async function getAllJobs(client: FirstHandClient) {
  const allJobs = [];
  let cursor: string | undefined;
 
  do {
    const page = await client.listJobs({ limit: 100, cursor });
    allJobs.push(...page.data);
    cursor = page.has_more ? page.next_cursor : undefined;
  } while (cursor);
 
  return allJobs;
}

Python Example

def get_all_jobs(client):
    jobs = []
    cursor = None
    while True:
        page = client.list_jobs(limit=100, cursor=cursor)
        jobs.extend(page["data"])
        if not page["has_more"]:
            break
        cursor = page["next_cursor"]
    return jobs

Endpoints That Support Pagination

EndpointSorted By
GET /v1/jobsCreated at (newest first)
GET /v1/jobs/:id/filesCreated at (newest first)
GET /v1/jobs/:id/submissionsCreated at (newest first)
GET /v1/webhook_endpointsCreated at (newest first)
GET /v1/api_keysCreated at (newest first)
GET /v1/billing/transactionsCreated at (newest first)
GET /v1/audit-eventsCreated at (newest first)

Why Cursor-Based?

Cursor-based pagination is more reliable than offset-based (?page=2) because:

  • No skipped or duplicated records when items are added during pagination
  • Consistent performance — cursors use indexed lookups, not OFFSET scans
  • Stable across concurrent writes — safe for real-time data

Filtering

Most list endpoints support filtering alongside pagination:

# List only completed jobs, 50 per page
curl "https://api.firsthandapi.com/v1/jobs?status=completed&limit=50" \
  -H "Authorization: Bearer fh_live_..."

Filters reduce the total result set before pagination is applied.