OpenAPI

OpenAPI 仕様 完全ガイド — API設計・開発・運用のための包括的リファレンス


目次

  1. はじめに
  2. OpenAPI の歴史と背景
  3. OpenAPI 仕様の基本構造
  4. Info オブジェクトとメタデータ
  5. Servers オブジェクト
  6. Paths オブジェクトとオペレーション
  7. パラメータの定義
  8. リクエストボディ
  9. レスポンスの定義
  10. スキーマオブジェクトとデータモデリング
  11. コンポーネントと再利用
  12. 認証・認可 (Security Schemes)
  13. コールバックとWebhooks
  14. リンクオブジェクト
  15. タグとドキュメント構造化
  16. 拡張フィールド (Specification Extensions)
  17. OpenAPI 3.0 と 3.1 の差分
  18. OpenAPI ツールエコシステム
  19. API設計のベストプラクティス
  20. 実践的なAPI設計例:ECサイトAPI
  21. CI/CDパイプラインへの統合
  22. マイクロサービスアーキテクチャにおけるOpenAPI
  23. パフォーマンスとスケーラビリティの考慮事項
  24. まとめと今後の展望

1. はじめに

1.1 本書の目的

本書は、OpenAPI 仕様 (OpenAPI Specification, OAS) の全容を包括的に解説する技術リファレンスである。API の設計・開発・テスト・運用に携わるソフトウェアエンジニア、アーキテクト、テクニカルリードを主な対象読者とし、OpenAPI の基礎概念から高度な設計パターン、実運用における活用手法までを体系的にまとめている。

1.2 OpenAPI とは何か

OpenAPI 仕様は、RESTful API のインターフェースを記述するための、言語に依存しない標準的なフォーマットである。YAML または JSON で記述され、API が提供するエンドポイント、各エンドポイントで利用可能な操作(HTTPメソッド)、操作のパラメータ、リクエスト/レスポンスの構造、認証方法などを機械可読な形式で定義する。

OpenAPI 仕様の本質的な価値は、API の契約 (Contract) を明示的に定義することにある。これにより、API の提供者と利用者の間で共通の理解が形成され、開発プロセス全体の効率が大幅に向上する。

1.3 API ファーストの設計思想

現代のソフトウェア開発において、「API ファースト」のアプローチは不可欠な設計思想となっている。API ファーストとは、実装に先立って API の仕様を定義し、その仕様を基にフロントエンド・バックエンド・モバイルアプリなどの各コンポーネントの開発を並行して進める手法である。

  ① API 設計 (OpenAPI仕様策定)
       |
       v
  ② レビュー & フィードバック
       |
       v
  ③ 仕様確定
       |
       +----------+-----------+-----------+
       v          v           v           v
  バックエンド  フロントエンド  モバイル    テスト
  実装         実装          実装       自動生成
       |          |           |           |
       +----------+-----------+-----------+
                  |
                  v
            ④ 統合テスト --> ⑤ デプロイ

OpenAPI はこの API ファーストアプローチを実現するための中核的なツールである。


2. OpenAPI の歴史と背景

2.1 Swagger から OpenAPI へ

OpenAPI 仕様の前身は、2011年に Tony Tam によって開発された Swagger である。

イベント
2011Swagger 1.0 リリース
2014Swagger 2.0 リリース -- JSON Schema ベースのスキーマ定義を導入
2015SmartBear Software が Swagger を買収。Linux Foundation 傘下の OpenAPI Initiative (OAI) を設立
2017OpenAPI Specification 3.0.0 リリース -- 大幅な構造改善
2021OpenAPI Specification 3.1.0 リリース -- JSON Schema との完全互換を実現
2024OpenAPI 3.1.1 リリース -- 軽微な修正と明確化

2.2 OpenAPI Initiative (OAI)

OpenAPI Initiative は、Linux Foundation の傘下で OpenAPI 仕様の策定・推進を担う業界団体である。Google、Microsoft、IBM、Amazon、PayPal など、主要なテクノロジー企業がメンバーとして参加している。

2.3 関連する他の API 記述仕様

