REST APIは、Webサービスやモバイルアプリケーションのバックエンドとして広く採用されているアーキテクチャスタイルです。しかし、「RESTful」という言葉を使いながらも、その本質的な設計原則を理解せずにAPIを設計しているケースは少なくありません。

本記事では、REST APIの設計原則を体系的に解説します。Roy Fieldingが提唱した6つのアーキテクチャ制約条件から、実際のエンドポイント設計のベストプラクティス、HTTPメソッドとリソースの対応関係、ステータスコードの適切な使い分け、そして避けるべきアンチパターンまで、API設計者が押さえるべき知識を網羅します。

前提条件と対象読者

本記事は以下の知識を持つ開発者を対象としています。

  • HTTP通信の基礎(リクエスト/レスポンスの構造、ヘッダー情報)を理解している方
  • バックエンドAPIの設計・実装経験がある、または学習中の方
  • JSON形式のデータ交換について基本的な理解がある方

HTTP通信の基礎についてはHTTPリクエストとレスポンスの仕組みを図解で理解するで詳しく解説しています。

RESTとは何か

REST(Representational State Transfer)は、2000年にRoy Fieldingが博士論文で提唱したソフトウェアアーキテクチャスタイルです。WebのアーキテクチャをRESTfulに設計することで、スケーラビリティ、シンプルさ、変更容易性、可視性などの品質特性を実現できます。

RESTの誕生と背景

RESTは、HTTPプロトコルの設計にも関わったRoy Fieldingが、Web全体のアーキテクチャを分析・体系化する中で生まれました。Fieldingは、Webが大規模に成功している理由を「アーキテクチャ制約の組み合わせ」として説明し、それをRESTと名付けました。

flowchart TB
    subgraph REST["REST(Representational State Transfer)"]
        direction TB
        A["クライアント・サーバー分離"]
        B["ステートレス通信"]
        C["キャッシュ可能"]
        D["統一インターフェース"]
        E["階層化システム"]
        F["コードオンデマンド(オプション)"]
    end
    
    REST --> G["スケーラブルで<br>保守性の高いAPI"]

RESTとRESTfulの違い

「REST」はアーキテクチャスタイルそのものを指し、「RESTful」はRESTの原則に従って設計されたシステムを形容する言葉です。つまり、RESTfulなAPIとは、RESTの制約条件を満たすように設計されたAPIを意味します。

用語 意味
REST アーキテクチャスタイルの名称
RESTful RESTの原則に従っている状態を表す形容詞
REST API RESTfulに設計されたWeb API

RESTの6つのアーキテクチャ制約条件

REST APIを正しく設計するためには、Fieldingが定義した6つの制約条件を理解することが不可欠です。これらの制約を守ることで、スケーラブルで保守性の高いAPIを実現できます。

1. Client-Server(クライアント・サーバー分離)

クライアントとサーバーの関心事を分離することで、それぞれが独立して進化できるようにします。

flowchart LR
    subgraph Client["クライアント"]
        A["ユーザーインターフェース"]
        B["ユーザー体験"]
    end
    
    subgraph Server["サーバー"]
        C["データストレージ"]
        D["ビジネスロジック"]
    end
    
    Client <-->|HTTP| Server

この分離により得られるメリットは以下の通りです。

  • クライアントはサーバーのデータストレージ実装を知る必要がない
  • サーバーはクライアントのUI実装を知る必要がない
  • 各コンポーネントを独立してスケール・更新できる
  • フロントエンドとバックエンドで異なる技術スタックを採用可能

2. Stateless(ステートレス)

サーバーはクライアントの状態を保持しません。各リクエストには、そのリクエストを処理するために必要なすべての情報が含まれている必要があります。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    
    Note over C,S: ステートレス通信
    C->>S: GET /users/123<br>Authorization: Bearer token123
    S-->>C: 200 OK<br>ユーザー情報
    
    Note over S: サーバーは状態を保持しない
    
    C->>S: PUT /users/123<br>Authorization: Bearer token123<br>更新データ
    S-->>C: 200 OK<br>更新後の情報

