mcpField
A
awesome-api-design

awesome-api-design

github.com/khasky開発2265 回インストール1 週間前に更新
リポジトリ

awesome-api-design について

HTTP API 契約の設計とレビューを支援するスキルで、APIを新設または進化させるチーム向けです。リソース設計、互換性、ページネーション、リトライ、並行制御、機械可読な仕様を扱います。

主な機能

  1. 01リソース指向のURLとメソッド設計
  2. 02バージョン管理と廃止ルール
  3. 03カーソルページネーションと許可リスト式フィルター
  4. 04冪等性と並行制御
  5. 05契約の基準となるOpenAPIまたはスキーマ

活用シーン

  1. 01新しいHTTP APIの設計
  2. 02APIまたはOpenAPI仕様のレビュー
  3. 03既存APIの規約に沿ったエンドポイント追加
  4. 04公開済み契約変更の互換性確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/khasky/awesome-agent-skills --skill awesome-api-design

インストール後、Claude Code で/awesome-api-designを入力して読み込まれたか確認します。

同梱ファイルevals/eval_queries.json

詳細

API 設計

HTTP API を設計する際は、利用者が破壊的な変更に不意を突かれることなく、何年にもわたってその API に基づいて開発できるようにします。契約こそがプロダクトです。URL、メソッド、ペイロード、エラー、進化のルールをここで意図的に決定します。暗黙のまま残したものはすべて、最初に依存したクライアントによって偶発的な契約になります。

有効にするタイミング

  • 「X の API を設計して」「この API 設計/OpenAPI 仕様をレビューして」「バージョン管理/ページネーション/リトライはどうすべきか」といった依頼。
  • 設計ドキュメントの API セクションを具体化する必要がある場合(awesome-design-doc から引き継ぐ)。
  • 既存の API に新しいエンドポイントを追加し、その規約に合わせる必要がある場合。

エラーエンベロープのフィールドやリトライの分類を定義する場合(その契約は awesome-error-standards が担当)、または実装済みハンドラーの脆弱性を監査する場合(awesome-security-audit)には有効にしないでください。

作業プロセス

  1. 既存の規約とプロジェクト独自の用語を確認します。既存 API の大文字・小文字の形式、ID 形式、ページネーション方式、エンベロープは、このガイドラインより優先されます。1 つの API 内での一貫性は、世界全体のベストプラクティスよりも重要です。以下のデフォルトを使うのは、新しい API の場合だけです。リソース名を 1 つでも決める前に、記録済みの決定事項(既存の ADR)と、プロジェクトの用語集(CONTEXT.md、ドメイン文書、またはコードやテストですでに使われている用語)を確認してください。パスは公開され、長期間使われる名前です。コードベースにすでにある概念の名前を変えると、読む人すべてに用語の置き換えを強いることになります。
  2. 手続きではなくリソースをモデル化します。ID とライフサイクルを持つ名詞(/orders/{id})を使い、アクションはリソースに対する状態遷移として表現します(純粋な動詞が避けられない場合は POST /orders/{id}/cancel を使い、/doCancelOrder は決して使いません)。ネストは最大 1 階層にします。それ以上深い階層はクエリフィルター(/comments?post_id=…)にします。ネストの階層が増えるたびに、あらゆるクライアントの URL に所有関係の前提が固定されるためです。
  3. v1 をリリースする前に、進化のルールを決めます。追加的な変更(新しい任意フィールド、新しいエンドポイント)は既存の API に追加します。破壊的な変更(フィールドの削除/改名/型変更、バリデーションの厳格化)は、必ず新しいバージョンで提供します。この分類を API とともに公開し、利用者が安全に無視できる変更を把握できるようにします。変更は段階的に導入します。再設計した抽象化は旧来のものと並行して提供し、既存の統合は利用者が移行するまで動作し続けます。非推奨化は、適用開始前に告知期間を設けて告知し、既存仕様をその場で変更して強制することはありません。
  4. リストエンドポイントは拡張に備えて設計します。オフセット方式ではなく、オペークなカーソルページネーションを使います((sort_key, id) の位置をエンコードし、リストエンベロープで has_more と next_cursor を返します)。オフセット方式は、同時書き込みによって行を飛ばしたり重複させたりし、深いページでは機能しなくなるためです。フィルタリングとソートには、インデックス付きフィールドに対する名前付きパラメーターの許可リストを使い、クエリレイヤーにそのまま渡すことは決してしません。
  5. 安全でないメソッドはリトライしても安全にします。変更を伴うリクエストでは Idempotency-Key を受け付けます。同じキーと同じ本文なら保存済みのレスポンスを再生し、同じキーで本文が異なる場合は 409 を返します。この仕組みがなければ、クライアントがリトライするたびに副作用が重複する可能性があります。(リトライの分類とエンベロープ形式については awesome-error-standards を参照してください。)
  6. 同時実行と部分更新の仕様を定めます。競合する可能性のある更新には、楽観的同時実行制御(ETag と If-Match)を使います。不一致の場合は、現在のバージョンとともに 409 を返します。PATCH の意味(マージパッチか置換か)を明記し、空の PATCH は何もせず受け入れるのではなく拒否します。
  7. 契約を信頼できる唯一の情報源として文書化します。実装を生成または検証する OpenAPI/スキーマ文書を使い、実装から乖離する説明文だけに頼らないでください。ID はオペークでプレフィックス付き(ord_…)、タイムスタンプは ISO 8601 UTC、金額は通貨とともに整数の最小通貨単位で表し、列挙値は閉じたものとします。また、未知の値を受け取った場合に利用者側で使うデフォルト値を文書化します。

設計レビューのチェックリスト

