Zendeskチケットのページネーション方法:完全な開発者ガイド

Stevia Putri
Written by

Stevia Putri

Reviewed by

Stanley Nicholas

Last edited 2026 3月 2

Expert Verified

Zendeskチケットのページネーション方法:完全な開発者ガイドのバナー画像

Zendeskとの連携を構築している場合、APIがチケットデータベース全体を一度に渡さないことにすぐに気づくでしょう。代わりに、ページネーションと呼ばれるメカニズムを通じて、データを小さく分割して提供します。これは仕様によるものです。ページネーションは、APIの応答性を維持し、数千(または数百万)のサポートチケットを処理する際のタイムアウトを防ぎます。

しかし、ここからが面白いところです。Zendeskは、データをページネーションする2つの異なる方法を提供しています。カーソルページネーションとオフセットページネーションです。1つは高速で、最新で、事実上無制限です。もう1つは、10,000件のレコードに制限されており、古いAPI設計からのいくつかの遺産を引き継いでいます。2023年8月以降、Zendeskはオフセット方式に厳格な制限を課すことで、開発者をカーソルページネーションに移行させています。

このガイドでは、動作するコード例とともに、両方のページネーションアプローチについて説明します。各メソッドをいつ使用するか、エッジケースを処理する方法、および回避すべき落とし穴について学びます。また、自分でページネーションロジックを記述せずにZendeskワークフローを自動化する簡単な方法があるはずだと考えている場合は、それについても説明します。

カーソルページネーションは、大規模なデータセットに対してスケーラブルなパスを提供しますが、オフセットページネーションは10,000件のレコードの上限によって制限されます。
カーソルページネーションは、大規模なデータセットに対してスケーラブルなパスを提供しますが、オフセットページネーションは10,000件のレコードの上限によって制限されます。

Zendesk APIのページネーションについて

コードに入る前に、ページネーションが存在する理由と、それがどのように機能するかを大まかに説明しましょう。

Zendesk APIは、パフォーマンス上の理由から、大きな結果セットを小さなページに分割します。1回のAPI呼び出しで100,000件のチケットをリクエストすると、ほとんどのシステムでタイムアウトまたはクラッシュが発生します。代わりに、ページ1をリクエストし、それらの結果を処理してから、ページ2をリクエストします。これをすべて取得するまで繰り返します。

エンドポイントによって、デフォルトのページサイズが異なります。

  • チケットとユーザー: 1ページあたり100アイテム
  • ヘルプセンターの記事: 1ページあたり30アイテム
  • 検索結果: 最大1ページあたり100アイテム

通常、制限内でページサイズを調整できますが、特定のエンドポイントの最大値を超えることはできません。

すべてのAPIリクエストは、レート制限に対してカウントされます。Zendeskでは、プランに応じて1分あたりのリクエスト数が制限されており、大規模なデータセットを取得する場合、ページネーションによってそのクォータをすぐに使い果たす可能性があります。良いニュースは、カーソルページネーションの方がオフセットページネーションよりも効率的であるため、メソッドを切り替えることで、APIの使用量を実際に削減できることです。

知っておくべき重要な変更点の1つは、2023年8月15日から、最初の10,000件のレコード(100ページ)を超えるオフセットベースのページネーションリクエストは、400 Bad Requestエラーを返すことです。10,000件を超えるレコードが必要な場合、カーソルページネーションが唯一のオプションになります。この変更の詳細については、Zendeskオフセットページネーションのお知らせをご覧ください。

カーソルページネーション:推奨される方法

カーソルページネーションは、ほとんどのリストエンドポイントでZendeskが推奨するアプローチです。これは、レコードを最初からカウントするのではなく、データセット内の位置を追跡するポインタ(カーソル)を使用します。これにより、APIがページを見つけるためにレコードをカウントしてスキップする必要がないため、大規模なデータセットでは大幅に高速になります。