ステートレス設計のメリットは以下の通りです。

  • サーバーのスケーラビリティが向上(どのサーバーインスタンスでもリクエストを処理可能)
  • 障害時のリカバリが容易
  • リクエストの可視性が向上(各リクエストが自己完結)

ステートレス設計の実装ポイントとして、認証情報はリクエストヘッダー(Authorizationヘッダー等)で毎回送信します。セッション状態をサーバー側で保持するのではなく、JWT(JSON Web Token)などのトークンベースの認証を採用することで、ステートレス性を維持できます。

3. Cacheable(キャッシュ可能)

レスポンスは暗黙的または明示的に、キャッシュ可能かどうかを示す必要があります。キャッシュを適切に活用することで、ネットワーク効率とパフォーマンスが向上します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600, public
ETag: "abc123"

{
  "id": 123,
  "name": "Sample Product",
  "price": 1000
}

キャッシュ制御に使用する主なヘッダーは以下の通りです。

ヘッダー 用途
Cache-Control キャッシュの動作を制御(max-age、no-cache、no-store等)
ETag リソースのバージョンを識別するタグ
Last-Modified リソースの最終更新日時
Expires キャッシュの有効期限(非推奨、Cache-Controlを優先)

4. Uniform Interface(統一インターフェース)

RESTの最も特徴的な制約であり、クライアントとサーバー間の通信を標準化します。この制約は4つのサブ制約で構成されます。

4.1 リソースの識別

リソースはURIで一意に識別されます。リソースとは、操作の対象となるデータや概念を指します。

良い例:
GET /users/123          # ID 123のユーザーリソース
GET /products/456       # ID 456の商品リソース
GET /orders/789/items   # ID 789の注文に含まれる商品一覧

4.2 表現によるリソース操作

クライアントは、リソースの「表現」を通じてリソースを操作します。同じリソースでも、リクエストヘッダーに応じてJSONやXMLなど異なる形式で表現できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
GET /users/123
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 123,
  "name": "田中太郎",
  "email": "tanaka@example.com"
}

4.3 自己記述的メッセージ

各メッセージには、そのメッセージを処理するために必要な情報がすべて含まれます。Content-Typeヘッダーでメディアタイプを指定し、どのように解釈すべきかを明示します。

4.4 HATEOAS(Hypermedia as the Engine of Application State)

レスポンスには、クライアントが次に実行可能なアクションへのリンク(ハイパーメディア)を含めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "id": 123,
  "name": "田中太郎",
  "email": "tanaka@example.com",
  "_links": {
    "self": { "href": "/users/123" },
    "orders": { "href": "/users/123/orders" },
    "update": { "href": "/users/123", "method": "PUT" },
    "delete": { "href": "/users/123", "method": "DELETE" }
  }
}

HATEOASを実装することで、APIの発見可能性が向上し、クライアントがAPIの構造をハードコードする必要がなくなります。

5. Layered System(階層化システム)

クライアントは、直接サーバーに接続しているのか、中間サーバー(ロードバランサー、キャッシュサーバー、ゲートウェイ等)を経由しているのかを意識する必要がありません。

flowchart LR
    C["クライアント"] --> LB["ロードバランサー"]
    LB --> Cache["キャッシュサーバー"]
    Cache --> GW["APIゲートウェイ"]
    GW --> S1["サーバー1"]
    GW --> S2["サーバー2"]
    GW --> S3["サーバー3"]

階層化によるメリットは以下の通りです。

  • セキュリティ強化(ファイアウォール、認証レイヤーの追加)
  • パフォーマンス向上(キャッシュレイヤー、CDNの活用)
  • スケーラビリティ(ロードバランシングによる負荷分散)

6. Code on Demand(オプション)

唯一のオプション制約です。サーバーからクライアントへ実行可能なコード(JavaScriptなど)を送信し、クライアントの機能を拡張できます。

1
2
<!-- サーバーから送信されるHTML -->
<script src="https://api.example.com/scripts/validation.js"></script>

