mcpField
R
rest-api-design

rest-api-design

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

rest-api-design について

rest-api-designは、REST/HTTP APIのリソース、動作、契約を設計するスキルです。一貫性と進化しやすさを重視するエンジニア向けに、ステータスコード、エラー、ページネーション、バージョニング、セキュリティを整理し、OpenAPI 3.1の契約に反映します。

主な機能

  1. 01リソース名詞を軸に一貫したURLを設計
  2. 02HTTPメソッド、ステータスコード、冪等性を選択
  3. 03RFC 9457のエラー形式と統一ページネーション
  4. 04バージョニング、認証、レート制限を策定
  5. 05設計をOpenAPI 3.1に反映

活用シーン

  1. 01ドメインエンティティからREST APIを設計
  2. 02APIのエラー形式やページネーションを統一
  3. 03リクエスト結果に対応するステータスコードを選択
  4. 04合意済みのAPI設計をOpenAPI契約に変換

インストール

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

$npx skills add https://github.com/bm629/agent-skills --skill rest-api-design

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
contract-patterns.md
error-model.md
openapi-mapping.md
sources.md

詳細

rest-api-design — SKILL.md

バリアント: standard · 使用するタイミング: スキルが呼び出されると、以下の設計上の判断をリソースの表面に適用し、一貫性のある契約を返します。その後、制御は呼び出し元に戻ります。

概要

このスキルは、REST/HTTP API とその契約を設計するための規律であり、あらゆる Web フレームワークの上位レイヤーにあたります。ドメインの名詞群を、一貫性があり進化させやすい HTTP の表面に落とし込む際に、経験豊富なエンジニアが適用する、明確な既定方針をまとめています。リソースの命名方法、各操作に割り当てるメソッドとステータスコード、機械可読なエラー形式(RFC 9457 problem+json)、構造化された成功レスポンスとページネーション用のエンベロープ、バージョニングの方針、認証とレート制限の適用箇所、そして全体を OpenAPI 3.1 の契約として表現する方法を扱います。コード例は Python/FastAPI と Pydantic v2 を想定していますが、設計上の判断はすべて言語に依存しません。フレームワークの仕組み(ルーター、依存性注入、response_model)とスキーマモデリングは fastapi および pydantic-v2 スキルの対象です。このスキルではそれらを参照するだけで、重複して説明しません。

有効化するタイミング

  • ✅ ドメインエンティティ群をもとに、新しい API の表面を設計するとき — エンドポイント、メソッド、契約を決める場合。
  • ✅ 結果に適したステータスコードを選ぶとき、または 400 と 422、401 と 403、PUT と PATCH のどちらにするか決めるとき。
  • ✅ API のエラーモデル、成功エンベロープ、またはページネーション方式を定義または修正するとき。
  • ✅ API のバージョニング、認証、またはレート制限の方針を決めるとき。
  • ✅ 合意済みの REST 設計を OpenAPI 3.1 の契約に落とし込むとき。

次の場合は有効化しないでください:

  • 設計済みエンドポイントの FastAPI ハンドラー/ルーター/DI コードを書く場合 → fastapi スキルを使用してください。
  • リクエスト/レスポンスのデータクラスを詳細にモデリングする場合 → pydantic-v2 スキルを使用してください。
  • 大規模な OpenAPI ドキュメントを作成または生成する場合、リンティングする場合、あるいは SDK のコード生成を実行する場合 → これらは OpenAPI の作成/コード生成に関する専用の作業です(設計から契約への対応付けと引き継ぎ先については、references/openapi-mapping.md を参照してください)。
  • GraphQL または gRPC の表面を設計する場合 → 対象外です。このスキルが扱うのは REST/HTTP のみです。

ワークフロー

以下の手順を順番に適用してください。各手順には明確な既定方針があります。理由がある場合にのみ、既定方針から外れてください。