最後に取得したレコードを追跡するためにポインタを使用することで、カーソルページネーションはデータセットのサイズに関係なく一貫したパフォーマンスを保証します。
最後に取得したレコードを追跡するためにポインタを使用することで、カーソルページネーションはデータセットのサイズに関係なく一貫したパフォーマンスを保証します。

カーソルページネーションの仕組み

カーソルページネーションを有効にするには、リクエストにpage[size]パラメーターを追加します。これにより、Zendeskにカーソルモードを使用することを示し、ページごとに返すアイテム数を指定します(ほとんどのエンドポイントで最大100)。

レスポンスには、次の2つのキーオブジェクトが含まれています。

  • meta: has_more(ブール値)、after_cursor、およびbefore_cursorが含まれています
  • links: 隣接するページのnextおよびprev URLが含まれています

一般的なレスポンスは次のようになります。

{
  "tickets": [
    { "id": 1, "subject": "Sample ticket" },
    { "id": 2, "subject": "Another ticket" }
  ],
  "meta": {
    "has_more": true,
    "after_cursor": "eyJvIjoibmljZV9pZCIsInYiOiJhV2tCQUFBQUFBQUEifQ==",
    "before_cursor": "eyJvIjoibmljZV9pZCIsInYiOiJhUzRCQUFBQUFBQUEifQ=="
  },
  "links": {
    "next": "https://example.zendesk.com/api/v2/tickets.json?page[size]=100&page[after]=eyJvIjoibmljZV9pZCIsInYiOiJhV2tCQUFBQUFBQUEifQ==",
    "prev": "https://example.zendesk.com/api/v2/tickets.json?page[size]=100&page[before]=eyJvIjoibmljZV9pZCIsInYiOiJhUzRCQUFBQUFBQUEifQ=="
  }
}

meta.has_moreがfalseになるまでページネーションを続けます。その時点で、すべてのレコードを取得しました。

カーソルページネーションを使用したPythonの例

Pythonとrequestsライブラリを使用した完全な動作例を次に示します。

import requests
import time

ZENDESK_SUBDOMAIN = 'your-subdomain'
ZENDESK_EMAIL = 'your-email@example.com'
ZENDESK_API_TOKEN = 'your-api-token'

BASE_URL = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json'
auth = (f'{ZENDESK_EMAIL}/token', ZENDESK_API_TOKEN)

def fetch_all_tickets():
    tickets = []
    url = BASE_URL
    params = {'page[size]': 100}  # Use cursor pagination with 100 items per page

    while url:
        response = requests.get(url, auth=auth, params=params)

        # Handle rate limiting
        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            print(f'Rate limited. Waiting {retry_after} seconds...')
            time.sleep(retry_after)
            continue

        response.raise_for_status()
        data = response.json()

        # Process tickets from this page
        for ticket in data['tickets']:
            tickets.append(ticket)
            print(f"Fetched ticket {ticket['id']}: {ticket['subject']}")

        # Check if there are more pages
        if data['meta']['has_more']:
            url = data['links']['next']
            params = None  # Next URL already includes all parameters
        else:
            url = None

    return tickets

if __name__ == '__main__':
    all_tickets = fetch_all_tickets()
    print(f'\nTotal tickets fetched: {len(all_tickets)}')

この例で注意すべき主な点は次のとおりです。

  • page[size]=100から始めて、カーソルページネーションを有効にします
  • レート制限(HTTP 429)を確認し、Retry-Afterヘッダーを尊重します
  • 最初の要求の後、後続のページにはlinks.next URLを直接使用します
  • ループはhas_moreがfalseになるまで続行されます

カーソルページネーションを使用したNode.jsの例

axiosを使用したNode.jsでの同じロジックを次に示します。

const axios = require('axios');

const ZENDESK_SUBDOMAIN = 'your-subdomain';
const ZENDESK_EMAIL = 'your-email@example.com';
const ZENDESK_API_TOKEN = 'your-api-token';

const BASE_URL = `https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json`;
const auth = Buffer.from(`${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}`).toString('base64');

