API設計書の位置づけ
API設計書はフロントエンド・バックエンド・外部連携先の「接続仕様書」として機能する。実装前にこの設計書でレビューをおこなうことで、実装後の仕様変更コストを最小化できる。
💡 設計書の対象
REST API・GraphQL・gRPC・WebSocket など API の形式を問わず、「外部から呼び出されるインターフェース」であれば設計書の対象となる。本記事では REST API を中心に解説する。
定義すべき項目一覧
| 分類 | 定義項目 | 必須度 |
|---|---|---|
| 基本情報 | API名・APIバージョン・ベースURL | ◎ |
| 基本情報 | API概要・対象システム | ◎ |
| エンドポイント | HTTPメソッド・パス | ◎ |
| エンドポイント | 処理概要・対象リソース | ◎ |
| 認証・認可 | 認証方式(JWT / APIキー / OAuth2) | ◎ |
| 認証・認可 | アクセス権限(ロール別) | ◎ |
| リクエスト | パスパラメータ・クエリパラメータ | ◎ |
| リクエスト | リクエストボディ(JSON スキーマ) | ◎ |
| リクエスト | バリデーションルール | ◎ |
| レスポンス | 成功時レスポンス(スキーマ・例) | ◎ |
| レスポンス | HTTPステータスコード一覧 | ◎ |
| エラー | エラーコード・エラーメッセージ定義 | ◎ |
| レート制限 | レートリミット値・超過時の挙動 | ○ |
| 非機能 | タイムアウト・レスポンスタイム目標 | ○ |
エンドポイント定義
■ エンドポイント一覧
No. | HTTPメソッド | パス | 処理概要 | 認証
----|-------------|----------------------------|-----------------|------
001 | GET | /api/v1/users | ユーザー一覧取得 | JWT
002 | GET | /api/v1/users/{userId} | ユーザー詳細取得 | JWT
003 | POST | /api/v1/users | ユーザー新規登録 | JWT(ADMIN)
004 | PUT | /api/v1/users/{userId} | ユーザー情報更新 | JWT(本人 or ADMIN)
005 | DELETE | /api/v1/users/{userId} | ユーザー論理削除 | JWT(ADMIN)
006 | POST | /api/v1/auth/login | ログイン | なし(公開)
007 | POST | /api/v1/auth/refresh | トークン更新 | Refresh Token
認証・認可定義
| 項目 | 仕様 |
|---|---|
| 認証方式 | JWT(Bearer Token) |
| トークン有効期限 | アクセストークン: 15分 / リフレッシュトークン: 7日 |
| ヘッダー | Authorization: Bearer <token> |
| ロール定義 | ADMIN(全操作)/ USER(自己リソースのみ)/ READONLY(参照のみ) |
| 権限不足時 | HTTP 403 Forbidden + エラーコード AUTH_003 |
リクエスト仕様定義
■ パスパラメータ: なし
■ クエリパラメータ: なし
■ リクエストボディ(application/json)
{
"loginId": "string 必須 4〜50文字 英数字アンダースコアのみ",
"email": "string 必須 RFC5321準拠 最大255文字",
"password": "string 必須 8〜72文字 英大小数記号を各1文字以上含む",
"lastName": "string 必須 最大50文字",
"firstName": "string 必須 最大50文字",
"roleCode": "string 必須 ADMIN / USER / READONLY のいずれか"
}
■ リクエスト例
POST /api/v1/users
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"loginId": "acropolis",
"email": "acropolis@example.com",
"password": "P@ssw0rd!",
"lastName": "山田",
"firstName": "太郎",
"roleCode": "USER"
}
レスポンス仕様定義
■ 成功時(201 Created)
{
"userId": 12345,
"loginId": "acropolis",
"email": "acropolis@example.com",
"lastName": "山田",
"firstName": "太郎",
"roleCode": "USER",
"createdAt": "2026-06-18T12:00:00+09:00",
"updatedAt": "2026-06-18T12:00:00+09:00"
}
■ HTTPステータスコード一覧
200 OK — 取得・更新成功
201 Created — 新規作成成功
204 No Content — 削除成功
400 Bad Request — バリデーションエラー
401 Unauthorized— 認証エラー(トークン未提供・期限切れ)
403 Forbidden — 認可エラー(権限不足)
404 Not Found — リソースなし
409 Conflict — 重複エラー(loginId が既存)
500 Internal — サーバー内部エラー
エラーコード定義
| エラーコード | HTTP | メッセージ | 発生条件 |
|---|---|---|---|
| AUTH_001 | 401 | 認証トークンが必要です | Authorization ヘッダー未提供 |
| AUTH_002 | 401 | トークンの有効期限が切れています | JWT 期限切れ |
| AUTH_003 | 403 | この操作を行う権限がありません | ロール不足 |
| VAL_001 | 400 | 必須項目が未入力です | 必須フィールド欠如 |
| VAL_002 | 400 | 入力形式が正しくありません | 型・フォーマットエラー |
| DUP_001 | 409 | ログインIDが既に使用されています | loginId 重複 |
Python Tips — FastAPI から OpenAPI 仕様を自動抽出
FastAPI アプリケーションが稼働している環境では、/openapi.json から仕様を取得してドキュメント化できる。
"""
FastAPI / Spring Boot などの /openapi.json からエンドポイント一覧を取得し
Markdown テーブルとして出力する
pip install requests
"""
import json, requests
OPENAPI_URL = "http://localhost:8080/openapi.json" # 環境に合わせて変更
def fetch_openapi(url: str) -> dict:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
return resp.json()
def extract_endpoints(spec: dict) -> list[dict]:
rows = []
for path, methods in spec.get("paths", {}).items():
for method, op in methods.items():
if method in ("get", "post", "put", "patch", "delete"):
security = op.get("security", [])
auth = "なし" if not security else list(security[0].keys())[0] if security else "不明"
rows.append({
"method": method.upper(),
"path": path,
"summary": op.get("summary", "—"),
"tags": ", ".join(op.get("tags", [])),
"auth": auth,
})
return rows
def to_markdown(rows: list[dict]) -> str:
header = "| Method | Path | Summary | Tags | Auth |"
sep = "|--------|------|---------|------|------|"
lines = [header, sep]
for r in rows:
lines.append(f"| {r['method']} | `{r['path']}` | {r['summary']} | {r['tags']} | {r['auth']} |")
return "
".join(lines)
try:
spec = fetch_openapi(OPENAPI_URL)
rows = extract_endpoints(spec)
print(f"# API エンドポイント一覧 ({len(rows)} 件)")
print(to_markdown(rows))
# JSON ファイルにも保存
with open("api_spec_extracted.json", "w", encoding="utf-8") as f:
json.dump(rows, f, ensure_ascii=False, indent=2)
print("\n✅ api_spec_extracted.json に保存しました")
except Exception as e:
print(f"❌ 取得失敗: {e}")
レビューチェックリスト
| # | チェック項目 |
|---|---|
| 1 | 全エンドポイントにHTTPメソッドとパスが定義されているか |
| 2 | 認証・認可方式が全エンドポイントに定義されているか |
| 3 | リクエストの必須/任意・型・バリデーションが定義されているか |
| 4 | レスポンスのスキーマと具体例が定義されているか |
| 5 | エラーコードとエラーメッセージが定義されているか |
| 6 | APIバージョン管理方針が定義されているか |
| 7 | レートリミットが定義されているか |