ステップ 1:リソースをモデル化する(動詞ではなく名詞)
  • リソースは名詞です。動詞は HTTP メソッドで表します。POST /orders とし、POST /createOrder にはしません。
  • コレクション名は複数形で統一します:/users、/users/{id}、/users/{id}/orders。/user と /users を混在させてはいけません。
  • ネストは 2 階層までに制限します。/users/{id}/orders は問題ありませんが、/users/{id}/orders/{oid}/items/{iid} は避けてください。深い階層の子リソースはトップレベルのリソース(/order-items/{iid})に昇格させ、リンクで関連付けます。
  • URL を選ぶ前に、ドメインの名詞とその関係からリソースを特定します。サブリソースは包含/所有関係を表し、横断的な要素は独立したトップレベルのリソースにします。
  • URL のパスセグメントは小文字とハイフンで表記し(/order-items)、camelCase や snake_case は使用しません。
  • 行数や列挙可能性が露呈する内部 ID/主キー ID を公開してはいけません。公開契約では UUID または不透明な ID を優先してください。
ステップ 2:メソッドを割り当て、冪等性を守る

RFC 9110 の HTTP セマンティクスに従います。

メソッド用途安全冪等
GETリソース/コレクションを読み取るはいはい
POSTコレクションに作成する、または冪等でないアクションを実行するいいえいいえ
PUT既知の URL にあるリソースを完全に置き換えるいいえはい
PATCH部分更新する(送信したフィールドのみ)いいえいいえ
DELETEリソースを削除するいいえはい
  • PUT は置き換え、PATCH はマージします。 PUT の本文は新しい完全な表現であり、省略されたフィールドはクリアされます。PATCH の本文には変更するフィールドのみを含めます。部分更新に PUT を使わないでください。
  • POST と PATCH は冪等ではありません。POST を再試行すると重複が作成されます。クライアントが再試行する可能性のある作成/課金操作では、Idempotency-Key リクエストヘッダー(Stripe の慣例で、現在は IETF のドラフト)を受け付け、キーと最初のレスポンスを保存して、再度リクエストされた際にそれを再送することで、ネットワーク再試行を安全にします。
  • GET には副作用があってはなりません。状態を変更する操作は GET ではありません。
ステップ 3:結果に合ったステータスコードを選ぶ
コード意味/使用する場面
200 OKGET/PATCH/PUT の成功、または本文を返す DELETE の成功
201 Created作成の成功 — 新しいリソースの URL を Location ヘッダーに設定します
204 No Content本文なしで成功(一般的な DELETE、または何も返さない PUT/PATCH)
400 Bad Request形式が不正なリクエスト — 解析できない JSON、誤った構造、不正なクエリーエンコーディング
401 Unauthorized認証されていない — 認証情報がない、または無効
403 Forbidden認証済みだが、この操作を行う権限がない
404 Not Foundリソースが存在しない(または、この呼び出し元には非表示)
409 Conflictリクエストが現在の状態と競合している — 一意フィールドの重複、バージョンの不一致
422 Unprocessable Content構文的には有効だが、意味的に無効 — ビジネスルール/フィールドの検証に失敗
429 Too Many Requestsレート制限を超過 — Retry-After を含めます
5xxサーバー障害 — 500 は一般的なエラー、503 は利用不可。クライアントの責任にしてはいけません
  • 400 と 422 の違い: 400 はサーバーがリクエストをまったく解析/理解できなかった場合です。422 は解析できたものの、値が検証に失敗した場合です。新しい API では、検証失敗に422、解析失敗に 400をデフォルトとして使用します。
  • 401 と 403 の違い: 401 は「あなたは誰ですか」(再認証が必要)、403 は「あなたが誰かはわかっていますが、それでも許可されていません」です。
  • エラーを本文に含めた 200 を返してはいけません。 ステータスコードは機械で読み取れる主要なシグナルです。200 で包まれた失敗は、あらゆるクライアント、プロキシ、監視システムを破綻させます。
ステップ 4:エラーモデルを 1 つ定義する — RFC 9457 problem+json(デフォルト)

