本文へスキップ
Sursa Developers

ページネーション

Sursa APIのリストはカーソルでページ分割されます。最大limit件の項目を要求すると、レスポンスで次のページの取得方法がわかります。オフセットを計算する必要はなく、その間にデータが変わっても、ページのあいだで項目が重複したり抜け落ちたりすることはありません。

パラメーター値
limit1ページあたりの項目数。通常は1〜200です。新しいリストのデフォルトは50です。各リストの範囲とデフォルトはリファレンスに記載されています。
cursor前のページのカーソル。最初のページでは省略します。

リストは、レスポンスの形に応じて、2つの方法のいずれかで次のカーソルを返します。どちらを使うかは、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が加わり、項目は元の場所に残ります。

配列を返すリスト

GET /v1/collectionsのように、JSON配列そのものを返すリストもいくつかあります。レスポンスの形を変えられないので、次のページはヘッダーで返されます。

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", …}, …]
  • rel="next"のLinkは次のページの完全なアドレスです。X-Next-Cursorは同じカーソルだけを含みます。
  • rel="next"のLinkもX-Next-Cursorもなければ、最後のページです。
  • limitを指定しないと、これらのリストは従来どおり、すべての項目を1つのレスポンスで返します。ページ分割するにはlimitを渡してください。カーソルはページサイズを覚えているので、次のリクエストではlimitを省略できます。
  • 例外はGET /v1/cardsです。常にページ単位で返し、デフォルトは200枚、limitを指定すると1000枚までです。そのため、limitを指定しない場合もX-Next-Cursorをたどってください。
// 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のときも含め、すべてのページで返されます。これを保存しておき、後で同じカーソルで再度要求すると、その後に発生したイベントを取得できます。フィードは、自分のペースで読めるキューです。
  • イベントは、それが表す変更から1秒ほどでフィードに現れ、すでに読み込まれたイベントより前に現れることはありません。
  • フィードには組織全体のイベントが入るため、読み取るにはadminロールとwebhooks:manageスコープを持つキーが必要です。

データウェアハウスにエクスポートするに、ポーリングループの完全な例があります。

カーソルのルール

  • カーソルは最大512文字の不透明な文字列です。形式は変わることがあるので、解析したり自分で組み立てたりしないでください。
  • カーソルは、1つのリストと1組のフィルターに属します。壊れたカーソル、別のリストのカーソル、異なるフィルターと一緒に送信したカーソルには、コードapi.cursor_invalidとともに400が返ります。
  • 各リストには一意のキーで終わる固定の並び順があるので、各項目はちょうど1つのページに現れます。
  • カーソルとともに追加されたリストは、合計件数を返しません。以前からtotalを返していたリストは、引き続き返します。合計が必要な場合は、読み進めながら項目を数えてください。

オフセット方式のページネーション

カーソルの導入前にoffsetを受け付けていた一部のリストは、既存の連携システムが動き続けるように、今も受け付けています。新しいコードではcursorを使ってください。offsetとcursorは組み合わせられません。両方を送信すると、コードvalidation.failedとともに422が返ります。