Перейти к содержанию
Sursa для разработчиков

Пагинация

Списки Sursa API разбиты на страницы с помощью курсора: вы запрашиваете до limit элементов, а ответ подсказывает, как получить следующую страницу. Вычислять смещения не нужно, и если данные тем временем меняются, элементы не повторяются и не теряются между страницами.

ПараметрЗначение
limitСколько элементов на странице, обычно от 1 до 200. У новых списков по умолчанию 50; диапазон и значение по умолчанию для каждого списка указаны в справочнике.
cursorКурсор с предыдущей страницы. Для первой страницы не передавайте его.

Список возвращает следующий курсор одним из двух способов — в зависимости от формы ответа. На странице каждой операции в справочнике API указано, какой из них она использует.

Списки с конвертом data

Списки, добавленные для публичного API, например лента событий, возвращают объект с элементами в data:

curl "https://api.sursa.com/v1/webhook-events?limit=2" \
  -H "Authorization: Bearer $SURSA_API_KEY"
{
  "data": [
    {"id": "evt_8a1f…", "type": "card.published", "created_at": "2026-10-24T10:00:00Z"},
    {"id": "evt_8a20…", "type": "card.updated", "created_at": "2026-10-24T10:00:03Z"}
  ],
  "next_cursor": "eyJ2IjoxLCJrIjpbMTA0Ml19",
  "has_more": true
}

Если has_more равно true, запросите следующую страницу, передав в cursor значение next_cursor и те же фильтры:

curl "https://api.sursa.com/v1/webhook-events?limit=2&cursor=eyJ2IjoxLCJrIjpbMTA0Ml19" \
  -H "Authorization: Bearer $SURSA_API_KEY"

Списки, которые появились до курсоров и возвращают объект, сохраняют собственный конверт (например, {"items": […], "total": 120}). Они получают next_cursor и has_more в том же объекте, а элементы остаются на прежнем месте.

Списки, которые возвращают массив

Несколько списков возвращают голый JSON-массив, например GET /v1/collections. Форма их ответа не может измениться, поэтому следующая страница передаётся в заголовках:

curl -i "https://api.sursa.com/v1/collections?limit=50" \
  -H "Authorization: Bearer $SURSA_API_KEY"
HTTP/1.1 200 OK
Link: <https://api.example.com/v1/collections?limit=50&cursor=eyJ2IjoxLCJrIjpbNTBdfQ>; rel="next"
X-Next-Cursor: eyJ2IjoxLCJrIjpbNTBdfQ

[{"id": 1, "name": "support", …}, …]
  • Link с rel="next" — полный адрес следующей страницы; X-Next-Cursor — тот же курсор отдельно.
  • Если нет ни Link с rel="next", ни X-Next-Cursor, это последняя страница.
  • Без limit такие списки, как и раньше, возвращают все элементы одним ответом. Чтобы читать их по страницам, передайте limit; курсор запоминает размер страницы, поэтому в следующем запросе limit можно не передавать.
  • Исключение — GET /v1/cards: он всегда возвращает страницы, по умолчанию по 200 карточек и до 1000 с limit, поэтому переходите по X-Next-Cursor даже без limit.
// Every item of a list that returns an array.
async function* listArray(path) {
  let next = `https://api.sursa.com${path}?limit=200`;
  while (next) {
    const response = await fetch(next, { headers: { Authorization: `Bearer ${process.env.SURSA_API_KEY}` } });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    yield* await response.json();
    const cursor = response.headers.get("X-Next-Cursor");
    next = cursor ? `https://api.sursa.com${path}?cursor=${encodeURIComponent(cursor)}` : null;
  }
}

Лента событий

Лента событий GET /v1/webhook-events — это журнал, поэтому страницы в ней устроены немного иначе:

  • События идут по возрастанию, сначала самые старые.
  • next_cursor возвращается на каждой странице, даже когда has_more равно false. Сохраните его и позже запросите ленту снова с тем же курсором, чтобы получить события, произошедшие с тех пор. Лента — это очередь, которую можно читать в своём темпе.
  • Событие появляется в ленте примерно через секунду после изменения, которое оно описывает, и никогда — раньше события, которое уже прочитано.
  • Лента содержит события всей организации, поэтому для её чтения нужен ключ с ролью admin и областью webhooks:manage.

Полный цикл опроса показан в руководстве Выгрузка в хранилище данных.

Правила для курсоров

  • Курсор — непрозрачная строка длиной до 512 символов. Не разбирайте и не собирайте его сами: его формат может измениться.
  • Курсор относится к одному списку и одному набору фильтров. Курсор, который повреждён, получен из другого списка или отправлен с другими фильтрами, возвращает 400 с кодом api.cursor_invalid.
  • У каждого списка фиксированный порядок сортировки, который заканчивается уникальным ключом, поэтому каждый элемент попадает ровно на одну страницу.
  • Списки, добавленные вместе с курсорами, не возвращают общее количество; списки, у которых раньше был total, его сохраняют. Если общее количество нужно, считайте элементы по ходу чтения.

Пагинация со смещением

Некоторые списки принимали offset до появления курсоров и принимают до сих пор, чтобы существующие интеграции продолжали работать. В новом коде предпочитайте cursor. offset и cursor нельзя сочетать: если передать оба, вернётся 422 с кодом validation.failed.