すべてのエラーレスポンスでは、以下のメンバーを含む application/problem+json(RFC 7807 に取って代わる RFC 9457)を使用します。

  • type — 問題の種類を識別する URI(安定しており、文書化されているもの。ステータスコード以外に情報がない場合のデフォルトは "about:blank")。
  • title — 種類の簡潔な概要(about:blank の場合は HTTP ステータスの文言、例:"Not Found")。
  • status — HTTP ステータスコード。本文にも重複して記載します。
  • detail — この発生事象についての、人が読める説明。
  • instance — この発生事象を示す URI(例:リクエストパスまたはトレース ID)。
  • 拡張メンバー — 追加のドメインフィールド。クライアントは、認識できないものを無視 MUST です。フィールド単位の検証エラーは errors 配列に含めます(RFC で認められている拡張です)。
{
  "type": "https://api.example.com/problems/validation-error",
  "title": "Your request parameters did not validate.",
  "status": 422,
  "detail": "The request body has 2 invalid fields.",
  "instance": "/orders",
  "errors": [
    { "detail": "must be a positive integer", "pointer": "#/quantity" },
    { "detail": "must be a valid email", "pointer": "#/customer/email" }
  ]
}
  • API 全体で1 つのモデルを選び、混在させないでください。RFC 9457 は標準であり、機械で解析でき、自己記述的であるため、デフォルトとして適しています。
  • 代替案(組織内のスタイルガイドで必須の場合のみ): {"error": {"code": "...", "message": "...", "details": [...]}} のエンベロープ。機能しますが、標準ではありません。新しい API では problem+json を推奨します。両方を併用しないでください。
  • FastAPI での実装:application/problem+json を返す例外ハンドラーを登録し、RequestValidationError を errors 配列を含む 422 の problem にマッピングします。references/error-model.md を参照してください。
ステップ 5:成功レスポンスとページネーションを一つのエンベロープにまとめる
  • 単一のリソース:その表現を返します。薄く一貫性のあるラッパー({"data": {...}})も、すべての箇所で適用するなら問題ありません。一貫性が、凝った工夫よりも重要です。
  • コレクションには必ずページネーションを適用し、上限のないリストは決して返しません。デフォルトの limit は 20、上限は 100 とし、それを超える値は 422 で拒否します。
  • すべてのリストエンドポイントで、一つのエンベロープ形式を使います。data(項目)、pagination/meta(カーソル/件数)、および任意の links(ナビゲーション URL)です。
  • 大規模なデータや、頻繁に変化するデータ、フィード形式のデータでは、カーソル(キーベース)方式をデフォルトにします。挿入があっても安定し、深いページでも定数時間で取得でき、コストの高い全件数カウントも不要です。オフセット/ページ方式は、ランダムなページ移動や全件数が必要な、小規模で安定したデータセットにのみ使います。並行書き込みがあるとページずれ(スキップ/重複)が起き、深いページでは大幅に遅くなります。
  • どちらのエンベロープ形式も、カーソル方式とオフセット方式の選択基準も、references/contract-patterns.md を参照してください。
ステップ 6:バージョニング、認証、レート制限を決める
  • バージョニング — URL パスをデフォルトにします: /v1/users。目に見えてデバッグしやすく、キャッシュにも適しており、複数バージョンを並行稼働できます。URL の分かりやすさよりも発見しやすさを重視する場合は、ヘッダー/メディアタイプによるバージョニングが代替手段になります。
  • メジャーバージョンを上げるのは、破壊的変更の場合に限ります(フィールドの削除/改名、型の変更、必須フィールドの追加、同じ状況に対するステータスの変更)。追加的な変更(新しいエンドポイント、新しい任意フィールド)では、バージョンを上げません。クライアントは未知のフィールドを無視する寛容なリーダーとして設計します。
  • Deprecation ヘッダーと Sunset ヘッダー(RFC 8594)で廃止を通知し、サンセット後は 410 Gone を返します。
  • 認証は後付けではなく、コントラクトの一部です: ユーザー向け API では Authorization: Bearer <token>(JWT/OAuth)をデフォルトとし、サービス間通信では API キーヘッダー(例:X-API-Key)を使います。常に HTTPS を使用してください。 OpenAPI では、これらを securitySchemes と security 要件(操作ごと、またはグローバル)として定義します。
  • レート制限: 429 + Retry-After(安定した RFC-9110 のデフォルト)を返します。広く導入されている X-RateLimit-Limit/-Remaining/-Reset の規約でクォータを通知します。IETF の RateLimit/RateLimit-Policy フィールドは新たな標準ですが、まだ RFC ではありません。どのクライアントにも理解される安全な基本形は、429 + Retry-After です。