async function fetchAllTickets() {
  const tickets = [];
  let url = BASE_URL;
  let params = { 'page[size]': 100 };

  try {
    do {
      const response = await axios.get(url, {
        headers: { Authorization: `Basic ${auth}` },
        params: params
      });

      const data = response.data;

      // Process tickets from this page
      for (const ticket of data.tickets) {
        tickets.push(ticket);
        console.log(`Fetched ticket ${ticket.id}: ${ticket.subject}`);
      }

      // Prepare for next page
      if (data.meta.has_more) {
        url = data.links.next;
        params = null; // Next URL includes all parameters
      } else {
        url = null;
      }

    } while (url);

    console.log(`\nTotal tickets fetched: ${tickets.length}`);
    return tickets;

  } catch (error) {
    if (error.response && error.response.status === 429) {
      const retryAfter = error.response.headers['retry-after'] || 60;
      console.log(`Rate limited. Retry after ${retryAfter} seconds`);
    } else {
      console.error('Error fetching tickets:', error.message);
    }
    throw error;
  }
}

fetchAllTickets();

オフセットページネーション:レガシーメソッド

オフセットページネーションは、Zendeskがまだサポートしているものの、推奨しなくなった古いアプローチです。これは、ページ番号を指定することで機能し、APIはそのオフセットに基づいて、データセットの先頭からどのレコードを返すかを計算します。

オフセットページネーションは、Zendesk APIが結果を返す前に先行するすべてのレコードをカウントする必要があるため、深くなるほど遅くなります。
オフセットページネーションは、Zendesk APIが結果を返す前に先行するすべてのレコードをカウントする必要があるため、深くなるほど遅くなります。

オフセットページネーションの仕組み

オフセットページネーションでは、pageパラメーターを使用して特定のページ番号をリクエストし、オプションでper_pageを使用して1ページあたりのアイテム数(最大100)を設定します。

レスポンスには以下が含まれます。

  • next_page: 次のページのURL。最後のページの場合はnull
  • previous_page: 前のページのURL。最初のページの場合はnull
  • count: データセット内のレコードの総数

一般的なレスポンスは次のようになります。

{
  "tickets": [
    { "id": 1, "subject": "Sample ticket" },
    { "id": 2, "subject": "Another ticket" }
  ],
  "count": 15420,
  "next_page": "https://example.zendesk.com/api/v2/tickets.json?page=2",
  "previous_page": null
}

オフセットページネーションを使用したPythonの例

オフセット方式を使用してページネーションを行う方法は次のとおりです。

import requests
import time

ZENDESK_SUBDOMAIN = 'your-subdomain'
ZENDESK_EMAIL = 'your-email@example.com'
ZENDESK_API_TOKEN = 'your-api-token'

BASE_URL = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json'
auth = (f'{ZENDESK_EMAIL}/token', ZENDESK_API_TOKEN)

def fetch_tickets_offset():
    tickets = []
    url = BASE_URL

    while url:
        response = requests.get(url, auth=auth)

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            time.sleep(retry_after)
            continue

        if response.status_code == 400:
            # You've hit the 10,000 record limit
            print('Error: Cannot paginate beyond 10,000 records with offset pagination')
            break

        response.raise_for_status()
        data = response.json()

        for ticket in data['tickets']:
            tickets.append(ticket)

        # Move to next page
        url = data['next_page']

    return tickets

注意すべき制限事項

オフセットページネーションには、Zendeskが段階的に廃止している理由を説明するいくつかの欠点があります。

  • 10,000件のレコードのハードリミット: オフセットページネーションを使用して10,000件を超えるレコードを取得することはできません。101ページ以降をリクエストしようとすると、400エラーが返されます。

  • パフォーマンスの低下: より深いページ(50ページ、90ページ)をリクエストすると、APIはすべての先行レコードをカウントしてスキップする必要があるため、応答に時間がかかります。

  • データの一貫性の欠如: ページネーション中にレコードが追加または削除された場合、重複が表示されたり、レコードが失われたりする可能性があります。これは、オフセットが現在のデータセットの状態に基づいて各リクエストに対して新たに計算されるために発生します。

  • カーソルページネーションでは合計数が表示されない: オフセットページネーションの1つの利点は、レコードの合計数であるcountを返すことです。カーソルページネーションはこれを提供しないため、合計数が必要な場合は、別のAPI呼び出しが必要になります。

