ストーリー
高橋アーキテクトが要件を渡した。
ミッション概要
| ミッション | テーマ | 難易度 |
|---|---|---|
| Mission 1 | 基本構造とinfo/servers | 初級 |
| Mission 2 | タスクCRUDのpaths定義 | 中級 |
| Mission 3 | componentsスキーマ定義 | 中級 |
| Mission 4 | エラーレスポンスとセキュリティ | 上級 |
Mission 1: 基本構造の作成(10分)
OpenAPI仕様書の骨格(info, servers, tags)を作成してください。
要件
- タイトル: TaskFlow API
- バージョン: 1.0.0
- サーバー: 本番、ステージング、ローカル
- タグ: auth, users, projects, tasks, comments
解答
openapi: "3.1.0"
info:
title: "TaskFlow API"
description: |
タスク管理アプリケーション TaskFlow のREST API仕様書。
プロジェクトごとにタスクを管理し、チームでのコラボレーションを実現します。
version: "1.0.0"
contact:
name: "TaskFlow API Team"
email: "api-team@taskflow.example.com"
license:
name: "MIT"
url: "https://opensource.org/licenses/MIT"
servers:
- url: "https://api.taskflow.example.com/v1"
description: "本番環境"
- url: "https://staging-api.taskflow.example.com/v1"
description: "ステージング環境"
- url: "http://localhost:3000/v1"
description: "ローカル開発環境"
tags:
- name: auth
description: "認証関連のAPI"
- name: users
description: "ユーザー管理API"
- name: projects
description: "プロジェクト管理API"
- name: tasks
description: "タスク管理API"
- name: comments
description: "コメントAPI"
paths: {}
components: {}
Mission 2: タスクCRUDのpaths定義(20分)
タスクの作成、一覧取得、詳細取得、更新、削除のエンドポイントをpathsに定義してください。
要件
POST /projects/{projectId}/tasks- タスク作成GET /projects/{projectId}/tasks- タスク一覧(ページネーション、フィルタ付き)GET /tasks/{taskId}- タスク詳細PATCH /tasks/{taskId}- タスク更新DELETE /tasks/{taskId}- タスク削除
解答
paths:
/projects/{projectId}/tasks:
get:
tags: [tasks]
summary: "タスク一覧取得"
description: "指定プロジェクトのタスク一覧を取得します"
operationId: "listTasks"
parameters:
- name: projectId
in: path
required: true
schema:
type: string
example: "proj_123"
- name: status
in: query
description: "ステータスで絞り込み(カンマ区切りで複数指定可)"
schema:
type: string
example: "todo,in_progress"
- name: assigneeId
in: query
description: "担当者IDで絞り込み"
schema:
type: string
- name: sort
in: query
description: "ソート(-で降順)"
schema:
type: string
default: "-createdAt"
example: "-priority"
- name: page
in: query
schema:
type: integer
default: 1
minimum: 1
- name: perPage
in: query
schema:
type: integer
default: 20
minimum: 1
maximum: 100
responses:
"200":
description: "成功"
content:
application/json:
schema:
$ref: "#/components/schemas/TaskListResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
security:
- bearerAuth: []
post:
tags: [tasks]
summary: "タスク作成"
description: "指定プロジェクトにタスクを作成します"
operationId: "createTask"
parameters:
- name: projectId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateTaskRequest"
responses:
"201":
description: "作成成功"
headers:
Location:
description: "作成されたタスクのURI"
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/TaskResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"422":
$ref: "#/components/responses/ValidationError"
security:
- bearerAuth: []
/tasks/{taskId}:
get:
tags: [tasks]
summary: "タスク詳細取得"
operationId: "getTask"
parameters:
- name: taskId
in: path
required: true
schema:
type: string
example: "tsk_789"
responses:
"200":
description: "成功"
content:
application/json:
schema:
$ref: "#/components/schemas/TaskDetailResponse"
"404":
$ref: "#/components/responses/NotFound"
security:
- bearerAuth: []
patch:
tags: [tasks]
summary: "タスク更新"
operationId: "updateTask"
parameters:
- name: taskId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateTaskRequest"
responses:
"200":
description: "更新成功"
content:
application/json:
schema:
$ref: "#/components/schemas/TaskResponse"
"404":
$ref: "#/components/responses/NotFound"
"422":
$ref: "#/components/responses/ValidationError"
security:
- bearerAuth: []
delete:
tags: [tasks]
summary: "タスク削除"
operationId: "deleteTask"
parameters:
- name: taskId
in: path
required: true
schema:
type: string
responses:
"204":
description: "削除成功"
"404":
$ref: "#/components/responses/NotFound"
security:
- bearerAuth: []
Mission 3: componentsスキーマ定義(20分)
タスク関連のスキーマを components/schemas に定義してください。
要件
- Task(レスポンス用)
- CreateTaskRequest(作成リクエスト)
- UpdateTaskRequest(更新リクエスト)
- TaskListResponse(一覧レスポンス)
- PaginationMeta
解答
components:
schemas:
Task:
type: object
required: [id, title, status, priority, createdAt, updatedAt]
properties:
id:
type: string
example: "tsk_789"
title:
type: string
example: "ログイン画面のUI改善"
description:
type: string
nullable: true
example: "モバイル対応のレスポンシブデザインに修正"
status:
type: string
enum: [todo, in_progress, in_review, done]
example: "todo"
priority:
type: string
enum: [low, medium, high, critical]
example: "high"
assignee:
$ref: "#/components/schemas/UserSummary"
labels:
type: array
items:
$ref: "#/components/schemas/Label"
dueDate:
type: string
format: date-time
nullable: true
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
UserSummary:
type: object
required: [id, name]
properties:
id:
type: string
example: "usr_456"
name:
type: string
example: "鈴木花子"
Label:
type: object
required: [id, name, color]
properties:
id:
type: string
example: "lbl_001"
name:
type: string
example: "UI"
color:
type: string
pattern: "^#[0-9a-fA-F]{6}$"
example: "#3b82f6"
CreateTaskRequest:
type: object
required: [title]
properties:
title:
type: string
minLength: 1
maxLength: 200
description:
type: string
maxLength: 5000
assigneeId:
type: string
priority:
type: string
enum: [low, medium, high, critical]
default: medium
dueDate:
type: string
format: date-time
labelIds:
type: array
items:
type: string
maxItems: 10
UpdateTaskRequest:
type: object
properties:
title:
type: string
minLength: 1
maxLength: 200
description:
type: string
maxLength: 5000
nullable: true
status:
type: string
enum: [todo, in_progress, in_review, done]
priority:
type: string
enum: [low, medium, high, critical]
assigneeId:
type: string
nullable: true
dueDate:
type: string
format: date-time
nullable: true
labelIds:
type: array
items:
type: string
maxItems: 10
TaskResponse:
type: object
properties:
data:
$ref: "#/components/schemas/Task"
TaskDetailResponse:
type: object
properties:
data:
allOf:
- $ref: "#/components/schemas/Task"
- type: object
properties:
project:
$ref: "#/components/schemas/ProjectSummary"
commentCount:
type: integer
example: 5
ProjectSummary:
type: object
required: [id, name]
properties:
id:
type: string
example: "proj_123"
name:
type: string
example: "TaskFlow v2"
TaskListResponse:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/Task"
meta:
$ref: "#/components/schemas/PaginationMeta"
PaginationMeta:
type: object
properties:
totalCount:
type: integer
example: 42
currentPage:
type: integer
example: 1
perPage:
type: integer
example: 20
totalPages:
type: integer
example: 3
Mission 4: エラーレスポンスとセキュリティ(10分)
エラーレスポンスの共通定義とセキュリティスキームを定義してください。
解答
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: "JWT Bearer Token による認証"
responses:
Unauthorized:
description: "認証エラー"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error:
code: "UNAUTHENTICATED"
message: "認証が必要です"
traceId: "req_abc123"
Forbidden:
description: "権限エラー"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error:
code: "FORBIDDEN"
message: "この操作を行う権限がありません"
traceId: "req_def456"
NotFound:
description: "リソースが見つかりません"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error:
code: "NOT_FOUND"
message: "指定されたリソースが見つかりません"
traceId: "req_ghi789"
ValidationError:
description: "バリデーションエラー"
content:
application/json:
schema:
$ref: "#/components/schemas/ValidationErrorResponse"
example:
error:
code: "VALIDATION_ERROR"
message: "入力内容に問題があります"
details:
- field: "title"
message: "タイトルは必須です"
traceId: "req_jkl012"
schemas:
ErrorResponse:
type: object
required: [error]
properties:
error:
type: object
required: [code, message, traceId]
properties:
code:
type: string
message:
type: string
traceId:
type: string
ValidationErrorResponse:
type: object
required: [error]
properties:
error:
type: object
required: [code, message, details, traceId]
properties:
code:
type: string
message:
type: string
details:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
traceId:
type: string
security:
- bearerAuth: []
達成度チェック
| ミッション | テーマ | 完了 |
|---|---|---|
| Mission 1 | 基本構造 | [ ] |
| Mission 2 | パス定義 | [ ] |
| Mission 3 | スキーマ定義 | [ ] |
| Mission 4 | エラーとセキュリティ | [ ] |
まとめ
| ポイント | 内容 |
|---|---|
| 基本構造 | openapi, info, servers, tags で全体を定義 |
| paths | HTTPメソッドごとにparameters, requestBody, responsesを記述 |
| components | schemas, responses, securitySchemes で再利用可能な定義 |
| $ref | コンポーネントへの参照で重複を排除 |
チェックリスト
- OpenAPI仕様書の基本構造を自分で書ける
- CRUDエンドポイントのpaths定義ができる
- データモデルのスキーマ定義ができる
- エラーレスポンスとセキュリティの定義ができる
次のステップへ
お疲れさまでした。OpenAPI仕様書を実際に書く練習をしました。
次はStep 3のチェックポイントです。
推定所要時間: 60分