既存の設計をレビューする際は、以下の判断項目を順に確認します。

  • すべてのエンドポイントで命名と大文字・小文字の使い方が一貫しており、camelCase と snake_case のペイロードが混在していないこと。
  • モデル化された状態遷移を除き、リソースパスに動詞を含めないこと。REST リソースと並んで RPC 形式の /getX エンドポイントが存在しないこと。
  • すべてのリストエンドポイントで最初からページネーションを行うこと。後からページネーションを追加するのは破壊的変更です。
  • すべての変更操作について、キーによる冪等性を保証するか、自然に冪等であることを明記すること。
  • エラーレスポンスが、安定した単一のエンベロープ(awesome-error-standards)を参照すること。エンドポイントごとに場当たり的な対応をしないこと。
  • バージョニングと非推奨化のポリシーを明記すること。「何かを壊すときに決める」では不十分です。
  • API が送信する Webhook も公開インターフェースとして扱うこと。署名、バージョニング、再配信に対応し、エンドポイントと同じ契約上の規律を適用すること。
  • レスポンスに、クライアントに見せるべきでない情報を含めないこと。シリアライザーのデフォルトによって内部 ID、フラグ、フィールドが漏れないようにします。

変更レビュー

入力がリリース済みの契約への変更(仕様、スキーマ、ハンドラー、ペイロードの差分)である場合は、最終状態ではなく変更そのものをレビューします。新しいスキーマだけを見て互換性があると判断してはいけません。変更前と変更後の形式を並べて確認し、通信経路の両側のコードも確認します。以下の4つのシナリオを順に確認し、それぞれの結果を記録します。

  • 旧ライター、新リーダー:変更前に生成されたペイロードが、変更後のコードに届く。
  • 新ライター、旧リーダー:変更後に生成されたペイロードが、まだ更新されていないコードに届く(デプロイ済みのサーバー、リリース済みのモバイル版や SDK ビルドなど)。
  • ロールバック:新しいコードだけが書き込む値がすでに保存されている、または処理中である状態で、旧コードに戻る。
  • 保存済みペイロード:キュー内の旧形式のメッセージ、キャッシュエントリー、保存済みの行やファイルを新しいコードが読み取り、ロールバック後には新形式のデータを旧コードが読み取る。

アクセス可能なすべてのリポジトリで、両方向の利用箇所を検索します。

  • サーバーが送信を停止した、名前を変更した、または型を変更したフィールドをクライアントが読み取っている。エラーは発生せず、値が欠落または誤った値になるため、気付かないまま壊れます。
  • サーバーが、クライアントに分岐処理がないステータスコードやエラーコードを返す。
  • 既存の呼び出し元が省略しているにもかかわらず、リクエストフィールドが必須になったり、バリデーションが厳しくなったりする。
  • 網羅的な switch 文や閉じた型を持つコンシューマーに、新しい列挙値が届く。

「コンシューマーが見つからない」ことは「使われていない」ことを意味しません。外部クライアント、他のリポジトリ、スクリプト、保存済みデータはコード検索では確認できません。検索した対象を明記し、それ以外は不明として扱います。

変更ごとに1つの判定を示します。互換性あり(4つのシナリオすべてに問題がなく、根拠を引用している)、順序依存(明示したデプロイ順序、または明示した移行手順でのみ安全。その内容を記載する)、破壊的(稼働中のコンシューマーに対して、いずれかのシナリオで問題が発生する。修正には新しいバージョンまたは段階的な形式が必要)、判定不能(シナリオまたはコンシューマーの範囲を確認できない。不足している情報を明記し、決して「互換性あり」に繰り上げない)。

出力

API Design — <scope> — <date>

Contract decisions:
- <area: resources | versioning | pagination | idempotency | concurrency> — <decision> — <the consumer consequence it buys>
...

Spec: <OpenAPI/schema skeleton or diff, when producing one>
Deviations from incumbent conventions: <each with its justification, or "none">
Open questions: <decisions needing the user, with a recommended default each>

提出前のセルフチェック

  • 上記の設計レビューのチェックリストを自分の出力にも適用します。自分の設計に問題があれば、但し書きを添えて提出するのではなく、提出前に修正します。
  • 契約に関する各判断について、それによってコンシューマーにどのような影響があるかを明記します。「ベストプラクティスだから」は理由になりません。削除するか、正当化してください。
  • ステップ1には根拠を示します。実際に確認した既存の仕様、ルート、またはクライアントコードを明記します。慣例のある API に独自のデフォルトを適用することは、避けるべき失敗パターンです。
  • 設計上のすべての変更操作で、再試行に関する問いに答えます(冪等性キーを使うのか、自然に冪等なのか、どちらかを明記)。すべてのリストエンドポイントで、データ増加への対応に答えます。
  • 未解決の質問には、推奨するデフォルトを添えます。質問だけを残すと、設計作業を読者に押し戻すことになります。

アンチパターン

アンチパターン代わりに
拡大し続けるテーブルでのオフセットページネーションインデックス付きのソートキーを使った不透明なカーソル
「修正」として隠された破壊的変更新しいバージョンを用意し、クライアントに対して既存の形式は変更しない
エンドポイントごとに異なるエラー形式単一のエンベロープと、共通のクライアント側パーサー
URL 内の連番整数 ID不透明なプレフィックス付き ID。連番はデータ量を漏らし、列挙を招く
未知のフィールドを黙って破棄する PUT明示的な PATCH セマンティクスと、名前付きの拒否理由による厳格な検証
実装に追いついていない文章の仕様書コードを生成する、またはコードを検証する機械可読な契約
最初のクライアントの画面に合わせた設計リソースはドメインをモデル化し、ビューの構成はクライアントが担う

コメント