仕様対象形式特徴
OpenAPIREST APIYAML/JSON最も広く採用されている REST API 記述標準
RAMLREST APIYAMLMuleSoft が推進。階層的な記述が特徴
API BlueprintREST APIMarkdownApiary が開発。可読性を重視
GraphQL SchemaGraphQL APISDL型システムベースのスキーマ定義
gRPC/Protocol BuffersRPC API.proto高性能なバイナリプロトコル
AsyncAPI非同期 APIYAML/JSONイベント駆動型 API 向け。OpenAPI と構造が類似

3. OpenAPI 仕様の基本構造

3.1 ドキュメントのルート構造

openapi: "3.1.0"          # 必須: OpenAPI仕様のバージョン
info:                      # 必須: APIのメタデータ
  title: Sample API
  version: "1.0.0"
servers:                   # オプション: APIサーバーの情報
  - url: https://api.example.com/v1
paths:                     # オプション(3.1): エンドポイントの定義
  /users:
    get:
      summary: ユーザー一覧取得
components:                # オプション: 再利用可能なコンポーネント
  schemas: {}
  responses: {}
  parameters: {}
  securitySchemes: {}
security:                  # オプション: グローバルセキュリティ要件
  - bearerAuth: []
tags:                      # オプション: タグ定義
  - name: users
    description: ユーザー管理
externalDocs:              # オプション: 外部ドキュメント
  url: https://docs.example.com
webhooks:                  # オプション(3.1): Webhook定義
  newUser:
    post:
      summary: 新規ユーザー通知

3.2 YAML と JSON

OpenAPI 仕様は YAML と JSON の両方で記述可能である。実務では YAML が広く採用されているが、これは可読性が高く、コメントを記述できるためである。

3.3 $ref による参照

# 同一ドキュメント内の参照
$ref: '#/components/schemas/User'

# 外部ファイルの参照
$ref: './models/user.yaml'

# 外部ファイル内の特定パスの参照
$ref: './models/user.yaml#/properties/address'

大規模な API 仕様では、ファイルを機能単位で分割し、$ref で結合するアプローチが推奨される。

api/
├── openapi.yaml          # ルートドキュメント
├── paths/
│   ├── users.yaml
│   ├── orders.yaml
│   └── products.yaml
├── components/
│   ├── schemas/
│   ├── parameters/
│   ├── responses/
│   └── securitySchemes/
└── examples/

4. Info オブジェクトとメタデータ

info:
  title: "決済プラットフォーム API"
  summary: "オンライン決済処理のための統合 API"    # 3.1 で追加
  description: |
    ## 概要
    決済プラットフォーム API は、オンライン決済処理に必要な
    すべての機能を提供する RESTful API です。

    ## 主な機能
    - クレジットカード決済
    - 銀行振込
    - 電子マネー決済
    - 決済履歴の照会
    - 返金処理

    ## レート制限
    - 認証済みリクエスト: 1000 リクエスト/分
    - 未認証リクエスト: 60 リクエスト/分
  termsOfService: "https://example.com/terms"
  contact:
    name: "API サポートチーム"
    url: "https://developer.example.com/support"
    email: "api-support@example.com"
  license:
    name: "Apache 2.0"
    identifier: "Apache-2.0"    # 3.1 で追加
  version: "3.2.1"

バージョニング戦略:

戦略特徴
URL パスベース/v1/users, /v2/users最も直感的。キャッシュが容易
クエリパラメータ/users?version=2URL が変わらない
ヘッダーベースAccept: application/vnd.api+json;version=2URL がクリーン
セマンティックバージョニング1.2.3変更の影響度が明確

5. Servers オブジェクト

5.1 基本的なサーバー定義

servers:
  - url: https://api.example.com/v1
    description: 本番環境
  - url: https://staging-api.example.com/v1
    description: ステージング環境
  - url: https://sandbox-api.example.com/v1
    description: サンドボックス環境(テスト用)
  - url: http://localhost:3000/v1
    description: ローカル開発環境

5.2 サーバー変数

