コンテンツにスキップ

API 共通仕様

面接調整システムの REST API に共通する規約。個別エンドポイントの仕様は左メニューの各ページを参照。

基本情報

項目 内容
ベース URL(ローカル) http://localhost:8080
ベース URL(dev) https://interview-arrange-api.heineken.dev.4digit.ai
API プレフィックス /api/v1
OpenAPI 定義 GET /openapi.json(ルート定義から自動生成)
Swagger UI GET /docs
ヘルスチェック GET /health / GET /api/v1/ping
OpenAPI バージョン 3.0.3

メソッド

REST メソッドを採用しています。

メソッド 用途
GET 取得
POST 作成・実行(インポート、送信、同期の起動など)
PATCH 部分更新
PUT 全体置換(アンケートインポート設定、候補者選定の一括更新)
DELETE 削除

命名規則

クエリパラメータとノードの命名を統一し、可読性を向上させるため、リクエスト時の URI と JSON 内のノードには snake_case を使用します。

/api/v1/projects/{projectId}/candidates/import/survey/preview
{
  "interview_duration_minutes": 60,
  "scheduling_range_start_days": 1
}

レスポンスは camelCase

リクエストボディの公開フィールドは snake_case ですが、レスポンスのデータ部は camelCase です(interviewDurationMinutes)。この変換はルートハンドラ内で明示的に行われます。一部のレスポンス(sent_count / failed_count / file_id など)は snake_case のまま返る点に注意してください。

リクエストとレスポンス

ヘッダー

リクエストヘッダー

ヘッダー 必須 内容
Authorization 公開エンドポイント以外で必須 Bearer <access_token>
Content-Type ボディを持つ場合 application/json(TSV アップロードのみ multipart/form-data)
X-Request-ID 任意 指定するとレスポンスとログで同じ ID が使われる

レスポンスヘッダー

ヘッダー 内容
Content-Type application/json
X-Request-ID リクエスト追跡用 ID

CORS

ALLOWED_ORIGINS に列挙したオリジンのみ許可。許可メソッドは GET / POST / PUT / PATCH / DELETE / OPTIONS、credentials: true、プリフライトのキャッシュは 24 時間。

レスポンス封筒

全レスポンスが共通の封筒形式で返ります。実データは常に data の中にあります。

成功時(200 / 201)

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "timestamp": "2026-01-15T10:00:00.000Z",
  "requestId": "1a2b3c4d",
  "data": { "id": 1, "name": "Engineering Interview 2026" },
  "path": "/api/v1/projects/1",
  "method": "GET"
}

ページネーション時

data が配列になり、pagination が追加されます。

{
  "success": true,
  "status": "success",
  "statusCode": 200,
  "timestamp": "2026-01-15T10:00:00.000Z",
  "data": [ { "id": 1 }, { "id": 2 } ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 100,
    "totalPages": 5,
    "hasNext": true,
    "hasPrevious": false
  },
  "path": "/api/v1/projects",
  "method": "GET"
}

エラー時

{
  "success": false,
  "status": "fail",
  "statusCode": 404,
  "timestamp": "2026-01-15T10:00:00.000Z",
  "requestId": "1a2b3c4d",
  "data": {
    "code": "NOT_FOUND",
    "error": "Not Found",
    "message": "Project not found"
  },
  "path": "/api/v1/projects/999",
  "method": "GET"
}

204 No Content

削除系(DELETE)はボディを持たず 204 を返します。封筒形式は適用されません。

フロントエンドでの取り出し

Orval の custom-fetch が { data, status, headers } 形で返すため、画面側は response.data.data を辿ります。lib/utils.ts の apiData() ヘルパーを使ってください。

ページネーション

一覧系エンドポイントの共通クエリパラメータ。

パラメータ 型 既定値 制約 説明
page integer 1 正の整数 ページ番号
limit integer 20 1〜100 1 ページあたりの件数
sort string - - createdAt:desc 形式

アンケート系は offset/limit

