Skip to main content
The Untether Labs API uses cursor-based pagination for most endpoints which return lists of items. This approach provides efficient and consistent navigation through result sets.

Pagination Structure

All paginated endpoints return responses in the following format:
Paginated Response Structure
{
    "items": [
        // Array of returned items
    ],
    "cursor": "<string>"
}

Response Fields

items
array
required
An array containing the requested data items for the current page
cursor
string
required
A string token for fetching the next page, or null if this is the last page
The cursor value should be treated as an opaque string. The format is subject to change without notice, clients should not attempt to decode or modify it.

Making Paginated Requests

Initial Request

Start by making a request to any paginated endpoint without a cursor parameter:
Initial Paginated Request
curl -X GET --location "https://app.untetherlabs.com/api/v1/pay-codes" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"
Initial Response
{
    "items": [
        {
            "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
            "name": "Overtime",
            "shorthandName": "OT",
            "hexColor": "#f97316",
            "type": "hours",
            "value": 1.5
        }
        // ... more items
    ],
    "cursor": "my-opaque-cursor"
}

Subsequent Requests

To fetch the next page, include the previous cursor value as a query parameter:
Next Page Request
curl -X GET --location "https://app.untetherlabs.com/api/v1/timekeeping/timecards?cursor=my-opaque-cursor" \
  -H "Authorization: Bearer {ACCESS_TOKEN}"

Last Page Detection

When you reach the last page, the cursor will be null:
Final Page Response
{
    "items": [
        {
            "id": "79208585-e4d2-4142-aafd-e76b851ffb88",
            "name": "Regular",
            "shorthandName": "REG",
            "hexColor": "#f97316",
            "type": "hours",
            "value": 1
        }
    ],
    "cursor": null
}

Best Practices

  • Always treat cursor values as opaque strings
  • Process items in batches rather than loading all pages at once for large datasets
  • Consider implementing pagination limits in your application to avoid memory issues
Page counts are not currently provided in pagination responses. This may change (per-endpoint) in the future.

Implementation Examples

Below are basic examples of how to iterate through pages of a paginated endpoint in JavaScript and Python.
async function fetchAllItems(endpoint, accessToken) {
    const allItems = [];
    let cursor = null;

    do {
        const url = new URL(`https://app.untetherlabs.com/api${endpoint}`);
        if (cursor) {
            url.searchParams.set('cursor', cursor);
        }

        const response = await fetch(url, {
            headers: {
                Authorization: `Bearer ${accessToken}`,
            },
        });

        const data = await response.json();
        allItems.push(...data.items);
        cursor = data.cursor;
    } while (cursor !== null);

    return allItems;
}

// Usage
const allPayCodes = await fetchAllItems('/v1/pay-codes', accessToken);