本番システムは6つの外部APIと連携しています。データ収集のリクエスト実行、履歴データ取得、国内データ・海外データの処理——それぞれのAPIには固有の認証方式、レート制限、エラーコードがあります。
Claude Codeにこれらの API統合を任せた結果、「認証パターンの混同」「リトライ対象の誤り」「APIキーの取り違え」など、AI固有の落とし穴が見えてきました。本記事では、6つのAPI統合で得た実践的な知見を記録します。
6つのAPI一覧
| API | 用途 | 認証方式 | 特記事項 |
|---|---|---|---|
| Payment Gateway API | データ収集リクエスト・リソース管理 | HMAC-SHA256 | 条件付きリクエスト対応 |
| Historical Data API | 履歴データ取得 | Bearer Token | Parquet保存 |
| Domestic Analytics API | 国内データ処理 | トークン認証 | Proxy経由(macOS→Windows VM) |
| Domestic Data API | 国内データ取得 | リフレッシュトークン | 日次更新 |
| Cloud Processing API | 海外データ処理(初期) | API Key + Secret | ドライラン/本番モード切替 |
| Batch Processing API | 海外データ処理(移行先) | RSA署名 | SDK経由 |
共通パターン:AIに守らせる4原則
原則1:認証情報は.envに格納
1import os2from dotenv import load_dotenv3
4load_dotenv()5
6API_KEY = os.getenv("GATEWAY_API_KEY")7API_SECRET = os.getenv("GATEWAY_API_SECRET")8
9# ❌ AIがやりがちなハードコード10# API_KEY = "abc123..." # 絶対に禁止CLAUDE.mdに「認証情報のハードコード禁止」と書いても、AIは時々テストコードにダミーキーをハードコードします。.env.exampleに変数名だけ記載し、実値は.env(gitignore対象)に置く運用を徹底しました。
原則2:リトライは指数バックオフ
1import time2
3RETRYABLE_ERRORS = (ConnectionError, TimeoutError)4
5def api_call_with_retry(6 func,7 max_retries: int = 3,8 base_wait: float = 1.0,9):10 for attempt in range(max_retries):11 try:12 return func()13 except RETRYABLE_ERRORS as e:14 if attempt == max_retries - 1:15 raise5 collapsed lines
16 wait = base_wait * (2 ** attempt)17 logger.warning(18 f"リトライ {attempt + 1}/{max_retries}({wait:.1f}秒後): {e}"19 )20 time.sleep(wait)重要なのはRETRYABLE_ERRORSの定義です。AIに制約なしで書かせると、except Exceptionで全エラーをリトライしてしまいます。認証エラー(401)やバリデーションエラー(400)をリトライしても意味がありません。
原則3:レート制限の遵守
1import time2from collections import deque3
4class RateLimiter:5 def __init__(self, max_requests: int, window_seconds: float):6 self.max_requests = max_requests7 self.window_seconds = window_seconds8 self.timestamps: deque[float] = deque()9
10 def wait_if_needed(self) -> None:11 now = time.time()12 # ウィンドウ外のタイムスタンプを削除13 while self.timestamps and self.timestamps[0] < now - self.window_seconds:14 self.timestamps.popleft()15
10 collapsed lines
16 if len(self.timestamps) >= self.max_requests:17 sleep_time = self.timestamps[0] + self.window_seconds - now18 if sleep_time > 0:19 logger.info(f"レート制限: {sleep_time:.1f}秒待機")20 time.sleep(sleep_time)21
22 self.timestamps.append(time.time())23
24# Payment Gateway: 10リクエスト/秒25gateway_limiter = RateLimiter(max_requests=10, window_seconds=1.0)原則4:エラーレスポンスの解析
1def parse_api_error(response) -> str:2 """HTTPステータスコードとAPIエラーコードの両方を解析"""3 status_code = response.status_code4
5 try:6 body = response.json()7 api_error_code = body.get("messages", [{}])[0].get("message_code", "")8 api_error_string = body.get("messages", [{}])[0].get("message_string", "")9 except (ValueError, IndexError, KeyError):10 api_error_code = ""11 api_error_string = response.text12
13 return (14 f"HTTP {status_code} | "15 f"API Error: {api_error_code} | "2 collapsed lines
16 f"Detail: {api_error_string}"17 )API固有の実装詳細
Payment Gateway API:HMAC-SHA256認証
Payment Gateway APIの認証は、タイムスタンプ + HTTPメソッド + パス + ボディを連結してHMAC-SHA256で署名する方式です。
1import hmac2import hashlib3import time4
5def create_gateway_signature(method: str, path: str, body: str = "") -> dict:6 timestamp = str(int(time.time() * 1000))7 text = timestamp + method + path + body8 sign = hmac.new(9 API_SECRET.encode(), text.encode(), hashlib.sha25610 ).hexdigest()11 return {12 "API-KEY": API_KEY,13 "API-TIMESTAMP": timestamp,14 "API-SIGN": sign,15 }AIが間違えやすいポイント:
time.time()をミリ秒に変換する(* 1000を忘れる)- 連結順序を間違える(timestamp + method + path + body の順序が固定)
hmac.newではなくhmac.HMACを使おうとする(動作は同じだが既存コードとの一貫性が崩れる)
重大インシデント:APIキーの取り違え
Payment Gateway APIには「データ収集用API」と「分析用API」の2種類があります。APIキーは別物です。
1GATEWAY_API_KEY=xxxxx # データ収集用2GATEWAY_API_SECRET=yyyyy # データ収集用3GATEWAY_ANALYTICS_API_KEY=zzz # 分析用(使わない)AIがコードを修正する際、GATEWAY_ANALYTICS_API_KEYを使ってしまい、リクエストがERR-5012(認証エラー)で失敗する事故が起きました。
対策として、CLAUDE.mdに以下を追加しました。
1## Payment Gateway API注意事項2- データ収集には GATEWAY_API_KEY / GATEWAY_API_SECRET を使用3- GATEWAY_ANALYTICS_* は分析用。データ収集エンジンでは絶対に使わない4- ERR-5012が出たら、まずAPIキーの種別を確認することDomestic Analytics API:Proxy経由のアクセス
Domestic Analytics APIは Windows上でしか動かないデスクトップアプリに同梱されています。macOSの本番システムからアクセスするには、Windows VM経由のProxy構成が必要です。
1macOS (本番システム)2 → HTTP Request3 → Windows VM (10.211.55.3:19080)4 → localhost:18080 (Domestic Analytics API)1ANALYTICS_BASE_URL = "http://10.211.55.3:19080/analyticsapi"2
3def get_analytics_token() -> str:4 """Domestic Analytics APIの認証トークンを取得"""5 response = requests.post(6 f"{ANALYTICS_BASE_URL}/token",7 json={"APIPassword": os.getenv("ANALYTICS_API_PASSWORD")},8 )9 response.raise_for_status()10 return response.json()["Token"]AIに「Domestic Analytics APIを叩いて」と言うと、localhost:18080に直接アクセスしようとします。macOSからはlocalhostではなくProxy経由(10.211.55.3:19080)でアクセスする必要があることを、CLAUDE.mdに明記しました。
Historical Data API:履歴データのParquet保存
Historical Data APIからの履歴データは、CSV(遅い)ではなくParquet形式で保存します。
1import pandas as pd2
3def fetch_and_save_historical_data(4 data_source: str,5 granularity: str,6 from_date: str,7 to_date: str,8 output_dir: str,9) -> None:10 """Historical Data APIからデータを取得してParquetで保存"""11 headers = {12 "Authorization": f"Bearer {os.getenv('HISTORICAL_ACCESS_TOKEN')}",13 "Content-Type": "application/json",14 }15
20 collapsed lines
16 params = {17 "granularity": granularity,18 "from": from_date,19 "to": to_date,20 "price": "MBA", # Mid, Bid, Ask21 }22
23 response = requests.get(24 f"{HISTORICAL_BASE_URL}/sources/{data_source}/records",25 headers=headers,26 params=params,27 )28 response.raise_for_status()29
30 records = response.json()["records"]31 df = pd.DataFrame([flatten_record(r) for r in records])32
33 output_path = f"{output_dir}/{data_source}_{granularity}.parquet"34 df.to_parquet(output_path, index=False)35 logger.info(f"保存完了: {output_path}({len(df)}行)")AIが混同する認証パターン
6つのAPIを扱っていると、AIは認証方式を混同します。
1混同パターン:2 Payment GatewayのHMAC署名 ↔ Historical DataのBearerトークン3 Domestic AnalyticsのAPIパスワード ↔ Domestic Dataのリフレッシュトークン4 Cloud ProcessingのKey+Secret ↔ Batch ProcessingのRSA署名対策として、CLAUDE.mdにAPI別の認証方式を一覧化しました。
1## API認証方式一覧2
3| API | 認証方式 | 環境変数 |4|-----|---------|---------|5| Payment Gateway | HMAC-SHA256署名 | GATEWAY_API_KEY, GATEWAY_API_SECRET |6| Historical Data | Bearer Token | HISTORICAL_ACCESS_TOKEN |7| Domestic Analytics | パスワード→トークン交換 | ANALYTICS_API_PASSWORD |8| Domestic Data | リフレッシュトークン | DOMESTIC_REFRESH_TOKEN |9| Cloud Processing | API Key + Secret Header | CLOUD_API_KEY, CLOUD_SECRET_KEY |10| Batch Processing | RSA署名(SDK内部処理) | BATCH_RSA_KEY_PATH |この一覧があることで、AIが「Payment GatewayのAPIキーでHistorical Data APIにアクセスしようとする」ミスが激減しました。
エラーコード表の効果
APIエラーが発生した時、AIはエラーメッセージだけでは原因を特定できないことが多いです。エラーコード表をCLAUDE.mdに記載すると、デバッグ精度が上がります。
1## Payment Gateway エラーコード2
3| コード | 意味 | 対処 |4|--------|------|------|5| ERR-5003 | リクエストパラメータが不正 | パラメータの最小/最大値を確認 |6| ERR-5012 | 認証エラー | APIキーの種別(データ収集/分析)を確認 |7| ERR-5106 | リソース不足 | 利用可能なリソース枠を再確認 |8| ERR-5114 | パラメータが範囲外 | 現在の基準値からの乖離率を確認 |9| ERR-5122 | アクティブリソース上限超過 | 既存のアクティブリソースを確認 |エラーコード表なしの場合、AIは「ERR-5012が出ました。APIキーを確認してください」と汎用的な回答をします。表があると、「ERR-5012はデータ収集/分析のAPIキー種別の問題です。GATEWAY_API_KEYが分析用になっていないか確認します」と具体的な診断ができます。
6つのAPIで共通する3要素
6つのAPI全てに共通するのは、以下の3要素です。
1. リトライ
全APIで一時的なネットワーク障害が発生します。指数バックオフによるリトライは必須ですが、リトライ対象を限定することが重要です。
2. 認証
認証方式は異なりますが、「認証情報を.envから読み、リクエストヘッダーに付与する」という流れは同じです。
3. レート制限
レート制限のない APIは存在しません。制限値はAPIごとに異なりますが、RateLimiterの仕組みは共通化できます。
1# API別レート制限設定2RATE_LIMITS = {3 "gateway": RateLimiter(max_requests=10, window_seconds=1.0),4 "historical": RateLimiter(max_requests=20, window_seconds=1.0),5 "analytics": RateLimiter(max_requests=5, window_seconds=1.0),6 "domestic_data": RateLimiter(max_requests=10, window_seconds=60.0),7 "cloud": RateLimiter(max_requests=200, window_seconds=60.0),8 "batch": RateLimiter(max_requests=30, window_seconds=30.0),9}学んだこと
1. AIは認証パターンを混同しやすい
6つのAPIを1つのコードベースで扱うと、AIはHMAC署名とBearerトークンを取り違えることがあります。API固有の認証方式と環境変数名をCLAUDE.mdに一覧化することで、混同を防止できました。
2. 6つのAPIで共通するのは「リトライ」「認証」「レート制限」の3要素
認証方式やエラーコードはAPIごとに異なりますが、リトライロジック、認証情報の管理方法、レート制限の仕組みは共通化できます。myModules/の共有モジュールとして実装することで、新しいAPIの追加が容易になりました。
3. エラーコード表をCLAUDE.mdに記載すると、AIのデバッグ精度が上がる
AIはHTTPステータスコードだけでは「何を直せばいいか」がわかりません。APIエラーコードとその意味・対処法を表形式で記載すると、AIが具体的な診断と修正提案を行えるようになります。
まとめ
6つのAPI統合をAIに任せる際に重要なのは以下の3点です。
- API別の認証方式を明示: CLAUDE.mdに認証方式・環境変数・エラーコード表を記載。AIの認証パターン混同を防止
- リトライ対象の限定:
ConnectionErrorとTimeoutErrorのみリトライ。認証エラーやバリデーションエラーはリトライ禁止 - 共通パターンの抽出: リトライ、認証、レート制限の3要素は全APIで共通化し、
myModules/の共有モジュールとして管理