/api/v1/surveys/* の一覧は page ではなく offset / limit を使い、レスポンスも封筒の data 内に { items, total, limit, offset } を持つ独自形式です。

認証要件

Google OAuth 2.0 で取得したユーザー情報をもとにバックエンドが発行する JWT を用いた認証です。Authorization ヘッダーに有効な Bearer トークンが必要です。

sequenceDiagram
    participant FE as フロントエンド
    participant API as Backend API
    participant G as Google OAuth
    participant DB as PostgreSQL

    FE->>API: GET /api/v1/auth/google
    API-->>FE: 302 Google 認可画面へ
    FE->>G: ログイン・同意
    G->>API: GET /api/v1/auth/google/callback?code=...
    API->>G: code をトークンに交換
    API->>DB: ユーザーを検索/作成
    API-->>FE: 302 FRONTEND_URL へ(トークン付き)
    FE->>API: 以降 Authorization: Bearer <token>
    API->>API: JWT 検証(HS256)
項目 内容
署名アルゴリズム HS256
アクセストークン有効期限 JWT_EXPIRES_IN(既定 1 時間)
リフレッシュトークン有効期限 JWT_REFRESH_EXPIRES_IN(既定 7 日)
ペイロード userId / googleId / email / name / role
更新 POST /api/v1/auth/refresh
フロントの保管場所 localStorage の accessToken

認可(ロール)

ロールは階層構造で、admin(3)> member(2)> viewer(1)。各ルータで POST / PATCH / PUT / DELETE に対して member 以上を要求します。

ルータ 認証 更新系に必要なロール
/api/v1/auth/* 一部のみ(/logout /me) -
/api/v1/users 必要 -
/api/v1/projects/* 必要 member
/api/v1/projects/{id}/candidates/* 必要 member
/api/v1/projects/{id}/interviewers/* 必要 member
/api/v1/projects/{id}/email-templates/* 必要 member
/api/v1/projects/{id}/emails/* 必要 member
/api/v1/projects/{id}/reservations/* 必要 member(PATCH / PUT / DELETE)
/api/v1/email-templates 必要 member
/api/v1/surveys/* 必要 なし(参照専用だが viewer も全件閲覧可)
/api/v1/scheduling/* 不要(公開) -

例外処理

例外時のステータスコードは次のとおりです。

説明 ステータスコード ステータス名
バリデーションエラー 400 Bad Request
トークンが欠落または無効 401 Unauthorized
ロール不足 403 Forbidden
リソースが存在しない 404 Not Found
重複・枠競合 409 Conflict
レート超過 429 Too Many Requests
サーバ内部エラー 500 Internal Server Error
外部 API エラー 502 Bad Gateway
DB / Databricks 接続不可 503 Service Unavailable
外部 API タイムアウト 504 Gateway Timeout

エラーコード一覧

data.code に入る値。汎用エラーは src/lib/errors.ts、業務固有エラーは src/error.ts に定義されています。

汎用

コード ステータス 説明
BAD_REQUEST 400 不正なリクエスト
VALIDATION_ERROR 400 Zod バリデーション失敗。details に項目別のエラーが入る
UNAUTHORIZED 401 認証が必要/トークンが無効
FORBIDDEN 403 権限不足
NOT_FOUND 404 リソースが存在しない
CONFLICT 409 重複
TOO_MANY_REQUESTS 429 レート超過
INTERNAL_ERROR 500 内部エラー(詳細はクライアントに返さない)

データベース

コード ステータス 説明
DATABASE_ERROR 500 DB エラー全般
DATABASE_QUERY_ERROR 500 クエリ失敗
DATABASE_CONNECTION_ERROR 503 接続失敗
DATABASE_CONSTRAINT_ERROR 409 一意制約違反など

外部 API

コード ステータス 説明
EXTERNAL_API_ERROR 502 外部 API エラー全般
API_TIMEOUT 504 タイムアウト
API_UNAVAILABLE 503 一時的に利用不可
GOOGLE_API_ERROR 502 Google API エラー
GOOGLE_CALENDAR_ERROR 502 Google Calendar エラー
GMAIL_API_ERROR 502 Gmail API エラー

Databricks

コード ステータス 説明
DATABRICKS_ERROR 502 Databricks エラー全般
DATABRICKS_QUERY_ERROR 502 ステートメントの失敗・キャンセル・タイムアウト
DATABRICKS_AUTH_ERROR 502 OAuth M2M のトークン取得失敗
DATABRICKS_NOT_CONFIGURED 503 Databricks が未設定(DATABRICKS_HOST / 資格情報が空)

業務固有

コード ステータス 説明
TOKEN_EXPIRED 401 JWT の期限切れ
TOKEN_INVALID 401 JWT が不正
SCHEDULING_TOKEN_ERROR 400 調整トークンが無効または期限切れ
SLOT_NOT_AVAILABLE 409 選択した枠が既に埋まっている/確定済み
EMAIL_SEND_ERROR 500 メール送信失敗
IMPORT_ERROR 400 インポートエラー。row / column を持つ
SCORING_ERROR 400 スコアリングルールが不正
INVALID_STATUS_TRANSITION 400 許可されていないステータス遷移

エラー処理の実装

ハンドラでは throw new NotFoundError('Project') のように投げるだけでよく、middlewares/error-handler.ts が上記の変換を行います。isOperational が false のエラーは詳細をクライアントに返しません(開発時のみ stack を含む)。

エンドポイント一覧

リソース 件数 ページ
認証 5 認証 API
ユーザー 1 ユーザー API
プロジェクト 9 プロジェクト API
候補者 17 候補者 API
面接官 6 面接官 API
メール 10 メール API
予約 3 予約 API
日程調整(公開) 3 日程調整 API
アンケート 7 アンケート API