servers:
  - url: https://{environment}.api.example.com:{port}/{basePath}
    description: 環境変数付きサーバー
    variables:
      environment:
        default: production
        enum: [production, staging, sandbox]
        description: デプロイ環境
      port:
        default: "443"
        enum: ["443", "8443"]
      basePath:
        default: v1

  - url: https://{region}.api.example.com/v1
    description: リージョン別サーバー
    variables:
      region:
        default: ap-northeast-1
        enum: [us-east-1, us-west-2, eu-west-1, ap-northeast-1]

5.3 パスレベルおよびオペレーションレベルのサーバー

サーバー定義はパスレベルやオペレーションレベルでも上書きできる。

paths:
  /files/upload:
    servers:
      - url: https://upload.example.com/v1
        description: ファイルアップロード専用サーバー

6. Paths オブジェクトとオペレーション

6.1 パスの定義

paths:
  /users:
    get:
      operationId: listUsers
      summary: ユーザー一覧の取得
      tags: [users]
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: per_page
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        '200':
          description: ユーザー一覧の取得に成功
        '401':
          description: 認証エラー

    post:
      operationId: createUser
      summary: 新規ユーザーの作成
      tags: [users]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: ユーザーの作成に成功
        '400':
          description: リクエストが不正
        '409':
          description: 既に存在するメールアドレス

  /users/{userId}:
    get:
      operationId: getUser
      summary: ユーザー詳細の取得
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: ユーザー詳細の取得に成功
        '404':
          description: ユーザーが見つからない

    put:
      operationId: updateUser
      summary: ユーザー情報の更新

    delete:
      operationId: deleteUser
      summary: ユーザーの削除
      responses:
        '204':
          description: ユーザーの削除に成功

    patch:
      operationId: patchUser
      summary: ユーザー情報の部分更新
      requestBody:
        content:
          application/json-patch+json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/JsonPatchOperation'
          application/merge-patch+json:
            schema:
              $ref: '#/components/schemas/UserPatch'

6.2 Operation オブジェクトの全フィールド

paths:
  /example:
    get:
      tags: [examples]           # タグ(分類用)
      summary: 操作の概要        # 短い説明(1行)
      description: |             # 詳細な説明(Markdown対応)
        操作の詳細な説明。
      externalDocs:              # 外部ドキュメント
        url: https://docs.example.com/api/example
      operationId: getExample    # 一意識別子(コード生成で使用)
      parameters: []             # パラメータ一覧
      requestBody: {}            # リクエストボディ
      responses: {}              # レスポンス定義
      callbacks: {}              # コールバック定義
      deprecated: false          # 非推奨フラグ
      security:                  # セキュリティ要件
        - bearerAuth: []
      servers:                   # オペレーション固有のサーバー
        - url: https://api.example.com

6.3 operationId の命名規則

operationId: listUsers        # GET /users
operationId: createUser       # POST /users
operationId: getUser          # GET /users/{id}
operationId: updateUser       # PUT /users/{id}
operationId: deleteUser       # DELETE /users/{id}
operationId: getUserOrders    # GET /users/{id}/orders

7. パラメータの定義

7.1 パラメータの種類

parameters:
  # 1. パスパラメータ
  - name: userId
    in: path
    required: true
    schema:
      type: string
      format: uuid

  # 2. クエリパラメータ
  - name: status
    in: query
    required: false
    schema:
      type: string
      enum: [active, inactive, suspended]

  # 3. ヘッダーパラメータ
  - name: X-Request-Id
    in: header
    required: false
    schema:
      type: string
      format: uuid

  # 4. クッキーパラメータ
  - name: session_id
    in: cookie
    schema:
      type: string

7.2 パラメータのシリアライゼーション

stylein配列例 ([1,2,3])オブジェクト例 ({a:1,b:2})
matrixpath;id=1;id=2;id=3;a=1;b=2
labelpath.1.2.3.a=1.b=2
formquery, cookieid=1&id=2&id=3a=1&b=2
simplepath, header1,2,3a,1,b,2
spaceDelimitedqueryid=1%202%203N/A
pipeDelimitedqueryid=1|2|3N/A
deepObjectqueryN/Afilter[a]=1&filter[b]=2

8. リクエストボディ

8.1 基本的なリクエストボディ定義

