v1 · preview

Try webhook signature, alert.created, location_withheld or 429.

↑ ↓ moveEnter openEsc close

How it works

Pagination

Lists are paged with limit and an opaque cursor: the response includes next_cursor, which you pass back as cursor.

On this page

The API’s lists (/v1/alerts, /v1/musters, /v1/workers, /v1/devices, /v1/events) are walked with a cursor.

How it works

ParameterWhat it is
limitItems per page, from 1 to 500. 100 by default.
cursorThe next_cursor from the previous page. On the first page, it isn’t sent.

Each response carries the page in data and a next_cursor:

Response
{
  "data": [ … ],
  "next_cursor": "eyJ0IjoiMjAyNi0wOS0yNFQxMTowNDoxMloifQ"
}

For the next page, repeat the same request with the same filters and cursor=<next_cursor>. When next_cursor is null, there are no more.

Walking a whole list

async function* fetchAll(path, filters = {}) {
  let cursor = null;
  do {
    const url = new URL(`https://sandbox.api.safeonuba.com${path}`);
    for (const [k, v] of Object.entries(filters)) url.searchParams.set(k, v);
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('cursor', cursor);

    const res = await fetch(url, { headers: { Authorization: `Bearer ${await safeOnubaToken()}` } });
    if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
    const page = await res.json();
    yield* page.data;
    cursor = page.next_cursor;
  } while (cursor);
}

for await (const alert of fetchAll('/v1/alerts', { status: 'unacknowledged' })) {
  console.log(alert.id, alert.title);
}

Order of each list

  • /v1/alerts: from the most recent to the oldest.
  • /v1/events: from the oldest to the most recent, in publication order. That way it replays in the same order in which it was sent.

What a page costs

A page of 500 items counts for more towards your query-time limit than one of 50 (see Rate limits). Ask for what you’re going to use.

The short lists that aren’t paginated (/v1/sites, /v1/sites/{id}/zones, /v1/musters/{id}/missing, /v1/positions/latest, /v1/webhooks) return everything in data, with no next_cursor.