done.developers

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"
}
FieldWhat it holds
objectAlways list.
dataThe items on this page.
has_moretrue when there is another page.
next_cursorPass this as cursor to get the next page. It is null on the last page.

limit and cursor

Every list takes two query parameters:

ParameterWhat it does
limitHow many items to return, from 1 to 100. The default is 25.
cursorThe 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}.

On this page