paths:
  /users:
    post:
      requestBody:
        description: 作成するユーザーの情報
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, name, password]
              properties:
                email:
                  type: string
                  format: email
                  example: "user@example.com"
                name:
                  type: string
                  minLength: 1
                  maxLength: 100
                  example: "田中太郎"
                password:
                  type: string
                  format: password
                  minLength: 8
                  maxLength: 128
                  pattern: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$'
                role:
                  type: string
                  enum: [user, admin, moderator]
                  default: user
                profile:
                  type: object
                  properties:
                    bio:
                      type: string
                      maxLength: 500
                    avatar_url:
                      type: string
                      format: uri
                    timezone:
                      type: string
                      example: "Asia/Tokyo"
            examples:
              basic:
                summary: 基本的なユーザー作成
                value:
                  email: "tanaka@example.com"
                  name: "田中太郎"
                  password: "SecureP@ss1"

8.2 マルチパートフォーム(ファイルアップロード)

requestBody:
  content:
    multipart/form-data:
      schema:
        type: object
        required: [file]
        properties:
          file:
            type: string
            format: binary
          description:
            type: string
          tags:
            type: array
            items:
              type: string
      encoding:
        file:
          contentType: application/pdf, image/jpeg, image/png
        tags:
          style: form
          explode: true

9. レスポンスの定義

9.1 レスポンスオブジェクトの構造

responses:
  '200':
    description: ユーザー情報の取得に成功
    headers:
      X-Request-Id:
        schema:
          type: string
          format: uuid
      X-RateLimit-Limit:
        schema:
          type: integer
      X-RateLimit-Remaining:
        schema:
          type: integer
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/User'
        examples:
          active_user:
            summary: アクティブなユーザー
            value:
              id: "550e8400-e29b-41d4-a716-446655440000"
              email: "tanaka@example.com"
              name: "田中太郎"
              status: "active"
    links:
      GetUserOrders:
        operationId: getUserOrders
        parameters:
          userId: '$response.body#/id'

9.2 RFC 7807 準拠エラーレスポンス

components:
  schemas:
    ProblemDetails:
      type: object
      required: [type, title, status]
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
          format: uri
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
              code:
                type: string
        trace_id:
          type: string

  responses:
    BadRequest:
      description: リクエストが不正
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Unauthorized:
      description: 認証が必要
    Forbidden:
      description: アクセス権限がない
    NotFound:
      description: リソースが見つからない
    TooManyRequests:
      description: レート制限超過
      headers:
        Retry-After:
          schema:
            type: integer
    InternalServerError:
      description: サーバー内部エラー

9.3 ページネーションレスポンスパターン

components:
  schemas:
    PaginationMeta:
      type: object
      properties:
        current_page:
          type: integer
        per_page:
          type: integer
        total_pages:
          type: integer
        total_count:
          type: integer
        has_next:
          type: boolean
        has_prev:
          type: boolean

    PaginatedUserResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          type: object
          properties:
            self:
              type: string
              format: uri
            first:
              type: string
              format: uri
            prev:
              type: string
              format: uri
              nullable: true
            next:
              type: string
              format: uri
              nullable: true
            last:
              type: string
              format: uri

10. スキーマオブジェクトとデータモデリング

10.1 基本データ型

typeformat説明
string(なし)文字列"Hello"
stringdate日付 (RFC 3339)"2024-01-15"
stringdate-time日時 (RFC 3339)"2024-01-15T09:30:00Z"
stringemailメールアドレス"user@example.com"
stringuriURI"https://example.com"
stringuuidUUID"550e8400-..."
stringpasswordパスワード(UIで隠蔽)"********"
stringbyteBase64エンコード"SGVsbG8="
stringbinaryバイナリデータ(ファイルなど)
integerint3232ビット整数42
integerint6464ビット整数9007199254740992
numberfloat単精度浮動小数点3.14
numberdouble倍精度浮動小数点3.141592653589793
boolean(なし)真偽値true
array(なし)配列[1, 2, 3]
object(なし)オブジェクト{"key": "value"}
null(なし)null値 (3.1)null

10.2 バリデーション制約

