LESSON 25分

ストーリー

高橋アーキテクトが2つのAPI仕様書を並べた。

高橋アーキテクト
この2つのAPI、どちらが使いやすいと思う?

左のAPIは /getUserInfo?action=get&uid=123、 右のAPIは GET /api/v1/users/123

あなた
右のほうが…直感的に分かりやすいです
高橋アーキテクト
そうだ。でも世の中には左のようなAPIがたくさんある。なぜ右が良いのか、具体的に説明できるようになろう

実例比較:ユーザー管理API

悪いAPI設計

// 悪い例1: 動詞をURLに含める
POST /api/getUserById
Body: { "userId": 123 }

POST /api/createNewUser
Body: { "name": "田中", "email": "tanaka@example.com" }

POST /api/updateUserInfo
Body: { "userId": 123, "name": "田中太郎" }

POST /api/removeUser
Body: { "userId": 123 }

// 問題点:
// - すべてPOSTメソッド(HTTPメソッドの意味を無視)
// - URLに動詞が含まれている
// - 一貫性がない(get/create/update/remove とバラバラ)

良いAPI設計

// 良い例: RESTful設計
GET    /api/v1/users           // ユーザー一覧取得
GET    /api/v1/users/123       // 特定ユーザー取得
POST   /api/v1/users           // ユーザー作成
PUT    /api/v1/users/123       // ユーザー更新(完全置換)
PATCH  /api/v1/users/123       // ユーザー更新(部分更新)
DELETE /api/v1/users/123       // ユーザー削除

// 利点:
// - HTTPメソッドが操作を表現
// - URLはリソースを表す名詞のみ
// - パターンが一貫している

7つの観点で比較

1. URL設計

// 悪い例
GET /api/get-all-products         // 動詞が入っている
GET /api/product_list             // 命名がバラバラ
GET /api/Products/GetById/123     // PascalCase + 動詞

// 良い例
GET /api/v1/products              // 複数形・小文字・ハイフン区切り
GET /api/v1/products/123          // パスパラメータでID指定
GET /api/v1/products/123/reviews  // ネストでリレーションを表現

2. レスポンス形式

// 悪い例: 構造がバラバラ
// GET /api/users/123
{
  "code": 0,
  "msg": "success",
  "d": { "user_name": "tanaka", "Email": "tanaka@example.com" }
}

// GET /api/products/456
{
  "status": true,
  "result": { "productName": "Widget", "Price": 1500 }
}

// 良い例: 一貫した構造
// GET /api/v1/users/123
{
  "data": {
    "id": "123",
    "name": "田中太郎",
    "email": "tanaka@example.com",
    "createdAt": "2025-01-15T09:00:00Z"
  }
}

// GET /api/v1/products/456
{
  "data": {
    "id": "456",
    "name": "Widget",
    "price": 1500,
    "createdAt": "2025-01-10T10:30:00Z"
  }
}

3. エラーレスポンス

// 悪い例: エラーの詳細が分からない
{
  "error": true,
  "message": "Error occurred"
}

// 良い例: 構造化されたエラー情報
{
  "error": {
    "type": "VALIDATION_ERROR",
    "message": "入力内容に問題があります",
    "details": [
      {
        "field": "email",
        "message": "メールアドレスの形式が正しくありません",
        "value": "not-an-email"
      }
    ],
    "traceId": "abc-123-def"
  }
}

4. 日付・時刻の形式

// 悪い例: 形式がバラバラ
{
  "created": "2025/01/15",          // スラッシュ区切り
  "updated": "Jan 15, 2025",       // 英語表記
  "lastLogin": 1705305600          // Unix timestamp
}

// 良い例: ISO 8601形式で統一
{
  "createdAt": "2025-01-15T09:00:00Z",
  "updatedAt": "2025-01-15T14:30:00Z",
  "lastLoginAt": "2025-01-15T08:00:00Z"
}

5. IDの型

// 悪い例: 数値IDの問題
{
  "id": 9007199254740993  // JavaScriptの安全な整数範囲を超える
}

// 良い例: 文字列ID
{
  "id": "usr_abc123def456",  // プレフィックス付き文字列ID
  "orderId": "ord_789xyz"
}
// Stripe APIのように、リソース種別が分かるプレフィックスを付けると便利

6. Null の扱い

// 悪い例: nullと未定義が混在
{
  "name": "田中",
  "nickname": null,        // nullが返る
  // middleName は存在しない  // フィールドが欠落
}

// 良い例: 明確なポリシー
// 方針1: nullを許容し、フィールドは常に存在させる
{
  "name": "田中",
  "nickname": null,
  "middleName": null
}

// 方針2: 値がない場合はフィールドを省略する
{
  "name": "田中"
}
// → どちらかに統一する。混在させない。

7. コレクションのレスポンス

// 悪い例: 配列をそのまま返す
[
  { "id": 1, "name": "田中" },
  { "id": 2, "name": "鈴木" }
]
// 問題: メタ情報(総件数、ページ情報)を追加できない

// 良い例: エンベロープパターン
{
  "data": [
    { "id": "1", "name": "田中" },
    { "id": "2", "name": "鈴木" }
  ],
  "meta": {
    "totalCount": 150,
    "page": 1,
    "perPage": 20,
    "totalPages": 8
  }
}

有名APIから学ぶ

Stripe API(決済)

// Stripe は API 設計のお手本として有名
// プレフィックス付きID
{ "id": "cus_abc123" }          // customer
{ "id": "ch_xyz789" }           // charge
{ "id": "sub_def456" }          // subscription

// 一貫したリスト形式
{
  "object": "list",
  "data": [...],
  "has_more": true,
  "url": "/v1/customers"
}

GitHub API

// ネストされたリソースの表現
GET /repos/{owner}/{repo}/issues          // Issue一覧
GET /repos/{owner}/{repo}/issues/42       // 特定Issue
GET /repos/{owner}/{repo}/issues/42/comments  // Issueのコメント

// Link ヘッダーによるページネーション
// Link: <https://api.github.com/repos/...?page=2>; rel="next"

まとめ

観点悪いAPI良いAPI
URL動詞を含む、命名がバラバラ名詞・複数形・小文字で統一
レスポンス構造が不統一一貫したエンベロープ形式
エラー詳細が分からない構造化エラー情報
日付形式がバラバラISO 8601で統一
ID数値ID文字列ID(プレフィックス付き推奨)
Null混在ポリシーを統一
コレクション配列をそのまま返すメタ情報付きエンベロープ

チェックリスト

  • 良いAPIと悪いAPIの違いを7つの観点で説明できる
  • Stripe API、GitHub APIの設計パターンを把握した
  • 一貫性がAPI設計で最も重要であることを理解した

次のステップへ

良いAPIと悪いAPIの違いが分かりました。

次のセクションでは、API設計のベストプラクティスを体系的に学びます。 命名規則、ページネーション、フィルタリングなど、実務で即使えるテクニックを習得しましょう。


推定読了時間: 25分