ネットワーク障害は発生するものです。APIリクエストがタイムアウトした場合、クライアントはリトライします。適切な保護手段がないと、そのリトライによって2枚目のチケット、3枚目のチケットが作成され、最終的に顧客はシステム内に3件の同一のサポートリクエストを持つことになります。べき等性キーは、同じキーを持つリクエストを繰り返しても、重複を作成せずに同じ結果が生成されるようにすることで、この問題を解決します。
Zendesk APIとの統合を構築している場合、べき等性キーの理解はオプションではありません。実際のお客様のデータを処理する本番環境対応のシステムには不可欠です。
べき等性キーとは何か、なぜ重要なのか?
べき等性キー(Idempotency Key)とは、クライアントがAPIリクエストに含める一意の識別子です。サーバーがリクエストを受信すると、そのキーを以前に見たことがあるかどうかを確認します。キーが新しい場合、リクエストは通常どおりに処理され、結果が保存されます。キーが存在する場合、操作を再実行せずに、保存された結果が返されます。
この概念は数学に由来し、べき等な操作は、1回実行しても複数回実行しても同じ結果を生成します。APIの用語では、同じべき等性キーを使用してチケットを5回投稿すると、チケットが1つだけ作成され、毎回同じ応答が返されるはずです。
これがZendeskにとって特に重要な理由を以下に示します。チケットの作成は、副作用のある書き込み操作です。各チケットは、通知、ルーティングルール、および潜在的なSLAタイマーをトリガーします。チケットを重複して作成すると、システムが乱雑になるだけではありません。エージェントの時間を浪費し、複数の確認応答を受け取る顧客を混乱させ、メトリックを歪めます。
べき等性が役立つ実際のシナリオ:
- 支払いWebhook 決済プロバイダーがWebhookを送信して、失敗したトランザクションのチケットを作成します。Webhookはタイムアウト時にリトライします。べき等性がない場合、リトライごとに新しいチケットが作成されます。
- 一括インポート 古いシステムからチケットを移行しています。インポートスクリプトがネットワークエラーに遭遇して再起動します。べき等性がない場合、レコードが重複します。
- モバイルアプリ ユーザーがラグのために2回送信をタップします。べき等性がない場合、2つのチケットが作成されます。
信頼性の高いリトライロジックを手動で構築するのは複雑です。どのリクエストが成功したかを追跡し、部分的な失敗を処理し、分散システム全体の状態を調整する必要があります。べき等性キーは、この複雑さを本来あるべきAPIレイヤーにプッシュします。
これらのエッジケースを自分で処理せずにチケット作成を自動化したい場合は、当社のAIエージェントがZendesk統合の一部として、べき等性を自動的に管理します。

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("最大リトライ回数を超えました")
リトライロジックの重要なポイント:
- 同じ論理操作のすべてのリトライで同じべき等性キーを再利用する
IdempotentRequestErrorで400エラーが発生した場合はリトライしない これはコードのロジックバグを示していますRetry-Afterヘッダーを使用してレート制限(429)を尊重する- APIへの負荷を回避するために、サーバーエラーには指数バックオフを使用する
ZendeskチケットAPI構造の詳細については、APIを使用してZendeskチケットを作成するに関するガイドをご覧ください。
本番環境実装のベストプラクティス
基本が機能したら、これらの本番環境対応のプラクティスを検討してください。
主要なストレージ戦略。 高ボリュームシステムの場合は、独自のデータベースまたはキャッシュでべき等性キーを追跡することをお勧めします。これにより、次のことが可能になります。
- キーが期限切れになるかどうかを検出する(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のようなツールを使用すると、開発作業なしでチケットの作成と応答を処理できます。

違いは次のとおりです。APIアプローチでは、人間が応答するチケットを作成するスクリプトを記述します。AIエージェントを使用すると、ビジネスを理解し、作成から解決までのチケットライフサイクル全体を処理するようにシステムをトレーニングします。Zendeskアカウントに接続すると、過去のチケット、ヘルプセンターの記事、およびマクロから学習します。
段階的なロールアウトモデルは、AIがレビュー用の応答を下書きすることから始まり、それが証明されるにつれて完全な自動化に拡張されることを意味します。作成を自動化するだけでなく、チケットのボリュームを削減したいと考えているチームにとって、これはカスタムAPI開発よりも多くの場合、より迅速な結果をもたらします。
AI Copilotは、エージェントが送信する前にレビューする返信を下書きすることで、べき等なリトライロジックを自分で構築する複雑さなしにAI支援を提供することもできます。
よくある質問
この記事を共有

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.