ステップ 7:設計を OpenAPI 3.1 のコントラクトとして表現する

成果物は、設計をそのまま対応付けられる OpenAPI 3.1 ドキュメントです。リソースは paths、メソッドは操作、エンベロープ/エラー/エンティティの形式は components/schemas、再利用するレスポンス/パラメーターは $ref を介した components/responses + components/parameters、認証は components/securitySchemes に対応します。3.1 を使います(JSON Schema 2020-12 を完全にサポートしており、nullable には旧式の nullable ではなく type: ["string","null"] を使います)。設計ごとに、ひとつの具体的なコントラクトを提示したら、そこで終わりにします。OpenAPI の詳細な記述、リンティング、モックサーバー、SDK コード生成は別の課題です。設計からコントラクトへの完全な対応付けと、完成したコントラクトの例は references/openapi-mapping.md にあります。

ルール

必ず守るルール(例外なし):

  • API 全体でエラーモデルは 1 つにします。デフォルトは RFC 9457 の problem+jsonで、application/problem+json として提供します。2 種類のエラー形式を混在させてはいけません。
  • エラーを本文に含めて 200(またはその他の 2xx)を返してはいけません。ステータスコードが契約です。
  • リソースは名詞です。パスに動詞を含めてはいけません。コレクションは複数形で統一します。
  • すべてのコレクションエンドポイントでページネーションを行い、最大ページサイズを強制します。
  • 常に HTTPS を使用します。認証は契約内で宣言し(securitySchemes と security)、暗黙的にしてはいけません。
  • PUT は全置換、PATCH は部分更新です。両者を混同してはいけません。
  • 契約には OpenAPI 3.1(JSON Schema 2020-12)を使用します。null 許容性は "null" 型メンバーで表現し、廃止された 3.0 の nullable キーワードは使いません。

推奨事項(変更可能):

  • デフォルトではカーソル/キーセットページネーションを使います。オフセットは、小規模で安定しており、ランダムアクセスが必要なデータセットに限ります。
  • デフォルトでは URL パスでバージョンを管理します。メジャーバージョンのみを使い、追加的な変更ではバージョンを上げません。
  • ユーザー向け API には Bearer/JWT、サービス間通信には API キーを使います。
  • レート制限の基本は 429 と Retry-After にします。補足情報として X-RateLimit-* ヘッダーを追加します。
  • リソースのネストは 2 階層までに制限し、それより深い子リソースはトップレベルのリソースにします。

注意点

  • **PATCH を全置換として扱うと、**クライアントが送信しなかったフィールドが気付かないうちに消去されます。PATCH では指定されたフィールドのみをマージする必要があります。置換の動作が必要なら PUT を使います。
  • **エラーを本文に含めた 200 は、**ブラウザーでは問題ないように見えても、ステータスコードを基準に動作する再試行ロジック、キャッシュ、監視を壊します。常に実際のステータスを設定してください。
  • **オフセットページネーションのずれ:**並行して挿入や削除が行われると、ページ間で ?offset= により行がスキップされたり重複したりします。また、深いオフセットほど処理が遅くなります(データベースがスキップ対象の行をすべてスキャンして破棄するためです)。カーソル/キーセット方式なら、どちらも回避できます。
  • **422 と 400 の混同:**構文解析には成功したものの、業務上の検証に失敗した値に 400 を返すと、クライアントが処理を分岐するために使う情報が失われます。400 は「まったく解析できなかった」場合に限って使います。
  • **OpenAPI 3.1 のスキーマで nullable: true を指定しても、**3.0 のキーワードであるため、気付かないうちに無視されます。type: ["string", "null"] を使ってください。バリデーターが常に警告するとは限りません。
  • **POST のべき等性を前提にしてはいけません。**タイムアウトした POST をクライアント(およびプロキシ)が再試行すると、重複が作成される場合があります。再試行が想定される場合は、Idempotency-Key を必須にし、サーバー側で重複排除を行います。
  • 連番の内部 ID を漏えいすると(/users/1001)、行数が露呈し、列挙も可能になります。公開 API では不透明な ID/UUID を使います。

