Web api design
15 auto-selectable Claude Code skills distilling engineering best practices (Kent Beck, Fowler, Google SRE, OWASP, Anthropic, Netflix…), with a bilingual offline learning site. Make Claude Code write better code — and learn the practices yourself.
npx -y skills add goonobu-dot/dev-skills-library --skill web-api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 29 days oldThe repository was created 29 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Web/HTTP API design practices from Stripe and REST guidelines: idempotency keys, pagination, versioning, object IDs, error payloads, resource-oriented URLs. Use when designing or implementing HTTP endpoints, REST APIs, or webhooks, or when the user says API設計, エンドポイント, REST API, Webhook. Not for internal module/class interfaces (use deep-module-design).
SKILL.md
8.6 KB, as published. Nobody here has run it
Web API Design
HTTPで公開するAPI(REST/Webhook)を設計・実装するときに適用する実行知識。 「開発者を顧客として扱う」という前提に立ち、後方互換性・冪等性・可読性を最初から作り込む。内部モジュールのインターフェース設計は対象外(deep-module-designを使う)。
適用手順
1. リソース設計(着手時に必ず確認)
- URLは名詞・複数形・ケバブケースにする(例:
/user-profiles/{id},/orders)。動詞をURLに含めない(/getUserではなくGET /users/{id})。 - 操作はHTTPメソッドで表現する:一覧・取得=GET、作成=POST、全体更新=PUT、部分更新=PATCH、削除=DELETE。
- ネストは2階層までに抑える(
/orders/{id}/itemsはOK、/users/{id}/orders/{id}/items/{id}/...のような深いネストは避け、トップレベルリソース+クエリパラメータに切り替える)。 - レスポンスのフィールド名・大文字小文字規則をAPI全体で統一する(camelCase かsnake_caseかを最初に決めて混在させない)。
2. ID設計
- すべてのリソースIDに意味のあるプレフィックスを付ける(例:
usr_,ord_,evt_)。実装コストはほぼゼロで、ログ・デバッグ時にどのリソース種別か即座に判別できる。 - 連番の内部DB IDをそのまま外部公開しない。推測可能な連番は列挙攻撃・情報漏洩のリスクになる(ランダム性のあるID、またはULID/UUIDにプレフィックスを付与する)。
- IDは一度発行したら不変にする。リソースの属性変更でIDを変えない。
3. 冪等性(副作用のあるエンドポイント全てで検討)
- POST等の作成・課金・送信系エンドポイントには、クライアントが指定する冪等性キー(
Idempotency-Keyヘッダ)を受け付ける設計にする。 - サーバー側は同一キーでの再送を検知し、実処理を再実行せず前回と同じレスポンスを返す。
- 冪等性キーの保存期間(例: 24時間)を決め、期限切れ後は新規リクエストとして扱う。
- ネットワークリトライ・二重クリックなど「同じリクエストが複数回届く」ことを前提に設計する。冪等性を後付けするのは高コストなので、副作用のあるエンドポイントは最初から組み込む。
4. ページネーション
- 一覧取得APIはオフセット方式(
?page=2)ではなくカーソル方式(?after=xxx&limit=50)を優先する。オフセット方式はデータ追加・削除時に結果がずれ、大きなオフセットでDB性能が劣化する。 - レスポンスに次ページの有無・カーソル値・(可能なら)総件数を含める。
limitの上限をサーバー側で強制し、クライアント指定値をそのまま信用しない。
5. バージョニングと後方互換性
- 破壊的変更が必要になったら、既存クライアントを壊さない形で新バージョンを追加する(URLパス
/v2/またはAPIバージョン日付ヘッダ方式のいずれかをプロジェクトで統一する)。 - 「破壊的変更」の定義を明文化する:フィールド削除・型変更・必須化・既存の意味変更は破壊的、フィールド追加・新エンドポイント追加は非破壊的。
- 非推奨化する場合は猶予期間と告知手段(レスポンスヘッダの
Deprecation、変更履歴)を用意してから撤去する。
6. エラーレスポンス設計
- エラーは構造化されたペイロードで返す。最低限
code(機械可読な識別子)、message(人間可読な説明)、可能ならdetails(どのフィールドが問題か)を含める。 - HTTPステータスコードは標準的な意味に従う(400=クライアント起因の入力不正、401=未認証、403=権限不足、404=リソース不在、409=競合、422=意味的検証エラー、429=レート制限、5xx=サーバー起因)。すべて200やすべて500で返さない。
- エラーメッセージには対処のヒントを含める(例:「
emailフィールドの形式が不正です」であって「Bad Request」だけで終わらせない)。 - 内部実装の詳細(スタックトレース、SQL文、内部パス)をエラーレスポンスに含めない(情報漏洩対策。詳細はサーバーログ側に残す)。
7. Webhook設計(送信側になる場合)
- 受信側の冪等な処理を前提に、同一イベントが複数回配送されうることを明記する(配送保証は「少なくとも1回」が現実的)。
- イベントごとに一意のイベントID・タイムスタンプを付与し、受信側が重複排除できるようにする。
- 署名検証の仕組み(HMAC等)を用意し、受信側が送信元を検証できるようにする。
- リトライポリシー(指数バックオフ・最大試行回数)をドキュメント化する。
チェックリスト(実装前後で確認)
- URLは名詞・複数形・ケバブケース、動詞を含んでいない
- IDに意味のあるプレフィックスが付いている、連番DB IDを直接晒していない
- 副作用のあるエンドポイントに冪等性キーの受け口がある
- 一覧APIはカーソルベースのページネーションで、limit上限をサーバー側で強制している
- 破壊的変更が既存クライアントに影響しない形で導入されている(バージョニング方針に従っている)
- エラーレスポンスが構造化されており、ステータスコードが標準的な意味で使われている
- エラーメッセージに内部実装の詳細が漏れていない
- Webhookは重複配送・署名検証を前提に設計されている
アンチパターン集
| アンチパターン | なぜ問題か | 代わりにすること |
|---|---|---|
/getUserListのようなRPC風URL | HTTPメソッドの意味が失われ、一貫性がなくなる | GET /users にしてメソッドで操作を表現する |
| 内部の連番IDをそのまま公開 | 件数が推測でき、列挙攻撃・競合情報の漏洩につながる | プレフィックス付きランダムIDを発行する |
| POSTエンドポイントに冪等性キーがない | リトライ・二重送信で二重課金・二重作成が起きる | 作成・課金系には冪等性キーを最初から用意する |
| オフセットページネーションのみ提供 | データ変動時に結果が重複・欠落する、大きいoffsetで低速 | カーソルベースをデフォルトにする |
| すべてのエラーを200やHTTP 500で返す | クライアントがエラー種別で分岐できない | 意味に応じたステータスコードを返す |
| エラーメッセージにスタックトレース・SQL文を含める | 内部実装が漏洩し攻撃の手がかりになる | ユーザー向けメッセージと内部ログを分離する |
| 破壊的変更を既存バージョンに直接適用 | 既存クライアントが予告なく壊れる | 新バージョンを追加し、旧バージョンは猶予期間を設けて廃止する |
| Webhookが「1回だけ届く」前提で受信側を実装 | 実際は再送されうるため重複処理が起きる | イベントIDで冪等に処理する設計を受信側にも要求する |
出典
- Stripe Engineering, "Stripe's payments APIs: The first 10 years" (https://stripe.dev/blog/payment-api-design)
- Stripe, "Designing robust and predictable APIs with idempotency" (https://stripe.com/blog/idempotency)
- Stripe, "APIs as infrastructure: future-proofing Stripe with versioning" (https://stripe.com/blog/api-versioning)
- elsewhencode/project-guidelines (MIT License) — REST API設計規約部分
- John Ousterhout, A Philosophy of Software Design(深いモジュールの考え方をAPI設計に援用)
- 上記はいずれも要約・手順化したものであり、原文からの引用ではない。