この制約はオプションであり、すべてのREST APIで実装する必要はありません。Webアプリケーションでは一般的に使用されますが、モバイルアプリやマイクロサービス間通信では使用されないことが多いです。

リソース指向のエンドポイント設計

REST APIのエンドポイント設計では、「リソース」を中心に考えることが重要です。適切なエンドポイント設計は、APIの直感性と保守性を大きく左右します。

リソースとは何か

リソースとは、APIを通じて操作する対象となるエンティティや概念です。具体的には、ユーザー、商品、注文、記事など、ビジネスドメインにおける「もの」を指します。

flowchart TB
    subgraph Resources["リソースの例"]
        direction LR
        A["users<br>ユーザー"]
        B["products<br>商品"]
        C["orders<br>注文"]
        D["articles<br>記事"]
    end
    
    subgraph URI["URIでの表現"]
        direction LR
        E["/users"]
        F["/products"]
        G["/orders"]
        H["/articles"]
    end
    
    A --> E
    B --> F
    C --> G
    D --> H

エンドポイント設計のベストプラクティス

REST APIのエンドポイント設計には、広く受け入れられているベストプラクティスがあります。

1. 名詞を使用し、動詞を避ける

エンドポイントにはリソースを表す名詞を使用し、操作を表す動詞はHTTPメソッドで表現します。

良い例:
GET  /users          # ユーザー一覧を取得
POST /users          # ユーザーを作成
GET  /users/123      # 特定のユーザーを取得

悪い例:
GET  /getUsers       # 動詞がURIに含まれている
POST /createUser     # 動詞がURIに含まれている
GET  /getUserById/123

2. 複数形を使用する

コレクションを表すリソースには複数形を使用します。単数形と複数形が混在するとAPIの一貫性が損なわれます。

良い例:
/users
/products
/orders

悪い例:
/user      # 単数形
/product
/order

3. 階層関係をパスで表現する

リソース間の関係性は、パス階層で表現します。

GET /users/123/orders          # ユーザー123の注文一覧
GET /users/123/orders/456      # ユーザー123の注文456
GET /orders/456/items          # 注文456の商品一覧

ただし、階層が深くなりすぎると可読性が低下します。一般的には2〜3階層までに留めることを推奨します。

4. クエリパラメータで絞り込み・ソート・ページングを行う

リソースのフィルタリング、ソート、ページングにはクエリパラメータを使用します。

GET /users?status=active                    # ステータスで絞り込み
GET /users?sort=created_at&order=desc       # ソート
GET /users?page=2&limit=20                  # ページング
GET /products?category=electronics&min_price=1000

リソース命名の規則

一貫性のあるリソース命名は、APIの使いやすさを向上させます。

規則 良い例 悪い例
小文字を使用 /users /Users
ハイフン区切り /user-profiles /user_profiles, /userProfiles
複数形を使用 /products /product
動詞を避ける /users /getUsers
ファイル拡張子を避ける /users /users.json

HTTPメソッドとCRUD操作の対応

REST APIでは、HTTPメソッドを使用してリソースに対する操作を表現します。各メソッドには明確なセマンティクスがあり、適切に使い分けることが重要です。

HTTPメソッドの一覧と特性

メソッド 操作 べき等性 安全性 リクエストボディ
GET リソースの取得 あり あり なし
POST リソースの作成 なし なし あり
PUT リソースの完全更新 あり なし あり
PATCH リソースの部分更新 なし なし あり
DELETE リソースの削除 あり なし なし(通常)

「べき等性」とは、同じリクエストを複数回実行しても結果が同じになる性質です。「安全性」とは、リソースの状態を変更しない性質を指します。

GETメソッドの使用例

リソースの取得に使用します。レスポンスはキャッシュ可能です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# コレクションの取得
GET /api/v1/users HTTP/1.1
Host: api.example.com
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "users": [
    { "id": 1, "name": "田中太郎", "email": "tanaka@example.com" },
    { "id": 2, "name": "鈴木花子", "email": "suzuki@example.com" }
  ],
  "total": 2,
  "page": 1,
  "limit": 20
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 個別リソースの取得
GET /api/v1/users/1 HTTP/1.1
Host: api.example.com
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 1,
  "name": "田中太郎",
  "email": "tanaka@example.com",
  "created_at": "2026-01-01T10:00:00Z"
}

