コンテンツにスキップ

面接官 API

プロジェクトへの面接官の登録と、Google Calendar を用いた空き枠算出・仮枠押さえ。共通規約は API 共通仕様 を参照。

ベースパス: /api/v1/projects/{projectId}/interviewers

メソッド パス 概要 必要ロール
GET / 面接官一覧取得 viewer
POST / 面接官追加 member
DELETE /{userId} 面接官削除 member
GET /availability 面接官空き状況取得 viewer
POST /tentative-slots 仮枠カレンダーイベント作成 member
DELETE /tentative-slots 仮枠カレンダーイベント削除 member

全エンドポイントで Authorization: Bearer <access_token> が必要。更新系は member 以上。


面接官一覧取得

URI

GET /api/v1/projects/{projectId}/interviewers

レスポンス(200 OK)

data が Interviewer の配列(ページネーションなし)。

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "data": [
    {
      "id": 3,
      "projectId": 1,
      "userId": 5,
      "user": {
        "id": 5,
        "email": "interviewer@example.com",
        "name": "末成",
        "picture": null,
        "role": "member",
        "createdAt": "2026-01-10T09:00:00Z"
      },
      "createdAt": "2026-01-15T09:00:00Z"
    }
  ],
  "path": "/api/v1/projects/1/interviewers",
  "method": "GET"
}
フィールド 型 説明
id integer project_interviewers.id
projectId integer プロジェクト ID
userId integer ユーザー ID
user object ユーザー情報
createdAt string(date-time) 追加日時

例外処理

説明 ステータスコード ステータス名
トークンが欠落または無効 401 Unauthorized
プロジェクトが存在しない 404 Not Found
サーバ内部エラー 500 Internal Server Error

面接官追加

URI

POST /api/v1/projects/{projectId}/interviewers

リクエストボディ

{
  "userId": 5
}

バリデーションルール

フィールド ルール
userId 必須。正の整数。既存ユーザーを参照すること

追加対象のユーザー ID は ユーザー API の一覧から取得する。

レスポンス(201 Created)

data に作成された Interviewer。

例外処理

説明 ステータスコード ステータス名
バリデーションエラー 400 Bad Request
トークンが欠落または無効 401 Unauthorized
ロール不足 403 Forbidden
プロジェクトまたはユーザーが存在しない 404 Not Found
既に登録済み 409 Conflict

uk_project_user(project_id + user_id)により重複登録はできない。


面接官削除

URI

DELETE /api/v1/projects/{projectId}/interviewers/{userId}

パスパラメータ

フィールド ルール
projectId 必須。正の整数
userId 必須。正の整数(users.id。project_interviewers.id ではない)

レスポンス(204 No Content)

ボディなし。

例外処理

説明 ステータスコード ステータス名
トークンが欠落または無効 401 Unauthorized
ロール不足 403 Forbidden
面接官が存在しない 404 Not Found

面接官空き状況取得

プロジェクトに登録された面接官の Google Calendar を参照し、予約可能枠を算出する。STEP1 の「空き枠を算出」で呼ばれる。

URI

GET /api/v1/projects/{projectId}/interviewers/availability

クエリパラメータ

フィールド 型 必須 ルール 説明
startDate string ◯ YYYY-MM-DD 算出期間の開始日
endDate string ◯ YYYY-MM-DD 算出期間の終了日
durationMinutes integer - 正の整数 面接の所要時間。未指定なら projects.interview_duration_minutes

リクエスト例

GET /api/v1/projects/1/interviewers/availability?startDate=2026-02-01&endDate=2026-02-14&durationMinutes=90

durationMinutes を渡す理由

所要時間は STEP1 を保存したときにプロジェクトへ書き込まれる。画面で選んだ直後に「空き枠を算出」を押すとまだ保存されていないため、明示的に渡さないと前の値で算出されてしまう。

枠は平日 9:00〜18:00(JST)の範囲で、所要時間の倍数を開始時刻として並ぶ(90 分なら 9:00-10:30 / 10:30-12:00 / …)。枠同士は重ならず、営業時間をはみ出す枠は返さない。

