案件 API
調査票の案件(survey)を管理するエンドポイント。
認証・レスポンス形式・エラーの扱いは API 定義 を参照。
メソッド
HTTP メソッド
| メソッド | URI | 概要 |
|---|---|---|
| GET | /api/surveys |
案件一覧取得 |
| POST | /api/surveys |
案件新規作成と初期案生成 |
| GET | /api/surveys/{surveyId} |
案件詳細取得 |
| PATCH | /api/surveys/{surveyId} |
案件基本情報更新 |
| DELETE | /api/surveys/{surveyId} |
案件削除(論理削除) |
| GET | /api/surveys/{surveyId}/theme |
案件テーマ取得 |
| PATCH | /api/surveys/{surveyId}/theme |
案件テーマ更新 |
| POST | /api/theme-assists |
テーマ設定候補取得 |
| POST | /api/surveys/{surveyId}/save |
保存して新しい版を作成 |
| POST | /api/surveys/{surveyId}/versions |
同上(エイリアス) |
| POST | /api/surveys/{surveyId}/duplicate |
案件複製 |
| POST | /api/survey-copies |
案件または指定版から複製 |
| POST | /api/surveys/{surveyId}/questions/renumber |
設問コードの振り直し |
| POST | /api/surveys/{surveyId}/archive |
案件アーカイブ |
| POST | /api/surveys/{surveyId}/export |
JSON 出力と過去質問データへの登録 |
| POST | /api/surveys/{surveyId}/exports |
同上(エイリアス) |
| PUT | /api/surveys/{surveyId}/favorite |
お気に入り設定・解除 |
命名規則
URI・JSON のノードには camelCase を使用します(API 定義)。
リソース定義
案件のステータス
| ステータス | 説明 |
|---|---|
| 下書き | 初期状態。作成時に設定される |
| レビュー中 | レビュー依頼中 |
| 出力済み | JSON 出力を実行した状態。出力操作で自動的に遷移する |
| アーカイブ | 運用を終えた案件。一覧では既定で非表示 |
案件スキーマ
| フィールド | データ型 | 備考 |
|---|---|---|
| id | string | UUID |
| title | string | 案件タイトル |
| clientName | string | クライアント名 |
| objective | string | 調査目的 |
| deliveryArea | string | 配信エリア |
| category | string | カテゴリ |
| promptText | string | 自由記述 |
| status | enum | 下書き / レビュー中 / 出力済み / アーカイブ |
| latestVersionNo | number | 最新版の版番号 |
| createdBy | string | 作成者のユーザー ID |
| updatedBy | string | 最終更新者のユーザー ID |
| createdAt | string | ISO 8601 |
| updatedAt | string | ISO 8601 |
| sections | Section[] | 最新版のセクション一覧 |
| permissions | SurveyPermission[] | 共有権限一覧 |
| versions | SurveyVersion[] | 版履歴 |
認証要件
x-user-email / x-user-name ヘッダによるユーザー認証が必要です。
案件への操作は view / edit 権限で制御されます。権限がない場合も 404 Not Found を返します(案件の存在自体を秘匿するため)。例外は案件削除で、権限不足のときのみ 403 Forbidden を返します。
| 操作 | 必要な権限 |
|---|---|
| 一覧・詳細・テーマ取得・複製 | view |
| 更新・保存・アーカイブ・出力・お気に入り・設問コードの振り直し | edit |
| 削除 | 作成者本人、または管理者 |
案件一覧取得
概要
ログインユーザーが view または edit 権限を持つ案件の一覧を取得します(管理者は全件)。一覧項目にはセクション数とお気に入り状態が含まれ、セクション・設問の詳細は含まれません。
URI
クエリパラメータ
| パラメータ | データ型 | 必須 | 備考 |
|---|---|---|---|
| q | string | タイトル・クライアント名でのキーワード検索 | |
| status | enum | 下書き / レビュー中 / 出力済み / アーカイブ で絞り込み | |
| includeArchived | enum | true / false。既定は false |
|
| sort | enum | updatedAtDesc / updatedAtAsc / titleAsc / titleDesc。既定は updatedAtDesc |
レスポンス(200 OK)
{
"ok": true,
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"status": "下書き",
"latestVersionNo": 3,
"createdBy": "…",
"updatedBy": "…",
"createdAt": "2026-08-01T00:00:00.000Z",
"updatedAt": "2026-08-10T00:00:00.000Z",
"favorite": true,
"sectionCount": 4
}
]
}
| フィールド | データ型 | 備考 |
|---|---|---|
| favorite | boolean | ログインユーザーがお気に入り登録しているか |
| sectionCount | number | 最新版のセクション数 |
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| 認証ヘッダが欠落 | 401 | Unauthorized |
処理フロー
- 認証ミドルウェアがヘッダからユーザーを特定する
- 管理者でなければ、
view/edit権限を持つ案件に絞り込む - 削除済み(
deletedAtあり)の案件を除外する includeArchivedがfalseならアーカイブを除外するq/statusで絞り込み、sortで並べ替える(お気に入りを先頭に寄せる)
案件新規作成
概要
案件を新規作成します。版 1 が同時に作られ、作成者に edit 権限が付与されます。generateInitialContent を省略するか true にすると、初期セクション・初期設問が自動生成されます。
URI
リクエストボディ
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"generateInitialContent": true
}
バリデーションルール
| フィールド | ルール |
|---|---|
| title | 必須。文字列 |
| clientName | 必須。文字列 |
| objective | 必須。文字列 |
| deliveryArea | 必須。文字列 |
| category | 必須。文字列 |
| promptText | 任意。省略時は空文字 |
| generateInitialContent | 任意。真偽値。省略時は true |
レスポンス(201 Created)
案件スキーマ(sections / permissions / versions を含む)を返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
| 認証ヘッダが欠落 | 401 | Unauthorized |
処理フロー
シーケンス図
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: POST /api/surveys
API->>API: リクエストバリデーション
API->>DB: トランザクション開始
API->>DB: surveys へ案件を作成
API->>DB: survey_versions へ版 1 を作成
API->>DB: survey_version_pointers に最新版ポインタを作成
API->>DB: survey_permissions に作成者の edit 権限を作成
opt generateInitialContent = true
API->>DB: 初期セクション・初期設問を挿入
end
API->>DB: コミット
API-->>Client: 201 Created
案件詳細取得
概要
最新版のセクション・設問・分岐ルール・表示ロジックと、権限一覧・版履歴をまとめて返します。
URI
| パラメータ | データ型 | 必須 | 備考 |
|---|---|---|---|
| surveyId | string | ◯ | 案件の UUID |
レスポンス(200 OK)
案件スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| 案件が存在しない、または権限がない | 404 | Not Found |
処理フロー
- 案件を取得し、削除済みでないことを確認する
view権限を確認する(管理者は常に許可)- 最新版のスナップショット(セクション・設問・選択肢・分岐ルール・表示ロジック)を読み込む
- 権限一覧と版履歴を付与して返す
案件基本情報更新
概要
案件の基本情報とステータスを更新します。指定したフィールドのみが更新されます。
URI
リクエストボディ
バリデーションルール
| フィールド | ルール |
|---|---|
| title | 任意。文字列 |
| clientName | 任意。文字列 |
| objective | 任意。文字列 |
| deliveryArea | 任意。文字列 |
| category | 任意。文字列 |
| promptText | 任意。文字列 |
| status | 任意。下書き / レビュー中 / 出力済み / アーカイブ のいずれか |
レスポンス(200 OK)
更新後の案件スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
案件が存在しない、または edit 権限がない |
404 | Not Found |
案件削除
概要
案件を削除します。論理削除であり、削除日時が記録されるだけでデータは残ります。実行できるのは 案件の作成者本人と管理者のみ です。
URI
レスポンス(200 OK)
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| 作成者でも管理者でもない | 403 | Forbidden |
| 案件が存在しない、または削除済み | 404 | Not Found |
処理フロー
シーケンス図
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: DELETE /api/surveys/{surveyId}
API->>DB: 案件を取得 (deleted_at IS NULL)
alt 見つからない
API-->>Client: 404 Not Found
else 作成者でも管理者でもない
API-->>Client: 403 Forbidden
else
API->>DB: deleted_at に現在時刻を設定
API-->>Client: 200 OK
end
案件テーマ取得
概要
案件のテーマを、UI の入力フォームに合わせた構造化形式で取得します。DB では調査目的・配信エリア・カテゴリを 1 つの文字列として保持していますが、この API では「プリセット選択」と「自由入力」に分解して返します。
URI
レスポンス(200 OK)
{
"ok": true,
"data": {
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": { "presets": ["認知度の把握"], "customText": "" },
"deliveryArea": { "preset": "全国", "customText": "" },
"categories": { "labels": ["ブランド"], "freeText": "" },
"promptText": "",
"status": "下書き"
}
}
| フィールド | データ型 | 備考 |
|---|---|---|
| objective.presets | string[] | 選択済みのプリセット調査目的 |
| objective.customText | string | 自由入力の調査目的 |
| deliveryArea.preset | string | null | 選択済みのプリセット配信エリア |
| deliveryArea.customText | string | 自由入力の配信エリア |
| categories.labels | string[] | 選択済みのカテゴリ |
| categories.freeText | string | 自由入力のカテゴリ |
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| 案件が存在しない、または権限がない | 404 | Not Found |
案件テーマ更新
概要
案件のテーマを構造化形式で更新します。受け取った構造は DB 保存用の文字列へ直列化されます。
URI
リクエストボディ
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": { "presets": ["認知度の把握"], "customText": "" },
"deliveryArea": { "preset": "全国", "customText": "" },
"categories": { "labels": ["ブランド"], "freeText": "" },
"promptText": ""
}
バリデーションルール
| フィールド | ルール |
|---|---|
| title | 必須。文字列 |
| clientName | 必須。文字列 |
| objective | 必須。presets(文字列配列)と customText(文字列) |
| deliveryArea | 必須。preset(文字列 or null)と customText(文字列) |
| categories | 必須。labels(文字列配列)と freeText(文字列) |
| promptText | 必須。文字列 |
レスポンス(200 OK)
更新後のテーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
案件が存在しない、または edit 権限がない |
404 | Not Found |
テーマ設定候補取得
概要
入力中のテーマから、関連カテゴリ・過去の類似設問・推奨セクション構成 を提案します。案件の作成前でも呼べます。提案は、ログインユーザーが閲覧できる案件と質問ライブラリの内容をもとに算出されます。
URI
リクエストボディ
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"selectedCategories": ["ブランド"]
}
バリデーションルール
| フィールド | ルール |
|---|---|
| title | 必須。文字列 |
| clientName | 必須。文字列 |
| objective | 必須。文字列または構造化形式 |
| deliveryArea | 必須。文字列または構造化形式 |
| category | 必須。文字列または構造化形式 |
| promptText | 任意。省略時は空文字 |
| selectedCategories | 任意。文字列配列。省略時は category から導出する |
レスポンス(200 OK)
{
"ok": true,
"data": {
"suggestedCategories": ["ブランド", "購買行動"],
"relatedQuestions": [
{
"id": "…",
"category": "ブランド",
"sectionTitle": "認知",
"promptText": "以下のブランドのうち、知っているものをすべてお選びください。",
"questionType": "multi"
}
],
"recommendedSections": ["スクリーニング", "認知", "利用実態"]
}
}
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
処理フロー
- 閲覧可能な案件一覧と質問ライブラリを取得する
- テーマの各項目を連結してキーワードに分割する
- ライブラリの各設問について、設問文(4 点)・カテゴリ(3 点)・セクションタイトル(2 点)の一致でスコアを算出する
- スコアが 1 点以上のものを降順に並べ、上位 5 件を関連設問として返す
- 案件とライブラリから作った候補プールをもとに関連カテゴリを提案する
- カテゴリと関連設問から推奨セクション構成を組み立てて返す
保存して新しい版を作成
概要
現在の最新版の内容をまるごと複製して 新しい版を作成 し、それを最新版にします。
URI
2 つは同じ処理のエイリアスです。
レスポンス(201 Created)
{
"ok": true,
"data": {
"id": "…",
"versionNo": 4,
"createdAt": "2026-08-18T00:00:00.000Z",
"createdBy": "…",
"status": "下書き",
"snapshotSections": [],
"sourceVersionId": "…"
}
}
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
案件が存在しない、または edit 権限がない |
404 | Not Found |
処理フロー
edit権限を確認する- 最新版の ID を取得する
- 最新版のスナップショットを読み込む
- 新しい版を作成し、スナップショットを複製する。安定 ID はそのまま引き継ぐ
- 案件の最新版番号と最新版ポインタを更新する
安定 ID を引き継ぐ理由
版ごとに行の ID は新しく振られますが、安定 ID を引き継がないと質問ライブラリが古い版のスナップショットを指したままになり、設問の流用時に対象を見つけられなくなります。
案件複製
概要
案件を最新版の内容で複製し、新しい案件 を作成します。タイトルの末尾に「複製」が付き、共有権限も引き継がれます。
URI
レスポンス(201 Created)
複製された案件スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
案件が存在しない、または view 権限がない |
404 | Not Found |
処理フロー
view権限を確認する- 複製元の案件と最新版のスナップショットを読み込む
- トランザクションで新しい案件(版 1)を作成する
- 複製元の権限をすべて引き継ぐ
- スナップショットのセクション・設問を挿入する
案件または指定版から複製
概要
案件、または案件の指定した版から新しい案件を複製します。sourceVersionNo を指定すると指定版から、省略すると最新版から複製します。
URI
リクエストボディ
バリデーションルール
| フィールド | ルール |
|---|---|
| sourceSurveyId | 必須。複製元の案件 UUID |
| sourceVersionNo | 任意。1 以上の整数。省略時は最新版 |
レスポンス(201 Created)
複製された案件スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
| 案件または版が存在しない、または権限がない | 404 | Not Found |
設問コードの振り直し
概要
案件全体の設問コードを、出現順にきれいな連番へ振り直します。
| 設問タイプ | 振り直し後のコード |
|---|---|
提示ステップ(intro) |
T1 / T2 / … |
| それ以外 | Q1 / Q2 / … |
連番はセクション単位ではなく案件全体の通し番号です。振り直しに伴い、分岐条件の参照元(sourceQuestionCode)・分岐先(destinationQuestionCode)・表示ロジックの参照元も自動で新しいコードへ付け替え られます。
frontend は設問の並びが変わる操作(並べ替え・削除・複製・流用・「その他」フォローアップ設問の自動作成)のたびに、この API を自動的に呼び出します。
URI
| パラメータ | データ型 | 必須 | 備考 |
|---|---|---|---|
| surveyId | string | ◯ | 案件の UUID |
レスポンス(200 OK)
振り直し後の案件スキーマを返します。振り直しが不要だった(すでに連番になっていた)場合も現在の案件をそのまま返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
案件が存在しない、または edit 権限がない |
404 | Not Found |
処理フロー
edit権限を確認する- 最新版のスナップショットを読み込む
- セクション順・設問順に走査し、
introはT連番、それ以外はQ連番で次のコードを決める - 変更が必要な設問だけを対象に、旧コード → 新コードの対応表を作る
- トランザクションで設問コードを更新する
- 分岐ルールの分岐先、分岐条件の参照元、表示ロジックの参照元を対応表で付け替える
- 振り直し後の案件を返す
シーケンス図
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: POST /api/surveys/{surveyId}/questions/renumber
API->>API: edit 権限を確認
API->>DB: 最新版のスナップショットを読み込み
API->>API: intro=T連番 / それ以外=Q連番 で新コードを決定
alt 変更なし
API-->>Client: 200 OK (現在の案件)
else
API->>DB: トランザクション開始
API->>DB: 設問コードを更新
API->>DB: 分岐先・分岐条件の参照元を付け替え
API->>DB: 表示ロジックの参照元を付け替え
API->>DB: コミット
API-->>Client: 200 OK
end
据え置きコードへの参照は付け替えない
Q2 と Q3 を入れ替えるような相互リネームでも参照が二重に置換されないよう、付け替えは振り直し前に読んだ値を基準に 1 行 1 回だけ行われます。コードが変わらなかった設問への参照はそのまま維持されます。
失敗しても元の操作は成立している
frontend はこの API の失敗を警告表示に留めます。並べ替えや削除といった元の操作自体はすでに完了しているためで、コードが連番から外れたまま残ることがあります。
案件アーカイブ
概要
案件のステータスを「アーカイブ」に変更します。PATCH /api/surveys/{surveyId} で status に アーカイブ を指定するのと同じ結果になります。
URI
レスポンス(200 OK)
更新後の案件スキーマを返します。
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
案件が存在しない、または edit 権限がない |
404 | Not Found |
JSON 出力
概要
案件を 調査票 JSON として出力 します。Chrome 拡張が CS へ投入する際の入力データになります。
出力は副作用を伴います。
- 案件と最新版のステータスが「出力済み」になる
- 案件の全設問が 質問ライブラリへ登録 される(同じ案件の既存登録は置き換えられる)
URI
2 つは同じ処理のエイリアスです。
レスポンス(200 OK)
{
"ok": true,
"data": {
"surveyId": "…",
"title": "ブランド認知度調査",
"status": "出力済み",
"exportedAt": "2026-08-18T00:00:00.000Z",
"metadata": {
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"latestVersionNo": 3
},
"sections": [
{
"title": "スクリーニング",
"description": "",
"generatedBy": "manual",
"questions": [
{
"code": "Q1",
"questionType": "single",
"promptText": "あなたの性別をお答えください。",
"isRequired": true,
"isLinkedToPrevious": false,
"options": [
{ "label": "男性", "isExclusive": false, "allowOtherInput": false, "isNotApplicable": false },
{ "label": "女性", "isExclusive": false, "allowOtherInput": false, "isNotApplicable": false }
],
"branchRules": [],
"visibilityRules": []
}
]
}
]
}
}
| フィールド | データ型 | 備考 |
|---|---|---|
| exportedAt | string | 出力日時(ISO 8601) |
| metadata | object | 案件のテーマ情報と最新版番号 |
| sections[].questions[] | object[] | 設問の全設定(選択肢・マトリクス行列・FA 欄・サブ設問・分岐ルール・表示ロジック) |
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
案件が存在しない、または edit 権限がない |
404 | Not Found |
処理フロー
シーケンス図
sequenceDiagram
participant Client
participant API
participant DB
participant Library as 質問ライブラリ
Client->>API: POST /api/surveys/{surveyId}/export
API->>API: edit 権限を確認
API->>DB: 案件と最新版のスナップショットを読み込み
API->>DB: トランザクション開始
API->>DB: 案件のステータスを 出力済み に更新
API->>DB: 最新版のステータスを 出力済み に更新
API->>Library: この案件の登録を削除して再登録
API->>DB: コミット
API->>API: 調査票 JSON を組み立て
API-->>Client: 200 OK
お気に入り設定・解除
概要
案件のお気に入り状態を設定・解除します。お気に入りは ユーザーごと に管理されます。
URI
リクエストボディ
バリデーションルール
| フィールド | ルール |
|---|---|
| favorite | 必須。真偽値。true で登録、false で解除 |
レスポンス(200 OK)
例外処理
| 説明 | ステータスコード | ステータス名 |
|---|---|---|
| リクエストボディが不正 | 400 | Bad Request |
| 案件が存在しない、または権限がない | 404 | Not Found |