components:
  schemas:
    ProductCreateRequest:
      type: object
      required: [name, price, category]
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        price:
          type: number
          minimum: 0
          exclusiveMinimum: true
          maximum: 99999999.99
          multipleOf: 0.01
        quantity:
          type: integer
          minimum: 0
          maximum: 999999
          default: 0
        sku:
          type: string
          pattern: '^[A-Z]{2}-\d{6}$'
        tags:
          type: array
          items:
            type: string
          minItems: 0
          maxItems: 20
          uniqueItems: true
        category:
          type: string
          enum: [electronics, clothing, food, books, other]
        attributes:
          type: object
          additionalProperties:
            type: string
          maxProperties: 50

10.3 スキーマの組み合わせ (allOf, oneOf, anyOf)

allOf -- 継承・ミックスイン

components:
  schemas:
    BaseEntity:
      type: object
      required: [id, created_at, updated_at]
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true

    User:
      allOf:
        - $ref: '#/components/schemas/BaseEntity'
        - type: object
          required: [email, name]
          properties:
            email:
              type: string
              format: email
            name:
              type: string
            role:
              type: string
              enum: [user, admin, moderator]

oneOf -- 排他的選択 + Discriminator

    PaymentMethod:
      oneOf:
        - $ref: '#/components/schemas/CreditCardPayment'
        - $ref: '#/components/schemas/BankTransferPayment'
        - $ref: '#/components/schemas/DigitalWalletPayment'
      discriminator:
        propertyName: payment_type
        mapping:
          credit_card: '#/components/schemas/CreditCardPayment'
          bank_transfer: '#/components/schemas/BankTransferPayment'
          digital_wallet: '#/components/schemas/DigitalWalletPayment'

anyOf -- 1つ以上に一致

    NotificationTarget:
      anyOf:
        - $ref: '#/components/schemas/EmailNotification'
        - $ref: '#/components/schemas/SmsNotification'
        - $ref: '#/components/schemas/PushNotification'

10.4 readOnly / writeOnly

    User:
      properties:
        id:
          type: string
          readOnly: true      # レスポンスのみ
        password:
          type: string
          writeOnly: true     # リクエストのみ

10.5 Nullable (OpenAPI 3.1)

# 3.0: nullable: true
# 3.1: type 配列を使用
middle_name:
  type: [string, "null"]

11. コンポーネントと再利用

components:
  schemas: {}           # データモデル
  responses: {}         # レスポンス
  parameters: {}        # パラメータ
  examples: {}          # サンプルデータ
  requestBodies: {}     # リクエストボディ
  headers: {}           # ヘッダー
  securitySchemes: {}   # セキュリティスキーム
  links: {}             # リンク
  callbacks: {}         # コールバック
  pathItems: {}         # パスアイテム (3.1)

再利用可能なパラメータの例:

components:
  parameters:
    PageParam:
      name: page
      in: query
      schema:
        type: integer
        minimum: 1
        default: 1
    PerPageParam:
      name: per_page
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20
    SortByParam:
      name: sort_by
      in: query
      schema:
        type: string
        enum: [created_at, updated_at, name]
        default: created_at
    RequestIdHeader:
      name: X-Request-Id
      in: header
      schema:
        type: string
        format: uuid

12. 認証・認可 (Security Schemes)

12.1 セキュリティスキームの種類

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    BasicAuth:
      type: http
      scheme: basic
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://auth.example.com/oauth2/authorize
          tokenUrl: https://auth.example.com/oauth2/token
          refreshUrl: https://auth.example.com/oauth2/refresh
          scopes:
            read:users: ユーザー情報の参照
            write:users: ユーザー情報の更新
            admin: 管理者権限
        clientCredentials:
          tokenUrl: https://auth.example.com/oauth2/token
          scopes:
            service:read: サービス間読み取り
    OpenIdConnect:
      type: openIdConnect
      openIdConnectUrl: https://auth.example.com/.well-known/openid-configuration
    MutualTLS:
      type: mutualTLS

12.2 セキュリティ要件の適用

# グローバル(OR 関係)
security:
  - BearerAuth: []
  - OAuth2: [read:users]

# オペレーション固有
paths:
  /public/health:
    get:
      security: []           # 認証不要
  /admin/settings:
    put:
      security:
        - BearerAuth: []     # AND 関係
          ApiKeyAuth: []
        - OAuth2: [admin]    # OR 関係