カーソル対オフセット:どちらを使用すべきか?

ほとんどのユースケースでは、選択は簡単です。

機能カーソルページネーションオフセットページネーション
レコード制限無制限最大10,000
パフォーマンス一貫性がある(深いページでも高速)ページ番号が増加するにつれて低下する
利用可能な合計数いいえはい(countプロパティ)
任意のページへのジャンプ不可能可能
ページネーション中のデータの一貫性より良い重複/レコードの欠落が発生しやすい
Zendeskの推奨事項推奨レガシーサポートのみ

次の場合にカーソルページネーションを使用します。

  • 10,000件を超えるレコードが必要な場合
  • パフォーマンスが重要な場合(特に大規模なデータセットの場合)
  • ジャンプする必要なく、データを順番に処理する場合

次の場合にオフセットページネーションを使用します。

  • レコードの合計数が必要な場合
  • ユーザーが特定のページにジャンプできるUIを構築している場合
  • 小さなデータセット(10,000件未満のレコード)を扱っており、シンプルさが重要な場合

現在オフセットページネーションを使用しており、10,000件のレコード制限に達している場合は、カーソルページネーションへの移行は簡単です。主な変更点は次のとおりです。

  1. pageパラメーターをpage[size]に置き換えます
  2. next_pageがnullかどうかではなく、meta.has_moreを確認します
  3. next_pageの代わりに、次のページのURLにlinks.nextを使用します

一般的なページネーションの落とし穴と解決策

動作するコードがあっても、本番環境ではエッジケースが発生します。最も一般的な問題の処理方法を次に示します。

レート制限とカーソルの有効期限切れに対する積極的なエラー処理により、Zendeskデータ同期が信頼性が高く、完全な状態に保たれます。
レート制限とカーソルの有効期限切れに対する積極的なエラー処理により、Zendeskデータ同期が信頼性が高く、完全な状態に保たれます。

レート制限の処理

レート制限を超えると、ZendeskはHTTP 429を返します。レスポンスには、待機する秒数を示すRetry-Afterヘッダーが含まれています。APIを繰り返し呼び出すのではなく、常に指数バックオフを実装してください。

import time

def make_request_with_backoff(url, auth, max_retries=5):
    for attempt in range(max_retries):
        response = requests.get(url, auth=auth)

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            # Exponential backoff: wait longer with each retry
            wait_time = retry_after * (2 ** attempt)
            time.sleep(wait_time)
            continue

        return response

    raise Exception('Max retries exceeded')

空のページの処理

場合によっては、has_moreがtrueであったにもかかわらず、次のリクエストがレコードを返さない空のページが発生することがあります。これは、前のページの最後のレコードがデータセット全体の最後のレコードであった場合に発生する可能性があります。この場合、以前のafter_cursor値を将来の使用のために保存します。

カーソルの有効期限

Export Search Resultsエンドポイントの場合、カーソルは1時間後に期限切れになります。処理にそれ以上の時間がかかる場合は、エクスポートを再開するか、データをより迅速に処理する必要があります。

Search APIの制限事項

Search APIには、独自のページネーションの癖があります。

  • クエリあたりの最大結果数は合計1,000件
  • 1ページあたりの最大結果数は100件
  • オフセットページネーションのみを使用
  • ページ11(1ページあたり100件の結果)をリクエストすると、422エラーが返されます

1,000件を超える検索結果が必要な場合は、代わりにExport Search Resultsエンドポイントを使用してください。このエンドポイントはカーソルページネーションをサポートし、1ページあたり最大1,000件のレコードを返します。詳細については、Zendesk Search APIドキュメントを参照してください。

APIなしでZendeskワークフローを自動化する