アンチパターン

  • 「とりあえず 200 を返して、本文に ok: false を入れればいい」— いけません。ステータスコードが機械可読な契約です。
  • 「動詞のほうが分かりやすいから、/getUser で問題ない」— いけません。動詞はメソッドで、パスは名詞です。
  • 「サブシステムごとにエラー形式を分ける」— 形式は 1 つ(problem+json)に決め、全体に適用します。
  • 「このコレクションは小さいからページネーションは不要」— コレクションは増えます。上限のないリストは、将来的な障害の火種です。
  • 「エンドポイントごとにバージョンを付ける/URL にマイナーバージョンを使う」— API 全体をメジャーバージョンのみでバージョン管理します。
  • 「ここで FastAPI のルーティングや Pydantic のモデリングを一から説明する」— fastapi と pydantic-v2 のスキルを参照してください。このスキルが扱うのは設計であり、フレームワークのコードではありません。

出力

このスキルでは、REST API の設計と OpenAPI 3.1 の契約を作成します。内容には、リソース/URL のマップ、各操作のメソッドとステータスコードの判断、単一のエラーモデル(problem+json)と成功時/ページネーション用のエンベロープ、バージョン管理/認証/レート制限の方針、およびそれらを表現した OpenAPI 3.1 ドキュメントの例が含まれます。想定される利用者は、fastapi と pydantic-v2 のスキルを使ってハンドラーを実装するエンジニア(またはコーディングエージェント)と、公開された契約に基づいて連携する下流のクライアントです。

関連項目

  • fastapi — フレームワークの仕組み(ルーター、依存性注入、response_model、例外ハンドラー)。このスキルが契約を決定し、fastapi が実装します。
  • pydantic-v2 — リクエスト/レスポンスのスキーマモデリング。このスキルがデータ構造を定義し、pydantic-v2 がモデル化します。
  • OpenAPI 作成/SDK コード生成ツール — より詳細な契約の作成、リンティング、モックサーバー、クライアント生成(このスキルから引き継ぐ別の領域です)。
  • references/error-model.md、references/contract-patterns.md、references/openapi-mapping.md — 以下の読み込み条件を参照してください。

段階的な開示

詳細な内容は references/ に格納されており、必要な場合にのみ読み込みます。

  • references/error-model.md — エラーモデルを定義または修正するときに読み込みます。RFC 9457 の各メンバー、errors 検証配列、about:blank のデフォルト、404 と 422 の problem+json の例、FastAPI の例外ハンドラーパターン、比較用の標準外の {error:{...}} 形式を扱います。
  • references/contract-patterns.md — レスポンスやページネーションを設計するときに読み込みます。成功時のエンベロープ、レスポンス形式を含むカーソル方式とオフセット方式の決定表、バージョン管理のライフサイクル(Deprecation/Sunset/410)、認証方式、レート制限ヘッダーを扱います。
  • references/openapi-mapping.md — 設計を契約として表現するときに読み込みます。設計から OpenAPI 3.1 要素へのマッピング、3.1 と 3.0 の違いに関する注記(JSON Schema 2020-12、null 型、Webhook)、problem+json レスポンスとセキュリティスキームを含む、全工程を網羅した契約例を扱います。
  • references/sources.md — 調査の出典/引用情報。

本文の上限

  • description は 1,024 文字以下(agentskills.io の上限)。
  • 本文は約 500 行/5,000 トークン以下にし、毎回のコンテキストに含めます。
  • 参照ファイルごとに、10k トークン超で警告、25k トークン超でエラー。参照ファイル全体では、25k トークン超で警告、50k トークン超でエラー。

コメント