POSTメソッドの使用例

新しいリソースの作成に使用します。サーバーがリソースのIDを生成する場合に適しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "name": "山田次郎",
  "email": "yamada@example.com",
  "password": "securePassword123"
}

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/users/3

{
  "id": 3,
  "name": "山田次郎",
  "email": "yamada@example.com",
  "created_at": "2026-01-07T12:00:00Z"
}

PUTメソッドの使用例

リソースの完全な更新(置換)に使用します。リクエストボディには更新後の完全なリソース表現を含めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
PUT /api/v1/users/3 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "name": "山田次郎(更新)",
  "email": "yamada.updated@example.com"
}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 3,
  "name": "山田次郎(更新)",
  "email": "yamada.updated@example.com",
  "updated_at": "2026-01-07T13:00:00Z"
}

PATCHメソッドの使用例

リソースの部分的な更新に使用します。変更したいフィールドのみをリクエストボディに含めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
PATCH /api/v1/users/3 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "email": "yamada.new@example.com"
}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 3,
  "name": "山田次郎(更新)",
  "email": "yamada.new@example.com",
  "updated_at": "2026-01-07T14:00:00Z"
}

DELETEメソッドの使用例

リソースの削除に使用します。

1
2
3
4
DELETE /api/v1/users/3 HTTP/1.1
Host: api.example.com

HTTP/1.1 204 No Content

PUTとPATCHの使い分け

PUTとPATCHの違いを正しく理解することは、REST API設計において重要です。

flowchart TB
    subgraph Before["更新前のリソース"]
        A["id: 1<br>name: 田中太郎<br>email: tanaka@example.com<br>age: 30"]
    end
    
    subgraph PUT["PUT /users/1"]
        B["name: 田中太郎<br>email: new@example.com"]
    end
    
    subgraph PATCH["PATCH /users/1"]
        C["email: new@example.com"]
    end
    
    subgraph PutResult["PUT後のリソース"]
        D["id: 1<br>name: 田中太郎<br>email: new@example.com<br>age: null(消失)"]
    end
    
    subgraph PatchResult["PATCH後のリソース"]
        E["id: 1<br>name: 田中太郎<br>email: new@example.com<br>age: 30(保持)"]
    end
    
    Before --> PUT --> PutResult
    Before --> PATCH --> PatchResult
観点 PUT PATCH
更新範囲 リソース全体を置換 指定したフィールドのみ更新
送信データ 完全なリソース表現が必要 変更部分のみ
未送信フィールド null/デフォルト値になる 既存値が保持される
べき等性 あり なし(実装依存)

HTTPステータスコードの適切な使い分け

REST APIでは、HTTPステータスコードを使用してリクエストの処理結果を伝えます。適切なステータスコードを返すことで、クライアントは処理結果を正しく判断し、適切なエラーハンドリングを実装できます。

ステータスコードの分類

HTTPステータスコードは、最初の数字で5つのカテゴリに分類されます。

flowchart LR
    subgraph Codes["HTTPステータスコード"]
        direction TB
        A["1xx: 情報レスポンス"]
        B["2xx: 成功"]
        C["3xx: リダイレクト"]
        D["4xx: クライアントエラー"]
        E["5xx: サーバーエラー"]
    end

2xx: 成功レスポンス

コード 名称 使用場面
200 OK GETリクエストの成功、PUT/PATCHによる更新成功
201 Created POSTによるリソース作成成功
202 Accepted 非同期処理の受付完了
204 No Content DELETEの成功(レスポンスボディなし)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 201 Created の例
POST /api/v1/users HTTP/1.1

HTTP/1.1 201 Created
Location: /api/v1/users/123
Content-Type: application/json

{
  "id": 123,
  "name": "田中太郎"
}
1
2
3
4
# 204 No Content の例
DELETE /api/v1/users/123 HTTP/1.1

HTTP/1.1 204 No Content

