Lists and pages
How list endpoints return pages, how to read the next one, and how to ask for related objects in full.
This page explains how every list endpoint pages its results and how to use limit, cursor and expand.
The list envelope
Every list endpoint answers the same envelope:
{
"object": "list",
"data": [
{ "id": "run_3WmK9pQa", "object": "scoring_run", "status": "running" }
],
"has_more": true,
"next_cursor": "eyJhdCI6IjIwMjYtMTAtMjJUMTY6MDI6NDdaIn0"
}| Field | What it holds |
|---|---|
object | Always list. |
data | The items on this page. |
has_more | true when there is another page. |
next_cursor | Pass this as cursor to get the next page. It is null on the last page. |
limit and cursor
Every list takes two query parameters:
| Parameter | What it does |
|---|---|
limit | How many items to return, from 1 to 100. The default is 25. |
cursor | The next_cursor from the previous page. Leave it out for the first page. |
A limit outside 1 to 100 is refused with 400 invalid_field.
# First page
curl "https://api.done.com/v1/people?limit=50" \
-H "Authorization: Bearer $DONE_API_KEY"
# Next page
curl "https://api.done.com/v1/people?limit=50&cursor=eyJhdCI6IjIwMjYtMTAtMjJUMTY6MDI6NDdaIn0" \
-H "Authorization: Bearer $DONE_API_KEY"Treat a cursor as opaque. Do not build one or change one. Send it back unchanged, with the same filters as the call that gave it to you.
Read every page by following next_cursor until has_more is false:
async function* allPages(path) {
let cursor = null;
do {
const url = new URL(`https://api.done.com/v1${path}`);
url.searchParams.set('limit', '100');
if (cursor) url.searchParams.set('cursor', cursor);
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.DONE_API_KEY}` },
});
const page = await response.json();
yield* page.data;
cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
}
for await (const person of allPages('/people')) {
console.log(person.id, person.name);
}Mind the rate limit when you read many pages.
Order and filters
Most lists return the newest items first. Scoring results come best fit first. Each list says its order in the reference.
Many lists also take filters, such as status on GET /scoring_runs, min_fit on GET /scoring_runs/{id}/results, and list, campaign and scout on GET /people. Filters combine: an item must match all you send.
expand
Related objects appear as an id string by default. Ask for one in full with expand, a comma-separated list of related objects:
curl "https://api.done.com/v1/scouts?expand=customer_profile" \
-H "Authorization: Bearer $DONE_API_KEY"You can expand up to 5 related objects in a call. Each object lists what it can expand under x-done-expandable in the reference. Today a scout can expand customer_profile, and a goal can expand scout and campaign. Only endpoints that list expand accept it: GET /scouts, GET /scouts/{id}, GET /goals and GET /goals/{id}.