13. コールバックとWebhooks

13.1 コールバック

paths:
  /webhooks/subscribe:
    post:
      callbacks:
        orderCreated:
          '{$request.body#/callback_url}':
            post:
              summary: 注文作成通知
              requestBody:
                content:
                  application/json:
                    schema:
                      type: object
                      properties:
                        event_type:
                          type: string
                        data:
                          $ref: '#/components/schemas/Order'
              responses:
                '200':
                  description: 通知受信成功

13.2 Webhooks (OpenAPI 3.1)

webhooks:
  userRegistered:
    post:
      operationId: onUserRegistered
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [event, data]
              properties:
                event:
                  type: string
                  enum: ["user.registered"]
                data:
                  type: object
                  properties:
                    user_id:
                      type: string
                      format: uuid
                    email:
                      type: string
                      format: email
      responses:
        '200':
          description: Webhook 受信確認

14. リンクオブジェクト

Link オブジェクトは HATEOAS パターンを表現する。

responses:
  '201':
    links:
      GetCreatedUser:
        operationId: getUser
        parameters:
          userId: '$response.body#/id'
      ListUserOrders:
        operationId: listUserOrders
        parameters:
          userId: '$response.body#/id'

Runtime Expression:

説明
$urlリクエスト URL
$methodHTTP メソッド
$statusCodeステータスコード
$request.header.{name}リクエストヘッダー
$request.body#/pointerリクエストボディ (JSON Pointer)
$response.header.{name}レスポンスヘッダー
$response.body#/pointerレスポンスボディ (JSON Pointer)

15. タグとドキュメント構造化

tags:
  - name: users
    description: ユーザー管理
    externalDocs:
      url: https://docs.example.com/guides/users
  - name: orders
    description: 注文管理
  - name: admin
    description: 管理者用
    x-audience: internal

16. 拡張フィールド (Specification Extensions)

x- プレフィックスで任意のフィールドを追加できる。

paths:
  /users:
    get:
      x-rate-limit:
        requests: 1000
        period: 60
      x-code-samples:
        - lang: curl
          source: |
            curl -X GET "https://api.example.com/v1/users" \
              -H "Authorization: Bearer YOUR_TOKEN"
拡張フィールド用途ツール
x-code-samplesコードサンプルRedoc
x-internal内部API マーキング各種
x-deprecated-date非推奨日付カスタム
x-tagGroupsタグのグループ化Redoc

17. OpenAPI 3.0 と 3.1 の差分

項目OpenAPI 3.0OpenAPI 3.1
JSON Schema 互換拡張サブセット完全互換 (Draft 2020-12)
nullablenullable: truetype: ["string", "null"]
exclusiveMinimumbooleannumber
const / if/then/else非サポートサポート
Webhooks非サポートトップレベルでサポート
pathItems コンポーネント非サポートサポート
info.summaryなし追加
license.identifierなし追加 (SPDX)
paths の必須性必須オプション

17.1 JSON Schema 新機能の例

# if/then/else
ShippingAddress:
  type: object
  if:
    properties:
      country:
        const: "JP"
  then:
    properties:
      postal_code:
        pattern: '^\d{3}-\d{4}$'

# prefixItems (タプル型)
GeoCoordinate:
  type: array
  prefixItems:
    - type: number
      minimum: -90
      maximum: 90
    - type: number
      minimum: -180
      maximum: 180
  items: false

# patternProperties
I18nContent:
  type: object
  patternProperties:
    '^[a-z]{2}(-[A-Z]{2})?$':
      type: string

18. OpenAPI ツールエコシステム

ドキュメント生成

ツール特徴
Swagger UIインタラクティブ、Try it out 機能
Redoc美しい3カラムレイアウト
Stoplight ElementsReact コンポーネント

コード生成

ツール対応言語
OpenAPI Generator50+ 言語
oapi-codegenGo
openapi-typescriptTypeScript
Kiota多言語

バリデーション