4xx: クライアントエラーレスポンス

クライアント側に問題がある場合に返します。

コード 名称 使用場面
400 Bad Request リクエストの構文エラー、バリデーションエラー
401 Unauthorized 認証が必要、認証情報が無効
403 Forbidden 認証済みだがリソースへのアクセス権限がない
404 Not Found リソースが存在しない
405 Method Not Allowed 許可されていないHTTPメソッド
409 Conflict リソースの状態との競合(楽観的ロック失敗等)
422 Unprocessable Entity リクエストは正しいがセマンティックエラー
429 Too Many Requests レート制限超過
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 400 Bad Request の例(バリデーションエラー)
POST /api/v1/users HTTP/1.1
Content-Type: application/json

{
  "name": "",
  "email": "invalid-email"
}

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "入力内容に問題があります",
    "details": [
      { "field": "name", "message": "名前は必須です" },
      { "field": "email", "message": "有効なメールアドレス形式ではありません" }
    ]
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 401 Unauthorized の例
GET /api/v1/users HTTP/1.1

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "認証が必要です"
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 403 Forbidden の例
DELETE /api/v1/admin/settings HTTP/1.1
Authorization: Bearer user-token

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": {
    "code": "FORBIDDEN",
    "message": "この操作を実行する権限がありません"
  }
}

5xx: サーバーエラーレスポンス

サーバー側に問題がある場合に返します。

コード 名称 使用場面
500 Internal Server Error サーバー内部エラー(予期しない例外等)
502 Bad Gateway 上流サーバーからの無効なレスポンス
503 Service Unavailable 一時的なサービス停止(メンテナンス等)
504 Gateway Timeout 上流サーバーからのレスポンスタイムアウト
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 503 Service Unavailable の例
GET /api/v1/users HTTP/1.1

HTTP/1.1 503 Service Unavailable
Retry-After: 3600
Content-Type: application/json

{
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "現在メンテナンス中です",
    "retry_after": 3600
  }
}

401と403の使い分け

401と403は混同されやすいステータスコードですが、明確な違いがあります。

flowchart TB
    A["リクエスト"] --> B{"認証情報はあるか?"}
    B -->|なし| C["401 Unauthorized<br>認証が必要"]
    B -->|あり| D{"認証情報は有効か?"}
    D -->|無効| E["401 Unauthorized<br>認証情報が無効"]
    D -->|有効| F{"権限はあるか?"}
    F -->|なし| G["403 Forbidden<br>アクセス権限がない"]
    F -->|あり| H["200 OK<br>リクエスト成功"]
観点 401 Unauthorized 403 Forbidden
意味 認証が必要/認証失敗 認可されていない
認証状態 未認証/認証エラー 認証済み
対処方法 正しい認証情報で再試行 権限を取得する

API設計で避けるべきアンチパターン

REST APIの設計において、避けるべきアンチパターンを理解することは、良いAPIを設計するうえで重要です。

1. 動詞をURLに含める

悪い例:
POST /api/createUser
GET  /api/getUsers
POST /api/deleteUser/123
POST /api/updateUserEmail

良い例:
POST   /api/users
GET    /api/users
DELETE /api/users/123
PATCH  /api/users/123

HTTPメソッドが操作を表すため、URLに動詞を含める必要はありません。

2. 一貫性のないURL設計

悪い例:
GET /api/users
GET /api/product       # 単数形と複数形の混在
GET /api/Order/123     # 大文字の使用
GET /api/user_profile  # アンダースコアの使用

良い例:
GET /api/users
GET /api/products
GET /api/orders/123
GET /api/user-profiles

3. 適切でないステータスコードの使用

悪い例:
# すべてのエラーで200を返す
HTTP/1.1 200 OK
{
  "success": false,
  "error": "User not found"
}

# リソースが見つからない場合に500を返す
HTTP/1.1 500 Internal Server Error
{
  "message": "User not found"
}

良い例:
# 適切なステータスコードを使用
HTTP/1.1 404 Not Found
{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "指定されたユーザーが見つかりません"
  }
}

