目次
1. リソース設計とURL
- URLは名詞、操作はHTTPメソッドで表す:
GET /users/123 は良く、/getUser?id=123 は避ける
- コレクションは複数形:
/users、/orders
- ネストは1〜2階層まで:
/users/123/orders は可。それより深い場合は /orders?user_id=123 のようにクエリにする
- 表記を統一する:URLはkebab-case(
/order-items)、JSONのキーはsnake_caseかcamelCaseのどちらかに揃える
2. HTTPメソッドの使い分け
| メソッド | 用途 | 冪等性 |
|---|
| GET | 取得 | ○ |
| POST | 作成・処理の実行 | × |
| PUT | 全体を置き換える | ○ |
| PATCH | 一部を更新する | △(実装による) |
| DELETE | 削除 | ○ |
- GETで副作用を起こさない
- 決済のようなPOSTには Idempotency-Key ヘッダを受け付け、リトライしても二重に処理されないようにする
3. ステータスコード
200 成功、201 作成(Location ヘッダを付ける)、204 返す本文なし
400 リクエスト不正、401 未認証、403 権限なし、404 存在しない、409 競合、422 バリデーションエラー、429 レート制限
500 サーバー側のエラー。エラーなのに 200 を返し、本文の "success": false で失敗を表すやり方はしない
4. エラーレスポンス
- 形式を統一する。RFC 9457(Problem Details) に準拠するのがおすすめ
{
"type": "https://example.com/errors/validation",
"title": "Validation failed",
"status": 422,
"detail": "email is invalid",
"errors": [{ "field": "email", "code": "invalid_format" }]
}
- 機械が判別できる
code と、人が読む message を分ける
- スタックトレースや内部情報は返さない
5. ページネーション・フィルタ・ソート
- 件数が多い場合や更新が頻繁なデータでは、カーソル方式(
?cursor=xxx&limit=50)がoffset方式よりも安定し、速い
limit には上限を設ける(例:最大100)
- フィルタは
?status=active、ソートは ?sort=-created_at のように書けるようにする
- レスポンスに
next_cursor や has_more を含める
6. バージョニング
- URLに入れる方式(
/v1/...)が最も分かりやすく、運用しやすい
- 破壊的変更はメジャーバージョンを上げるときだけ行う。フィールドの追加は後方互換を保てる
- 廃止予定は
Deprecation / Sunset ヘッダで事前に知らせる
7. セキュリティ
- HTTPSを必須にする
- 認証には OAuth 2.0 / OIDC、またはAPIキーを使う。トークンは短命にし、リフレッシュできる仕組みにする
- 認可はリソース単位で必ずチェックする(IDOR対策。
/users/124 を他人が見られないようにする)
- 入力をバリデーションし、レスポンスには必要なフィールドだけを返す(Mass Assignment と過剰なデータ露出の対策)
- レート制限をかけ、
RateLimit-* ヘッダで残りの回数を伝える
- CORSは必要なオリジンだけを許可する
- 参考:OWASP API Security Top 10
8. パフォーマンス
ETag / If-None-Match や Cache-Control でキャッシュを効かせる
- N+1を避け、関連データは
?include=author のように必要な分だけ返す
- gzip/brotliで圧縮する
- 時間のかかる処理は
202 Accepted を返してジョブ化し、ステータスを確認するエンドポイントかWebhookで結果を通知する
9. データ形式
- 日時は ISO 8601(UTC):
2026-10-29T12:00:00Z
- 金額は小数ではなく整数(最小単位)か文字列で表し、通貨コードを添える
- IDは推測されにくいもの(UUIDやULID)を検討する
null とキーの省略をどう扱うかを決めておく
10. ドキュメントと運用
- OpenAPI で仕様を定義する(スキーマファーストかコードファーストかを決める)
- リクエストIDを発行してレスポンスヘッダ(
X-Request-Id)に含め、ログを追えるようにする
- 構造化ログ・メトリクス・トレーシング(OpenTelemetry)を入れる
- コントラクトテストで、仕様と実装がずれないようにする
補足:Railsでの例
- エラー形式は
rescue_from で一か所にまとめる
- シリアライズには
jbuilder や alba を使う
- レート制限には Rails 8 標準の
rate_limit か rack-attack を使う
- OpenAPIは
rswag か committee で管理する