Zendesk APIのべき等性キーを使用してチケットの重複を防ぐ方法

Stevia Putri
執筆者

Stevia Putri

最終更新 March 2, 2026

専門家による検証済み
Zendesk APIのべき等性キーを使用してチケットの重複を防ぐ方法のバナー画像

ネットワーク障害は発生するものです。APIリクエストがタイムアウトした場合、クライアントはリトライします。適切な保護手段がないと、そのリトライによって2枚目のチケット、3枚目のチケットが作成され、最終的に顧客はシステム内に3件の同一のサポートリクエストを持つことになります。べき等性キーは、同じキーを持つリクエストを繰り返しても、重複を作成せずに同じ結果が生成されるようにすることで、この問題を解決します。

Zendesk APIとの統合を構築している場合、べき等性キーの理解はオプションではありません。実際のお客様のデータを処理する本番環境対応のシステムには不可欠です。

べき等性キーは、応答をキャッシュすることでAPIリクエストの重複を防ぎます
べき等性キーは、応答をキャッシュすることでAPIリクエストの重複を防ぎます

べき等性キーとは何か、なぜ重要なのか?

べき等性キー(Idempotency Key)とは、クライアントがAPIリクエストに含める一意の識別子です。サーバーがリクエストを受信すると、そのキーを以前に見たことがあるかどうかを確認します。キーが新しい場合、リクエストは通常どおりに処理され、結果が保存されます。キーが存在する場合、操作を再実行せずに、保存された結果が返されます。

この概念は数学に由来し、べき等な操作は、1回実行しても複数回実行しても同じ結果を生成します。APIの用語では、同じべき等性キーを使用してチケットを5回投稿すると、チケットが1つだけ作成され、毎回同じ応答が返されるはずです。

これがZendeskにとって特に重要な理由を以下に示します。チケットの作成は、副作用のある書き込み操作です。各チケットは、通知、ルーティングルール、および潜在的なSLAタイマーをトリガーします。チケットを重複して作成すると、システムが乱雑になるだけではありません。エージェントの時間を浪費し、複数の確認応答を受け取る顧客を混乱させ、メトリックを歪めます。

べき等性が役立つ実際のシナリオ:

  • 支払いWebhook 決済プロバイダーがWebhookを送信して、失敗したトランザクションのチケットを作成します。Webhookはタイムアウト時にリトライします。べき等性がない場合、リトライごとに新しいチケットが作成されます。
  • 一括インポート 古いシステムからチケットを移行しています。インポートスクリプトがネットワークエラーに遭遇して再起動します。べき等性がない場合、レコードが重複します。
  • モバイルアプリ ユーザーがラグのために2回送信をタップします。べき等性がない場合、2つのチケットが作成されます。

信頼性の高いリトライロジックを手動で構築するのは複雑です。どのリクエストが成功したかを追跡し、部分的な失敗を処理し、分散システム全体の状態を調整する必要があります。べき等性キーは、この複雑さを本来あるべきAPIレイヤーにプッシュします。

これらのエッジケースを自分で処理せずにチケット作成を自動化したい場合は、当社のAIエージェントがZendesk統合の一部として、べき等性を自動的に管理します。

スーパーバイザーエージェントを構成するためのeesel AIダッシュボード
スーパーバイザーエージェントを構成するためのeesel AIダッシュボード

Zendeskのべき等性キーの実装方法

Zendeskは、単純なHTTPヘッダーを介してべき等性を実装します。これを使用するには、リクエストに一意の値を持つIdempotency-Keyヘッダーを含めます。

Idempotency-Key: {unique_key}

値は、最大255文字の任意の文字列にすることができます。Zendeskは、UUIDまたはその他のエントロピーの高い識別子を使用することをお勧めします。

べき等性キーを使用してリクエストを行うと、Zendeskの応答にはx-idempotency-lookupヘッダーが含まれます。

  • x-idempotency-lookup: miss このキーが認識されたのは初めてです。リクエストは通常どおりに処理されます。
  • x-idempotency-lookup: hit このキーは以前に使用されました。Zendeskは、元のリクエストからキャッシュされた応答を返します。