4. バージョニングの欠如

悪い例:
GET /api/users  # バージョンがない

良い例:
GET /api/v1/users       # URLパスでバージョニング
GET /api/users          # ヘッダーでバージョニング
X-API-Version: 1

APIのバージョニングには主に以下の方法があります。

方法 メリット デメリット
URLパス /api/v1/users 明確、キャッシュしやすい URLが変わる
クエリパラメータ /api/users?version=1 実装が容易 キャッシュが複雑
カスタムヘッダー X-API-Version: 1 URLがシンプル 発見しにくい
Acceptヘッダー Accept: application/vnd.api.v1+json HTTP標準に準拠 複雑

5. 過度にネストしたURL

悪い例:
GET /api/companies/123/departments/456/employees/789/tasks/012/comments

良い例:
GET /api/tasks/012/comments
GET /api/comments?task_id=012

深いネストは可読性を損ない、URLが長くなりすぎます。2〜3階層に留め、必要に応じてクエリパラメータを使用します。

6. センシティブ情報のURL露出

悪い例:
GET /api/users?password=secret123
GET /api/login?token=abc123xyz

良い例:
POST /api/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "secret123"
}

URLはブラウザ履歴やサーバーログに記録されるため、パスワードやトークンなどのセンシティブ情報はリクエストボディやヘッダーで送信します。

7. 不十分なエラーレスポンス

悪い例:
HTTP/1.1 400 Bad Request
{
  "error": "Invalid request"
}

良い例:
HTTP/1.1 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "入力内容に問題があります",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "有効なメールアドレス形式ではありません"
      }
    ],
    "request_id": "req_abc123",
    "documentation_url": "https://api.example.com/docs/errors#VALIDATION_ERROR"
  }
}

クライアントが問題を特定し、対処できる十分な情報を提供することが重要です。

REST API設計チェックリスト

API設計時に確認すべきポイントをチェックリストとしてまとめます。

エンドポイント設計

  • リソースは名詞で表現されているか
  • 複数形で統一されているか
  • 小文字とハイフン区切りで統一されているか
  • URLに動詞が含まれていないか
  • 階層が深すぎないか(2〜3階層以内)

HTTPメソッド

  • GETはリソース取得のみに使用しているか
  • POSTは新規作成に使用しているか
  • PUT/PATCHは更新に適切に使い分けているか
  • DELETEは削除のみに使用しているか

ステータスコード

  • 成功時に適切な2xxコードを返しているか
  • 作成成功時に201と Locationヘッダーを返しているか
  • クライアントエラーに4xxを使用しているか
  • サーバーエラーに5xxを使用しているか
  • 401と403を正しく使い分けているか

レスポンス

  • 一貫したレスポンス構造になっているか
  • エラーレスポンスに十分な情報が含まれているか
  • ページングはクエリパラメータで実装しているか
  • 適切なContent-Typeが設定されているか

セキュリティとバージョニング

  • APIバージョンが明示されているか
  • センシティブ情報がURLに露出していないか
  • 認証が必要なエンドポイントは保護されているか

まとめ

本記事では、REST APIの設計原則を体系的に解説しました。要点を整理します。

RESTの6つの制約条件(Client-Server、Stateless、Cacheable、Uniform Interface、Layered System、Code on Demand)を理解し、遵守することで、スケーラブルで保守性の高いAPIを設計できます。

エンドポイント設計では、リソース指向のアプローチを採用し、名詞・複数形・小文字を使用した一貫性のあるURL設計を心がけます。HTTPメソッドはCRUD操作に適切に対応させ、ステータスコードはリクエストの処理結果を正確に反映するものを選択します。

アンチパターンを避けることも同様に重要です。動詞のURL混入、一貫性のない設計、不適切なステータスコード、バージョニングの欠如などは、APIの品質を低下させる要因となります。

REST APIの設計は、単なる技術的な規約ではなく、APIを利用する開発者の体験を左右する重要な設計活動です。本記事で解説した原則とベストプラクティスを参考に、使いやすく保守性の高いAPIを設計してください。

参考リンク