レスポンス(200 OK)

data が AvailableSlot の配列。

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "data": [
    {
      "slotId": "slot_20260203_1000",
      "interviewerId": 5,
      "interviewerName": "末成",
      "startAt": "2026-02-03T01:00:00Z",
      "endAt": "2026-02-03T02:00:00Z"
    }
  ],
  "path": "/api/v1/projects/1/interviewers/availability",
  "method": "GET"
}
フィールド 型 説明
slotId string 枠を識別する ID。希望日程の送信時にそのまま使う
interviewerId integer 面接官のユーザー ID
interviewerName string 面接官の表示名
startAt / endAt string(date-time) 枠の開始/終了

枠の長さはプロジェクトの interview_duration_minutes に従う。

例外処理

説明 ステータスコード ステータス名
日付形式が不正 400 Bad Request
トークンが欠落または無効 401 Unauthorized
プロジェクトが存在しない 404 Not Found
Google Calendar エラー(GOOGLE_CALENDAR_ERROR) 502 Bad Gateway

仮枠カレンダーイベント作成

STEP1 で確定した枠を、面接官の Google Calendar に暫定イベントとして一括登録する。既存の仮枠は削除されてから作り直される。

URI

POST /api/v1/projects/{projectId}/interviewers/tentative-slots

リクエストボディ

{
  "slots": [
    {
      "interviewerId": 5,
      "startTime": "2026-02-03T10:00:00+09:00",
      "endTime": "2026-02-03T11:00:00+09:00"
    },
    {
      "interviewerId": 5,
      "startTime": "2026-02-03T11:00:00+09:00",
      "endTime": "2026-02-03T12:00:00+09:00"
    }
  ]
}

バリデーションルール

フィールド ルール
slots 必須。配列
slots[].interviewerId 必須。整数
slots[].startTime 必須。ISO 8601 形式の文字列
slots[].endTime 必須。ISO 8601 形式の文字列

レスポンス(200 OK)

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "data": { "created": 20, "deleted": 0 },
  "path": "/api/v1/projects/1/interviewers/tentative-slots",
  "method": "POST"
}
フィールド 型 説明
created integer 作成した仮枠イベント数
deleted integer 事前に削除した既存仮枠数

作成されたイベント情報は projects.arrange_settings.step1.tentativeEventIds に保存される。

イベントはプロジェクトカレンダー(projects.google_calendar_id)に作られ、担当の面接官が attendee として入る。一度に多数作るため Google からの招待通知は送らない。カレンダーが未作成のプロジェクトでは、この時点で作成される。

tentativeEventIds の interviewerEmail

以前は面接官個人のカレンダーに書き込んでいたため、この項目がカレンダー ID を兼ねていた。現在は「どの面接官の枠か」を示すだけで、Calendar API のカレンダー ID としては使わない。

例外処理

説明 ステータスコード ステータス名
バリデーションエラー 400 Bad Request
トークンが欠落または無効 401 Unauthorized
ロール不足 403 Forbidden
プロジェクトが存在しない 404 Not Found
Google Calendar エラー 502 Bad Gateway

PROTOTYPE_MODE

PROTOTYPE_MODE=true の間はカレンダーへの書き込みが行われない。


仮枠カレンダーイベント削除

プロジェクトの仮枠イベントをすべて削除する。

URI

DELETE /api/v1/projects/{projectId}/interviewers/tentative-slots

リクエスト

ボディなし。パスパラメータ projectId のみ。

レスポンス(200 OK)

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "data": { "deleted": 20 },
  "path": "/api/v1/projects/1/interviewers/tentative-slots",
  "method": "DELETE"
}

204 ではなく 200 と削除件数を返す点に注意。

例外処理

説明 ステータスコード ステータス名
トークンが欠落または無効 401 Unauthorized
ロール不足 403 Forbidden
プロジェクトが存在しない 404 Not Found
Google Calendar エラー 502 Bad Gateway