# .spectral.yaml
extends: [spectral:oas]
rules:
  operation-operationId:
    severity: error
  oas3-server-https:
    severity: error
    given: "$.servers[*].url"
    then:
      function: pattern
      functionOptions:
        match: "^https://"

テスト

ツール用途
Dredd仕様 vs 実装テスト
Schemathesisプロパティベーステスト
Prismモックサーバー自動生成

19. API設計のベストプラクティス

19.1 RESTful URL 設計

paths:
  /users:                     # コレクション(複数形名詞)
  /users/{userId}:            # 個別リソース
  /users/{userId}/orders:     # サブリソース
# 非推奨: /getUsers, /user, /user_list, /Users

19.2 HTTP ステータスコード

コード用途
200 OKGET, PUT, PATCH
201 CreatedPOST
204 No ContentDELETE
400 Bad Requestリクエスト不正
401 Unauthorized認証必要
403 Forbidden権限不足
404 Not Foundリソースなし
409 Conflict競合
429 Too Many Requestsレート制限
500 Internal Server Errorサーバーエラー

19.3 冪等性の確保

paths:
  /orders:
    post:
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            format: uuid

19.4 Deprecation 戦略

paths:
  /v1/users:
    get:
      deprecated: true
      x-deprecated-date: "2024-06-01"
      x-removal-date: "2025-06-01"
      x-successor: "/v2/users"
      responses:
        '200':
          headers:
            Sunset:
              schema:
                type: string
              example: "2025-06-01T00:00:00Z"

20. 実践的なAPI設計例:ECサイトAPI

以下に EC サイト向け API の包括的な設計概要を示す。

openapi: "3.1.0"
info:
  title: "EC サイト API"
  version: "1.0.0"
servers:
  - url: https://api.ec-example.com/v1
tags:
  - name: auth        # 認証・認可
  - name: products    # 商品管理
  - name: cart        # ショッピングカート
  - name: orders      # 注文管理
  - name: payments    # 決済処理
security:
  - BearerAuth: []
paths:
  /auth/login:
    post:
      tags: [auth]
      security: []
      # トークン発行
  /auth/refresh:
    post:
      tags: [auth]
      security: []
      # トークンリフレッシュ
  /products:
    get:
      tags: [products]
      security: []
      # 商品一覧(ページネーション、フィルタ、ソート対応)
  /products/{productId}:
    get:
      tags: [products]
      security: []
  /cart:
    get:
      tags: [cart]
  /cart/items:
    post:
      tags: [cart]
      # 商品追加
  /cart/items/{itemId}:
    delete:
      tags: [cart]
  /orders:
    get:
      tags: [orders]
    post:
      tags: [orders]
      # 冪等キー対応、Link オブジェクトで決済へ誘導
  /orders/{orderId}:
    get:
      tags: [orders]
  /orders/{orderId}/payments:
    post:
      tags: [payments]
      # 冪等キー対応、コールバックで決済結果通知

21. CI/CDパイプラインへの統合

21.1 ワークフロー

CI:  バリデーション -> 破壊的変更検出 -> コード生成 -> Contract テスト -> ドキュメント生成
CD:  ドキュメントサイト更新 -> SDK 公開 -> API ゲートウェイ設定更新

21.2 GitHub Actions の設定例

name: API Specification Validation
on:
  pull_request:
    paths: ['api/**', 'openapi.yaml']
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npx @stoplight/spectral-cli lint openapi.yaml --fail-severity=error
      - uses: oasdiff/oasdiff-action/breaking@main
        with:
          base: 'https://raw.githubusercontent.com/${{ github.repository }}/main/openapi.yaml'
          revision: 'openapi.yaml'
  generate-sdk:
    needs: validate
    strategy:
      matrix:
        language: [typescript-axios, python, go, java]
    steps:
      - uses: openapi-generators/openapitools-generator-action@v1
        with:
          generator: ${{ matrix.language }}
          openapi-file: openapi.yaml

21.3 モックサーバー

prism mock openapi.yaml            # 静的モック
prism mock openapi.yaml --dynamic  # 動的モック
prism proxy openapi.yaml https://api.example.com  # プロキシ

22. マイクロサービスアーキテクチャにおけるOpenAPI

22.1 サービス間の契約

