Pagination
The Telesoft API uses cursor-based pagination to provide efficient and consistent access to large collections of resources. This documentation explains how to paginate through API results and provides best practices for handling paginated data.
Pagination Overview
When querying endpoints that return collections of resources (such as patients, diagnostics, or medical records), the Telesoft API paginates the results to ensure optimal performance. The pagination mechanism is designed to handle large data sets efficiently while providing a consistent user experience.
Key Characteristics
- Cursor-based: Our pagination uses cursors instead of page numbers to ensure consistency when the underlying data changes
- Resource-friendly: Pagination helps reduce server load and response sizes
- Stable ordering: Results maintain consistent ordering across pagination requests
- Forward and backward navigation: Support for navigating in both directions through result sets
How Pagination Works
When you make a request to an endpoint that returns a collection of resources, the response includes both the requested data and pagination metadata that allows you to navigate through the collection.
Pagination Response Format
{
"data": [
// Array of resource objects
{
"id": "pat_1a2b3c4d5e6f",
"name": "John Doe",
// Other resource properties
},
// More resource objects...
],
"pagination": {
"has_more": true,
"next_cursor": "eyJpZCI6InBhdF8xYTJiM2M0ZDVlNmYifQ==",
"prev_cursor": null,
"total_count": 157,
"page_size": 25
}
}
Pagination Field | Description |
---|---|
has_more | Boolean indicating if there are more results available |
next_cursor | Cursor to use when fetching the next page of results (null if there are no more results) |
prev_cursor | Cursor to use when fetching the previous page of results (null if this is the first page) |
total_count | The total number of items matching the query (may be approximate for very large datasets) |
page_size | The number of items returned in the current page |
⚠️ Important
Cursors are opaque tokens that should be treated as black boxes. Do not attempt to decode or modify cursor values, as their format may change without notice. Always use the exact cursor string returned by the API.
Paginating Through Results
Basic Pagination Parameters
When making requests to paginated endpoints, you can include the following query parameters:
Parameter | Description |
---|---|
limit | Number of items to return (max 100, default 25) |
cursor | Cursor for pagination (use the next_cursor or prev_cursor value from a previous response) |
direction | Direction to paginate: next (default) or prev |
Example: Retrieving the First Page
To retrieve the first page of results, simply make a request without a cursor:
// Using the Telesoft SDK
const telesoft = new TelesoftAI({
apiKey: 'YOUR_API_KEY',
environment: 'production'
});
// Get the first page of patients
const patientsPage = await telesoft.patients.list({
limit: 50,
order: 'created_at:desc'
});
console.log(`Showing ${patientsPage.data.length} of ${patientsPage.pagination.total_count} patients`);
console.log(`Has more: ${patientsPage.pagination.has_more}`);
console.log(`Next cursor: ${patientsPage.pagination.next_cursor}`);
Example: Retrieving Subsequent Pages
To retrieve the next page of results, use the next_cursor
from the previous response:
// Continue from the previous example
if (patientsPage.pagination.has_more) {
// Get the next page using the next_cursor
const nextPage = await telesoft.patients.list({
limit: 50,
cursor: patientsPage.pagination.next_cursor,
direction: 'next' // This is the default, so it could be omitted
});
console.log(`Showing next ${nextPage.data.length} patients`);
// To go back to the previous page
const prevPage = await telesoft.patients.list({
limit: 50,
cursor: nextPage.pagination.prev_cursor,
direction: 'prev'
});
}
Iterating Through All Results
In some cases, you may need to process all results across multiple pages. Here's how to iterate through all items efficiently:
Example: Automatic Pagination
// Using async iteration to process all patients
async function processAllPatients() {
let cursor = null;
let hasMore = true;
const limit = 100; // Max limit for efficiency
const processedIds = new Set();
while (hasMore) {
const response = await telesoft.patients.list({
limit,
cursor,
created_after: '2023-01-01T00:00:00Z' // Optional filtering
});
// Process each patient in this page
for (const patient of response.data) {
// Skip if we've already processed this patient (safety check)
if (processedIds.has(patient.id)) continue;
// Process the patient
await processPatient(patient);
// Mark as processed
processedIds.add(patient.id);
}
// Update pagination state for next iteration
hasMore = response.pagination.has_more;
cursor = response.pagination.next_cursor;
// Optional: Add delay between requests to avoid rate limiting
if (hasMore) {
await new Promise(resolve => setTimeout(resolve, 100));
}
}
console.log(`Processed ${processedIds.size} patients in total`);
}
// Function to process an individual patient
async function processPatient(patient) {
console.log(`Processing patient: ${patient.id} - ${patient.name}`);
// Your processing logic here
}
SDK Pagination Helpers
The Telesoft SDK provides helper methods to simplify pagination:
// Using the SDK's auto-pagination feature
const allPatients = await telesoft.patients.listAll({
created_after: '2023-01-01T00:00:00Z',
limit: 100,
maxPages: 10 // Optional: limit the maximum number of pages
});
console.log(`Retrieved ${allPatients.length} patients in total`);
// Using the SDK's iterator for more controlled pagination
const patientIterator = telesoft.patients.listAutoPaginate({
created_after: '2023-01-01T00:00:00Z',
limit: 100
});
let count = 0;
for await (const page of patientIterator) {
count += page.data.length;
console.log(`Processed page with ${page.data.length} patients`);
// You can break the loop at any point
if (count >= 500) break;
}
💡 Best Practice
For large datasets, it's better to use iterative pagination with controlled processing rather than loading all results into memory at once. This approach is more memory-efficient and allows you to process data incrementally.
Sorting and Pagination
Most paginated endpoints support sorting, which affects the order of results across pages. When implementing pagination, it's important to use consistent sorting parameters.
Specifying Sort Order
You can specify the sort order using the order
parameter:
// Sort by creation date in descending order (newest first)
const patients = await telesoft.patients.list({
order: 'created_at:desc',
limit: 50
});
// Sort by name in ascending order (A to Z)
const patientsAlphabetical = await telesoft.patients.list({
order: 'name:asc',
limit: 50
});
// Sort by multiple fields (primary: last_updated, secondary: name)
const patientsSorted = await telesoft.patients.list({
order: ['last_updated:desc', 'name:asc'],
limit: 50
});
Pagination with Sorting
⚠️ Important
When paginating through sorted results, it's crucial to maintain the same sort order across all requests. Changing the sort order between pagination requests can lead to unexpected results, including duplicated or missing items.
// Example of consistent sorting across paginated requests
async function fetchAllPatientsWithDiabetes() {
const sortOrder = 'last_visit:desc';
let cursor = null;
let hasMore = true;
const results = [];
while (hasMore) {
const response = await telesoft.patients.list({
filter: 'medical_history:contains:diabetes',
order: sortOrder, // Use the same sort order for all requests
cursor,
limit: 100
});
results.push(...response.data);
hasMore = response.pagination.has_more;
cursor = response.pagination.next_cursor;
}
return results;
}
Best Practices
Optimizing Pagination Performance
- Use appropriate limits: Set the
limit
parameter based on your application's needs. Higher limits mean fewer API calls but larger response payloads. - Implement lazy loading: For user interfaces, load additional pages only when needed rather than preloading all data.
- Cache results: Consider caching paginated results to reduce API calls, especially for data that doesn't change frequently.
- Use filtering: Apply appropriate filters to reduce the total dataset size before pagination.
Handling Edge Cases
- Empty result sets: When no items match your query, the response will contain an empty data array and pagination metadata with
has_more: false
andnext_cursor: null
. - Data changes during pagination: If new items are added or existing items are modified while you're paginating, cursor-based pagination ensures you won't miss or duplicate items.
- Cursor expiration: Cursors typically remain valid for 24 hours. If you attempt to use an expired cursor, the API will return an error.
// Example of handling empty results and expired cursors
async function getPatientPage(cursor) {
try {
const response = await telesoft.patients.list({
cursor,
limit: 50
});
if (response.data.length === 0) {
console.log('No matching patients found.');
}
return response;
} catch (error) {
if (error.code === 'invalid_cursor') {
console.error('The pagination cursor has expired. Starting a new pagination session.');
// Restart pagination without a cursor
return telesoft.patients.list({ limit: 50 });
}
throw error;
}
}
Advanced Pagination Features
Filtering with Pagination
Combine pagination with filtering to process specific subsets of data:
// Get all patients created in a specific date range
const patientsInDateRange = await telesoft.patients.list({
created_after: '2023-01-01T00:00:00Z',
created_before: '2023-02-01T00:00:00Z',
limit: 100
});
// Get all patients with a specific diagnosis
const patientsWithDiagnosis = await telesoft.patients.list({
filter: 'diagnoses:contains:J45.9', // ICD-10 code for asthma
limit: 100
});
// Combining multiple filters with pagination
const elderlyCovid = await telesoft.patients.list({
filter: [
'age:gte:65',
'diagnoses:contains:U07.1' // ICD-10 code for COVID-19
],
order: 'last_visit:desc',
limit: 50
});
Pagination with Include Options
Many API endpoints support including related resources in the response. This feature works with pagination:
// Get patients with their latest diagnostic results
const patientsWithDiagnostics = await telesoft.patients.list({
include: ['latest_diagnostic', 'primary_care_physician'],
limit: 25
});
// The response will include the related resources
console.log(patientsWithDiagnostics.data[0].latest_diagnostic);
console.log(patientsWithDiagnostics.data[0].primary_care_physician);
💡 Performance Tip
Using include
parameters can significantly reduce the number of API calls needed by including related data in a single request, but it may increase the response size. Use this feature judiciously based on your application's needs.