OpenAPI
OpenAPI 仕様 完全ガイド — API設計・開発・運用のための包括的リファレンス
目次
- はじめに
- OpenAPI の歴史と背景
- OpenAPI 仕様の基本構造
- Info オブジェクトとメタデータ
- Servers オブジェクト
- Paths オブジェクトとオペレーション
- パラメータの定義
- リクエストボディ
- レスポンスの定義
- スキーマオブジェクトとデータモデリング
- コンポーネントと再利用
- 認証・認可 (Security Schemes)
- コールバックとWebhooks
- リンクオブジェクト
- タグとドキュメント構造化
- 拡張フィールド (Specification Extensions)
- OpenAPI 3.0 と 3.1 の差分
- OpenAPI ツールエコシステム
- API設計のベストプラクティス
- 実践的なAPI設計例:ECサイトAPI
- CI/CDパイプラインへの統合
- マイクロサービスアーキテクチャにおけるOpenAPI
- パフォーマンスとスケーラビリティの考慮事項
- まとめと今後の展望
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 である。
| 年 | イベント |
|---|---|
| 2011 | Swagger 1.0 リリース |
| 2014 | Swagger 2.0 リリース -- JSON Schema ベースのスキーマ定義を導入 |
| 2015 | SmartBear Software が Swagger を買収。Linux Foundation 傘下の OpenAPI Initiative (OAI) を設立 |
| 2017 | OpenAPI Specification 3.0.0 リリース -- 大幅な構造改善 |
| 2021 | OpenAPI Specification 3.1.0 リリース -- JSON Schema との完全互換を実現 |
| 2024 | OpenAPI 3.1.1 リリース -- 軽微な修正と明確化 |
2.2 OpenAPI Initiative (OAI)
OpenAPI Initiative は、Linux Foundation の傘下で OpenAPI 仕様の策定・推進を担う業界団体である。Google、Microsoft、IBM、Amazon、PayPal など、主要なテクノロジー企業がメンバーとして参加している。
2.3 関連する他の API 記述仕様
| 仕様 | 対象 | 形式 | 特徴 |
|---|---|---|---|
| OpenAPI | REST API | YAML/JSON | 最も広く採用されている REST API 記述標準 |
| RAML | REST API | YAML | MuleSoft が推進。階層的な記述が特徴 |
| API Blueprint | REST API | Markdown | Apiary が開発。可読性を重視 |
| GraphQL Schema | GraphQL API | SDL | 型システムベースのスキーマ定義 |
| gRPC/Protocol Buffers | RPC API | .proto | 高性能なバイナリプロトコル |
| AsyncAPI | 非同期 API | YAML/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=2 | URL が変わらない |
| ヘッダーベース | Accept: application/vnd.api+json;version=2 | URL がクリーン |
| セマンティックバージョニング | 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 パラメータのシリアライゼーション
| style | in | 配列例 ([1,2,3]) | オブジェクト例 ({a:1,b:2}) |
|---|---|---|---|
matrix | path | ;id=1;id=2;id=3 | ;a=1;b=2 |
label | path | .1.2.3 | .a=1.b=2 |
form | query, cookie | id=1&id=2&id=3 | a=1&b=2 |
simple | path, header | 1,2,3 | a,1,b,2 |
spaceDelimited | query | id=1%202%203 | N/A |
pipeDelimited | query | id=1|2|3 | N/A |
deepObject | query | N/A | filter[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 基本データ型
| type | format | 説明 | 例 |
|---|---|---|---|
string | (なし) | 文字列 | "Hello" |
string | date | 日付 (RFC 3339) | "2024-01-15" |
string | date-time | 日時 (RFC 3339) | "2024-01-15T09:30:00Z" |
string | email | メールアドレス | "user@example.com" |
string | uri | URI | "https://example.com" |
string | uuid | UUID | "550e8400-..." |
string | password | パスワード(UIで隠蔽) | "********" |
string | byte | Base64エンコード | "SGVsbG8=" |
string | binary | バイナリデータ | (ファイルなど) |
integer | int32 | 32ビット整数 | 42 |
integer | int64 | 64ビット整数 | 9007199254740992 |
number | float | 単精度浮動小数点 | 3.14 |
number | double | 倍精度浮動小数点 | 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 |
$method | HTTP メソッド |
$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.0 | OpenAPI 3.1 |
|---|---|---|
| JSON Schema 互換 | 拡張サブセット | 完全互換 (Draft 2020-12) |
| nullable | nullable: true | type: ["string", "null"] |
exclusiveMinimum | boolean | number |
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 Elements | React コンポーネント |
コード生成
| ツール | 対応言語 |
|---|---|
| OpenAPI Generator | 50+ 言語 |
| oapi-codegen | Go |
| openapi-typescript | TypeScript |
| 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 OK | GET, PUT, PATCH |
201 Created | POST |
204 No Content | DELETE |
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 のインターフェース定義の事実上の標準として、以下を包括的にカバーする。
- API 設計と記述: パス、オペレーション、パラメータ、スキーマ
- セキュリティ: OAuth 2.0, OpenID Connect, API Key, JWT, mTLS
- 非同期通信: コールバックと Webhook
- データモデリング: JSON Schema ベースの強力なスキーマ定義
- ドキュメンテーション: Markdown 対応のリッチな記述
- コード生成: 50+ 言語対応
- テスト: Contract テスト、モックサーバー、プロパティベーステスト
- 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 を効率的に設計・開発・運用することが可能になる。
参考文献
- OpenAPI Specification 3.1.0 -- https://spec.openapis.org/oas/v3.1.0
- OpenAPI Initiative -- https://www.openapis.org/
- JSON Schema Draft 2020-12 -- https://json-schema.org/draft/2020-12/json-schema-core
- RFC 7807: Problem Details for HTTP APIs -- https://tools.ietf.org/html/rfc7807
- RFC 6749: OAuth 2.0 Authorization Framework -- https://tools.ietf.org/html/rfc6749
- Swagger/OpenAPI Tools -- https://openapi.tools/
- OpenAPI Generator -- https://openapi-generator.tech/
- Spectral -- https://github.com/stoplightio/spectral
- Redocly CLI -- https://redocly.com/docs/cli/
- AsyncAPI Specification -- https://www.asyncapi.com/