API Registry に仕様を集約し、ドキュメント生成・SDK 生成・Contract テストに活用する。

22.2 API ゲートウェイ統合

x-kong-plugin-rate-limiting:
  config:
    second: 10
    minute: 100
    policy: redis
x-kong-plugin-cors:
  config:
    origins: ["https://app.example.com"]
    methods: [GET, POST, PUT, DELETE]
    max_age: 3600

22.3 分散トレーシング

components:
  parameters:
    TraceParentHeader:
      name: traceparent
      in: header
      schema:
        type: string
        pattern: '^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$'
      description: W3C Trace Context

23. パフォーマンスとスケーラビリティの考慮事項

23.1 大規模仕様の管理

api/
├── openapi.yaml              # エントリーポイント
├── paths/
│   ├── auth/
│   ├── users/
│   ├── orders/
│   └── products/
├── components/
│   ├── schemas/
│   ├── parameters/
│   ├── responses/
│   └── securitySchemes/
└── examples/
npx @redocly/cli bundle api/openapi.yaml -o bundled-openapi.yaml
npx @redocly/cli split bundled-openapi.yaml --outDir api/

23.2 キャッシュ戦略

responses:
  '200':
    headers:
      Cache-Control:
        example: "public, max-age=300"
      ETag:
        schema:
          type: string
  '304':
    description: キャッシュが有効

23.3 SSE ストリーミング

paths:
  /events/stream:
    get:
      responses:
        '200':
          content:
            text/event-stream:
              schema:
                type: string

24. まとめと今後の展望

24.1 OpenAPI の現状

OpenAPI は REST API のインターフェース定義の事実上の標準として、以下を包括的にカバーする。

  1. API 設計と記述: パス、オペレーション、パラメータ、スキーマ
  2. セキュリティ: OAuth 2.0, OpenID Connect, API Key, JWT, mTLS
  3. 非同期通信: コールバックと Webhook
  4. データモデリング: JSON Schema ベースの強力なスキーマ定義
  5. ドキュメンテーション: Markdown 対応のリッチな記述
  6. コード生成: 50+ 言語対応
  7. テスト: Contract テスト、モックサーバー、プロパティベーステスト
  8. CI/CD 統合: バリデーション、破壊的変更検出、自動デプロイ

24.2 OpenAPI 4.0 (Moonwalk) への展望

  • 署名 (Signatures): API の意味的変更の追跡
  • オーバーレイ (Overlays): 環境差分管理
  • ワークフロー記述: 複数 API 呼び出しの連携定義
  • パフォーマンス改善: 大規模仕様の処理効率向上

24.3 API エコシステムの進化

AI と API の融合: LLM の Function Calling で OpenAPI スキーマが広く採用され、AI エージェントが API を自動的に発見・理解・呼び出す時代が到来している。

イベント駆動との統合: AsyncAPI との連携で同期・非同期 API を統一管理。

ゼロトラストセキュリティ: API ゲートウェイやサービスメッシュとの統合で実行時ポリシーに直接活用。

24.4 結び

OpenAPI 仕様の習得は現代のソフトウェアエンジニアにとって不可欠なスキルである。API ファーストの設計思想を実践し、OpenAPI の豊富な機能を活用することで、より堅牢で保守性の高い API を効率的に設計・開発・運用することが可能になる。


参考文献

  1. OpenAPI Specification 3.1.0 -- https://spec.openapis.org/oas/v3.1.0
  2. OpenAPI Initiative -- https://www.openapis.org/
  3. JSON Schema Draft 2020-12 -- https://json-schema.org/draft/2020-12/json-schema-core
  4. RFC 7807: Problem Details for HTTP APIs -- https://tools.ietf.org/html/rfc7807
  5. RFC 6749: OAuth 2.0 Authorization Framework -- https://tools.ietf.org/html/rfc6749
  6. Swagger/OpenAPI Tools -- https://openapi.tools/
  7. OpenAPI Generator -- https://openapi-generator.tech/
  8. Spectral -- https://github.com/stoplightio/spectral
  9. Redocly CLI -- https://redocly.com/docs/cli/
  10. AsyncAPI Specification -- https://www.asyncapi.com/