ここで重要なのは、Zendeskがべき等性キーを2時間保存することです。その期間が過ぎると、同じキーを持つリクエストは新しいものとして扱われます。これは、リトライロジックが有効期限を考慮する必要があることを意味します。昨日からのリクエストをリトライすると、重複が作成されます。

Zendeskは、同じべき等性キーを持つリクエストに同一のパラメータがあることも検証します。同じキーを異なる件名または説明で使用して送信すると、400エラーが発生します。

{ "error": "IdempotentRequestError", "description": "Request parameters don't match the given idempotency key" }

これにより、異なる操作間でキーが誤って使用されるのを防ぎます。また、異なるチケット間でキーを再利用するのではなく、個別の操作ごとに新しいキーを生成する必要があることも意味します。

重要な制限事項:べき等性キーは、チケットの一部として保存されません。後でチケットを取得しても、どのキーを使用して作成されたかはわかりません。この相関関係を追跡する必要がある場合は、独自のシステムに保存してください。

すべてのZendesk APIエンドポイントがべき等性をサポートしているわけではありません。主なユースケースは、チケットの作成(POST /api/v2/tickets.json)です。公式ドキュメントで使用している特定のエンドポイントを確認してください。

コードにべき等性キーを実装する

実際の実装について説明しましょう。ここではrequestsライブラリを使用してPythonを使用しますが、このパターンはどの言語にも適用できます。

ステップ1:一意のべき等性キーを生成する

最初のリクエストを行う前にべき等性キーを生成します。リトライ中ではありません。キーは、論理操作ごとに一意である必要があります。

import uuid idempotency_key = str(uuid.uuid4()) request_context = { 'idempotency_key': idempotency_key, 'payload': ticket_data, 'attempt': 0 }

UUIDv4または少なくとも128ビットのエントロピーを持つ別のランダムな文字列を使用します。タイムスタンプ、シーケンシャルID、またはペイロード自体のハッシュなどの予測可能なパターンは避けてください。これらは衝突したり、推測されたりする可能性があります。

ステップ2:APIリクエストにヘッダーを追加する

認証とともに、リクエストヘッダーにべき等性キーを含めます。

Pythonの例:

import requests import os subdomain = os.getenv('ZENDESK_SUBDOMAIN') email = os.getenv('ZENDESK_EMAIL') api_token = os.getenv('ZENDESK_API_TOKEN') url = f'https://{subdomain}.zendesk.com/api/v2/tickets.json' auth = (f'{email}/token', api_token) headers = { 'Content-Type': 'application/json', 'Idempotency-Key': idempotency_key } data = { 'ticket': { 'subject': '支払い失敗の通知', 'comment': {'body': '顧客の支払い方法が拒否されました'}, 'requester': {'email': 'customer@example.com'} } } response = requests.post(url, json=data, auth=auth, headers=headers)

cURLの例:

curl https://yourcompany.zendesk.com/api/v2/tickets.json \ -d '{"ticket": {"subject": "テストチケット", "comment": {"body": "これはテストです"}}}' \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \ -u your@email.com/token:your_api_token \ -X POST

JavaScript/Node.jsの例:

const response = await fetch('https://company.zendesk.com/api/v2/tickets.json', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + Buffer.from(`${email}/token:${token}`).toString('base64'), 'Idempotency-Key': idempotencyKey }, body: JSON.stringify(ticketData) });

ステップ3:応答とリトライを処理する

リトライロジックは、応答ステータスとヘッダーをチェックして、リトライするかどうかを判断する必要があります。

import time def create_ticket_with_retry(ticket_data, max_retries=3): idempotency_key = str(uuid.uuid4()) for attempt in range(max_retries + 1): headers = { 'Content-Type': 'application/json', 'Idempotency-Key': idempotency_key } response = requests.post( url, json=ticket_data, auth=auth, headers=headers ) # これがキャッシュされた応答かどうかを確認する lookup_status = response.headers.get('x-idempotency-lookup') if lookup_status == 'hit': print(f"リクエストはキャッシュされました(試行{attempt + 1}回目)") # 成功の場合 if response.status_code == 201: return response.json() # べき等の不一致 - リトライしないでください。これはロジックエラーです if response.status_code == 400 and 'IdempotentRequestError' in response.text: raise ValueError(f"べき等性キーの不一致:{response.json()['description']}") # レート制限 - 待機してリトライ if response.status_code == 429: retry_after = int(response.headers.get('Retry-After', 60)) time.sleep(retry_after) continue # サーバーエラー - 指数バックオフでリトライ if response.status_code in [500, 502, 503, 504]: if attempt < max_retries: backoff = (2 ** attempt) + (hash(idempotency_key) % 1000 / 1000) time.sleep(backoff) continue # クライアントエラー(4xx) - リトライしないでください response.raise_for_status() raise Exception("最大リトライ回数を超えました")