適切なページネーション、エラー処理、およびレート制限を備えたカスタムAPI連携を構築するには、多大な開発努力が必要です。コードを記述し、ZendeskがAPIを更新する際にそれを維持し、これまで説明したすべてのエッジケースを処理する必要があります。

多くのチームにとって、より簡単な方法があります。eesel AIは、Zendeskアカウントに直接接続し、すべてのデータ取得を自動的に処理します。ページネーションロジックを記述する代わりに、ビジュアルインターフェイスを通じて実行したいことを構成します。

Zendesk ChatGPT連携のためのeesel AIシミュレーション結果のスクリーンショット。予測される自動化率と、実際の顧客チケットに対するAI応答の例が表示されています。
Zendesk ChatGPT連携のためのeesel AIシミュレーション結果のスクリーンショット。予測される自動化率と、実際の顧客チケットに対するAI応答の例が表示されています。

仕組みは次のとおりです。

  • 数分でeesel AIをZendeskアカウントに接続します
  • AIは、過去のチケット、ヘルプセンターの記事、およびマクロから学習します
  • プレーンな英語で自動化ルールを定義します(コードは不要)
  • eesel AIは、すべてのAPI呼び出し、ページネーション、およびデータ処理を処理します

チケットのルーティング、エージェントの応答のドラフト作成、受信チケットのタグ付けと優先順位付け、およびレポートの生成を自動化できます。ページネーションコードを1行も記述せずに。

カスタム連携が必要なチームにとって、Zendesk APIは依然として適切な選択肢です。ただし、ワークフローを自動化し、効率を向上させることが目標である場合は、eesel AIのようなツールを使用すると、より迅速に目標を達成できます。

今すぐZendeskワークフローの自動化を開始する

ページネーションは、Zendesk APIを使用する際の基本的な概念です。カーソルページネーションは、より優れたパフォーマンスとレコード制限がないため、最新の連携のほとんどで明確な選択肢となります。オフセットページネーションは、小さなデータセットや、レコードの合計数が必要な場合に依然として役立ちますが、10,000件のレコード制限は、大規模なデータ取得には適していないことを意味します。

このガイドのコード例は、独自のプロジェクトでページネーションを実装するための確固たる基盤となるはずです。レート制限を適切に処理し、空のページのようなエッジケースに注意し、特定のユースケースに合ったページネーション方法を選択することを忘れないでください。

API開発を完全にスキップして、今すぐZendeskワークフローの自動化を開始したい場合は、eesel AIをお試しください。技術的な複雑さを処理するため、より優れたカスタマーサポートの提供に集中できます。

よくある質問

はい、カーソルとオフセットのページネーションは、ユーザー、組織、チケットなど、ほとんどのZendesk APIエンドポイントで一貫して機能します。同じpage[size]パラメーターで、サポートされているすべてのエンドポイントでカーソルページネーションが有効になります。
カーソルページネーションでは、ハードリミットはありません。チケットデータベース全体を取得できます。オフセットページネーションでは、10,000件のレコード(1ページあたり100件のレコードで100ページ)に制限されます。
標準のSearch APIはオフセットページネーションのみを使用し、最大1,000件の結果を返します。より大きな結果セットの場合は、カーソルページネーションをサポートするExport Search Resultsエンドポイントを使用してください。
HTTP 429レスポンスに注意し、Retry-Afterヘッダーを尊重してください。レート制限に繰り返し達しないように、指数バックオフを実装してください。
チケット、ユーザー、組織など、ほとんどのリストエンドポイントはカーソルページネーションをサポートしています。確認するには、特定のエンドポイントのドキュメントを確認してください。カーソルページネーションについて言及されていない場合、そのエンドポイントはおそらくオフセットページネーションのみをサポートしています。
カーソルページネーションのレスポンスには、合計数は含まれていません。レコードの総数が必要な場合は、カウントエンドポイント(/api/v2/tickets/count.jsonなど)への個別の呼び出しを行うことができます。

この記事を共有

Stevia undefined

Article by

Stevia Putri

Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.