Pagination

How list endpoints page through results.
View as Markdown

Jelliu uses three paging styles, depending on the endpoint. Each is described below with its parameter names and bounds.

StyleParametersUsed by
Timestamp cursorlimit, cursorGET /api/agents, GET /api/calls
Page numberpage, limitGET /api/campaigns, GET /api/campaigns/{campaignId}/contacts, GET /api/contacts
Offsetlimit, offsetGET /api/widgets, GET /api/integrations, GET /api/mcp-servers, GET /api/exports, GET /api/agents/{agentId}/knowledge, GET /api/agents/{agentId}/tools

Parameters are query-string values. A value out of range is rejected with 400 VALIDATION_FAILED rather than silently clamped. See Errors.

Timestamp cursor

The cursor is an ISO 8601 timestamp: the created_at of the last item you received. The next page returns items created before it.

Agents

limit
integer

1 to 200. Defaults to 50.

cursor
string (ISO 8601 date-time)

Return agents created before this instant. Must be a UTC timestamp ending in Z, for example 2026-08-01T15:04:05.000Z.

search
string

Case-insensitive match on the agent name. 1 to 200 characters.

GET /api/agents returns { "data": [ ... ] } with no cursor field. To fetch the next page, pass the created_at of the last agent as cursor. When a page has fewer items than limit, you have reached the end.

curl -sS "https://api.jelliu.co/api/agents?limit=50&cursor=2026-08-01T15:04:05.000Z" \
-H "Authorization: Bearer $JELLIU_API_KEY"

Calls

limit
integer

1 to 100. Defaults to 50.

cursor
string

The nextCursor value from the previous page.

offset
integer

0 to 100000. Alternative to cursor for numbered pages. A non-zero offset takes precedence over cursor.

agentId
string (uuid)

Only calls handled by this agent.

campaignId
string (uuid)

Only calls from this campaign.

GET /api/calls returns the page together with its paging state:

{
"data": {
"calls": [ { "id": "...", "created_at": "..." } ],
"total": 1284,
"limit": 50,
"offset": 0,
"nextCursor": "2026-09-10T18:22:41.512Z"
}
}

nextCursor is null when the page holds fewer than limit calls. Pass it back as cursor to continue:

async function* allCalls(apiKey) {
let cursor = null;
do {
const url = new URL('https://api.jelliu.co/api/calls');
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const { data } = await res.json();
yield* data.calls;
cursor = data.nextCursor;
} while (cursor);
}

/api/calls has a stricter rate limit of 20 requests per minute. Use limit=100 when walking the full history. See Rate limits.

Page number

page
integer

1-based page number. 1 to 100000. Defaults to 1.

limit
integer

1 to 100. Defaults to 20 for campaigns and 50 for contacts.

Extra filters:

  • GET /api/campaigns/{campaignId}/contacts accepts status.
  • GET /api/contacts accepts search (1 to 200 characters) over phone, name and email.

Response shapes:

EndpointShape
GET /api/campaigns{ "data": [ ... ], "meta": { "page": 1, "limit": 20 } }
GET /api/campaigns/{campaignId}/contacts{ "data": { "contacts": [ ... ], "total": 0, "page": 1, "limit": 50 } }
GET /api/contacts{ "data": { "contacts": [ ... ], "total": 0, "page": 1, "limit": 50 } }

Contact lists report total, so you can compute the number of pages. The campaign list does not; stop when a page returns fewer than limit items.

Offset

limit
integer

1 to 100. Defaults to 50.

offset
integer

Number of items to skip. 0 to 100000. Defaults to 0.

curl -sS "https://api.jelliu.co/api/widgets?limit=50&offset=50" \
-H "Authorization: Bearer $JELLIU_API_KEY"

Stop when a page returns fewer than limit items.

Endpoints without paging

Some lists are small and take no paging parameters. For example, GET /api/webhooks returns up to 100 webhooks, newest first. GET /api/webhooks/{webhookId}/delivery-logs accepts only limit (1 to 50, default 20) and returns the most recent delivery attempts.