リトライロジックの重要なポイント:

  • 同じ論理操作のすべてのリトライで同じべき等性キーを再利用する
  • IdempotentRequestError400エラーが発生した場合はリトライしない これはコードのロジックバグを示しています
  • Retry-Afterヘッダーを使用してレート制限(429)を尊重する
  • APIへの負荷を回避するために、サーバーエラーには指数バックオフを使用する

ZendeskチケットAPI構造の詳細については、APIを使用してZendeskチケットを作成するに関するガイドをご覧ください。

本番環境実装のベストプラクティス

基本が機能したら、これらの本番環境対応のプラクティスを検討してください。

API応答シナリオを処理するためのリトライロジック決定木
API応答シナリオを処理するためのリトライロジック決定木

主要なストレージ戦略。 高ボリュームシステムの場合は、独自のデータベースまたはキャッシュでべき等性キーを追跡することをお勧めします。これにより、次のことが可能になります。

  • キーが期限切れになるかどうかを検出する(Zendeskの2時間のウィンドウ)
  • どの操作が成功または失敗したかを監査する
  • Zendeskを超えるカスタムの重複排除ロジックを実装する

Redisは、これに最適な選択肢です。エッジケースを回避するために、Zendeskの2時間のウィンドウよりもわずかに短いTTLを設定します。

import redis redis_client = redis.Redis(host='localhost', port=6379) redis_client.setex(f"zendesk:idempotency:{key}", 5400, response_data)

同時リクエストを処理する。 同じべき等性キーを持つ2つのリクエストが同時に到着した場合、Zendeskは1つを処理し、もう1つにキャッシュされた結果を返します。ただし、クライアントで競合状態が発生する可能性があります。これが懸念される場合は、アプリケーションレイヤーでリクエストの重複排除を実装します。

リクエストのフィンガープリント。 異なるパラメータでキーを誤って再利用するバグをキャッチするには、リクエストペイロードをハッシュし、べき等性キーとともに保存します。送信する前に、ハッシュが一致することを確認します。

import hashlib import json def get_request_fingerprint(payload): return hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest() fingerprint = get_request_fingerprint(ticket_data) store_key_with_fingerprint(idempotency_key, fingerprint) if get_fingerprint_for_key(idempotency_key) != fingerprint: raise ValueError("既存のべき等性キーのペイロードが変更されました")

ロギングと監視。 ログでべき等性キーの使用状況を追跡します。

  • 各リクエストのキーとx-idempotency-lookupステータスをログに記録する
  • hit応答の割合が高い場合にアラートを出す(過剰なリトライを示している可能性があります)
  • IdempotentRequestErrorを監視する(バグを示します)

実装のテスト。 べき等性ロジックを検証するテストを作成します。

def test_duplicate_request_returns_same_ticket(): key = str(uuid.uuid4()) # 最初の要求 response1 = create_ticket(ticket_data, idempotency_key=key) ticket_id = response1['ticket']['id'] # 同じキーを持つ2番目の要求 response2 = create_ticket(ticket_data, idempotency_key=key) assert response2['ticket']['id'] == ticket_id assert response2.headers['x-idempotency-lookup'] == 'hit'

よくある間違いとその回避方法

経験豊富な開発者でも、べき等性を実装する際にこれらのエラーを犯します。

予測可能なキーパターンを使用する。 タイムスタンプ、シーケンシャルID、またはペイロードの単純なハッシュは、衝突したり、推測されたりする可能性があります。常にUUIDv4のような暗号化されたランダムな値を使用してください。

リトライ時に新しいキーを生成する。 重要なのは、リトライに同じキーを使用することです。試行ごとに新しいUUIDを生成すると、重複を防ぐのではなく、重複が作成されます。

2時間の有効期限を無視する。 リトライロジックが2時間以上続く場合(たとえば、長時間の停止が原因)、べき等性キーは機能しなくなります。長時間実行されるプロセスでは、独自の重複排除レイヤーを実装します。

パラメータの不一致エラーを処理しない。 IdempotentRequestErrorが発生した場合、通常はコードにバグがあります。異なるデータでキーを再利用しています。これらを積極的にログに記録し、根本原因を修正します。

エラー応答を誤ってキャッシュする。 一部の実装では、5xxエラーを含むすべての応答をキャッシュします。これは、一時的なサーバーエラーが「スタック」し、すべてのリトライが同じエラーを返すことを意味します。成功した応答(2xxステータスコード)のみをキャッシュします。

同時実行環境での競合状態。 適切なロックがないと、2つのスレッドがキーの存在を確認し、両方ともキーが見つからないことを確認し、両方ともリクエストを送信する可能性があります。大量のボリュームを処理する場合は、アトミック操作または分散ロックを使用します。

複雑さを排除してチケット作成を自動化する

API統合の構築と維持には時間がかかります。認証、エラーリトライロジック、レート制限、べき等性、およびAPIの変更に伴う継続的なメンテナンスを処理する必要があります。

カスタム統合を構築するのではなく、チケット作成を自動化することが目標である場合は、実際にコードを記述する必要があるかどうかを検討してください。eesel AIのようなツールを使用すると、開発作業なしでチケットの作成と応答を処理できます。

顧客への推奨される返信を示すeesel AI Copilotサイドバー
顧客への推奨される返信を示すeesel AI Copilotサイドバー

違いは次のとおりです。APIアプローチでは、人間が応答するチケットを作成するスクリプトを記述します。AIエージェントを使用すると、ビジネスを理解し、作成から解決までのチケットライフサイクル全体を処理するようにシステムをトレーニングします。Zendeskアカウントに接続すると、過去のチケット、ヘルプセンターの記事、およびマクロから学習します。

段階的なロールアウトモデルは、AIがレビュー用の応答を下書きすることから始まり、それが証明されるにつれて完全な自動化に拡張されることを意味します。作成を自動化するだけでなく、チケットのボリュームを削減したいと考えているチームにとって、これはカスタムAPI開発よりも多くの場合、より迅速な結果をもたらします。

AI Copilotは、エージェントが送信する前にレビューする返信を下書きすることで、べき等なリトライロジックを自分で構築する複雑さなしにAI支援を提供することもできます。

よくある質問

いいえ。べき等性キーは、チケットの作成など、リソースを作成する書き込み操作で最も重要です。読み取り操作(GETリクエスト)は、本質的にべき等です。更新操作は、重複が問題を引き起こすかどうかに応じて、必要になる場合とそうでない場合があります。
リクエストは通常どおりに処理されますが、リトライによってチケットが重複して作成されます。ネットワークが信頼性が高く、単純なリトライロジックを使用している場合は、気付かないかもしれません。ただし、本番システムでは、自動化されたチケット作成にはべき等性キーを使用する必要があります。
はい、2時間後、Zendeskはそのキーを新しいものとして扱います。より長い期間が必要な場合は、データベースで作成されたチケットを追跡する独自の重複排除レイヤーを実装してください。
高ボリュームシステムの場合は、はい。キーを保存すると、操作を監査したり、有効期限の問題を検出したり、カスタムの重複排除を実装したりできます。単純な統合の場合は、Zendeskのストレージのみに依存する場合があります。
このエラーは、異なるリクエストパラメータでキーを再利用していることを意味します。リトライ間でペイロードが変更されるバグがないかコードを確認してください。エラーをログに記録し、根本原因を修正します。これらのエラーをリトライしないでください。
特定のエンドポイントのドキュメントを確認してください。一括操作には、部分的な失敗を処理するための独自のセマンティクスがあります。標準のべき等性キーパターンは、個々のチケット作成に適用され、必ずしも一括インポートには適用されません。

Share this article

Stevia Putri

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.

AIチームメイトを採用する準備はできましたか?

数分でセットアップ。クレジットカード不要。

無料で始める