Surveys API
Endpoints that manage surveys.
See API Definition for authentication, response format, and error handling.
Method
HTTP Methods
| Method | URI | Overview |
|---|---|---|
| GET | /api/surveys |
List surveys |
| POST | /api/surveys |
Create a survey and generate an initial draft |
| GET | /api/surveys/{surveyId} |
Get survey detail |
| PATCH | /api/surveys/{surveyId} |
Update survey basics |
| DELETE | /api/surveys/{surveyId} |
Delete a survey (soft delete) |
| GET | /api/surveys/{surveyId}/theme |
Get the survey theme |
| PATCH | /api/surveys/{surveyId}/theme |
Update the survey theme |
| POST | /api/theme-assists |
Get theme suggestions |
| POST | /api/surveys/{surveyId}/save |
Save and create a new version |
| POST | /api/surveys/{surveyId}/versions |
Same (alias) |
| POST | /api/surveys/{surveyId}/duplicate |
Duplicate a survey |
| POST | /api/survey-copies |
Duplicate from a survey or a specific version |
| POST | /api/surveys/{surveyId}/questions/renumber |
Renumber the question codes |
| POST | /api/surveys/{surveyId}/archive |
Archive a survey |
| POST | /api/surveys/{surveyId}/export |
Export JSON and register into the question library |
| POST | /api/surveys/{surveyId}/exports |
Same (alias) |
| PUT | /api/surveys/{surveyId}/favorite |
Set or clear a favorite |
Naming Conventions
URIs and JSON nodes use camelCase (API Definition).
Resource Definition
Survey Status
| Status | Description |
|---|---|
| 下書き (Draft) | Initial state, set at creation |
| レビュー中 (In Review) | Awaiting review |
| 出力済み (Exported) | JSON export has been performed; set automatically by the export operation |
| アーカイブ (Archived) | A finished survey; hidden from the list by default |
Survey Schema
| Field | Type | Notes |
|---|---|---|
| id | string | UUID |
| title | string | Survey title |
| clientName | string | Client name |
| objective | string | Research objective |
| deliveryArea | string | Delivery area |
| category | string | Category |
| promptText | string | Free text |
| status | enum | Draft / In Review / Exported / Archived |
| latestVersionNo | number | Version number of the latest version |
| createdBy | string | User ID of the creator |
| updatedBy | string | User ID of the last updater |
| createdAt | string | ISO 8601 |
| updatedAt | string | ISO 8601 |
| sections | Section[] | Sections of the latest version |
| permissions | SurveyPermission[] | Sharing permissions |
| versions | SurveyVersion[] | Version history |
Authentication
User authentication via the x-user-email / x-user-name headers is required.
Operations are controlled by view / edit permissions. Missing permission also returns 404 Not Found (to hide whether the survey exists). The one exception is deletion, which returns 403 Forbidden when permission is missing.
| Operation | Required permission |
|---|---|
| List, detail, theme retrieval, duplication | view |
| Update, save, archive, export, favorite, renumbering question codes | edit |
| Deletion | The creator, or an administrator |
List Surveys
Overview
Returns the surveys on which the logged-in user holds view or edit permission (administrators see all). List entries include the section count and favorite state, but no section or question details.
URI
Query Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
| q | string | Keyword search over title and client name | |
| status | enum | Filter by Draft / In Review / Exported / Archived | |
| includeArchived | enum | true / false. Defaults to false |
|
| sort | enum | updatedAtDesc / updatedAtAsc / titleAsc / titleDesc. Defaults to updatedAtDesc |
Response (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
}
]
}
| Field | Type | Notes |
|---|---|---|
| favorite | boolean | Whether the logged-in user has favorited the survey |
| sectionCount | number | Number of sections in the latest version |
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Authentication headers missing | 401 | Unauthorized |
Processing Flow
- The authentication middleware identifies the user from the headers
- Unless the user is an administrator, narrow down to surveys where they hold
view/editpermission - Exclude deleted surveys (those with
deletedAt) - Exclude archived surveys unless
includeArchivedistrue - Filter by
q/statusand sort bysort(favorites are pulled to the top)
Create a Survey
Overview
Creates a survey. Version 1 is created at the same time, and the creator receives edit permission. Omitting generateInitialContent, or setting it to true, generates initial sections and questions.
URI
Request Body
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"generateInitialContent": true
}
Validation Rules
| Field | Rule |
|---|---|
| title | Required. String |
| clientName | Required. String |
| objective | Required. String |
| deliveryArea | Required. String |
| category | Required. String |
| promptText | Optional. Empty string when omitted |
| generateInitialContent | Optional. Boolean. Defaults to true |
Response (201 Created)
Returns the survey schema (including sections, permissions, and versions).
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
| Authentication headers missing | 401 | Unauthorized |
Processing Flow
Sequence Diagram
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: POST /api/surveys
API->>API: Validate the request
API->>DB: Begin transaction
API->>DB: Insert into surveys
API->>DB: Insert version 1 into survey_versions
API->>DB: Insert the latest-version pointer
API->>DB: Insert the creator's edit permission
opt generateInitialContent = true
API->>DB: Insert initial sections and questions
end
API->>DB: Commit
API-->>Client: 201 Created
Get Survey Detail
Overview
Returns the sections, questions, branch rules, and visibility rules of the latest version, together with the permission list and version history.
URI
| Parameter | Type | Required | Notes |
|---|---|---|---|
| surveyId | string | ◯ | Survey UUID |
Response (200 OK)
Returns the survey schema.
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Survey does not exist, or permission is missing | 404 | Not Found |
Processing Flow
- Fetch the survey and confirm it is not deleted
- Check
viewpermission (administrators are always allowed) - Load the latest version's snapshot
- Attach the permission list and version history
Update Survey Basics
Overview
Updates the survey's basic information and status. Only the fields given are updated.
URI
Request Body
Validation Rules
| Field | Rule |
|---|---|
| title | Optional. String |
| clientName | Optional. String |
| objective | Optional. String |
| deliveryArea | Optional. String |
| category | Optional. String |
| promptText | Optional. String |
| status | Optional. One of Draft / In Review / Exported / Archived |
Response (200 OK)
Returns the updated survey schema.
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
Survey does not exist, or edit permission is missing |
404 | Not Found |
Delete a Survey
Overview
Deletes a survey. This is a soft delete: the deletion timestamp is recorded but the data remains. Only the creator and administrators may perform it.
URI
Response (200 OK)
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Neither the creator nor an administrator | 403 | Forbidden |
| Survey does not exist, or is already deleted | 404 | Not Found |
Processing Flow
Sequence Diagram
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: DELETE /api/surveys/{surveyId}
API->>DB: Fetch the survey (deleted_at IS NULL)
alt Not found
API-->>Client: 404 Not Found
else Neither creator nor administrator
API-->>Client: 403 Forbidden
else
API->>DB: Set deleted_at to the current time
API-->>Client: 200 OK
end
Get the Survey Theme
Overview
Returns the survey's theme in the structured form used by the input form. In the database the research objective, delivery area, and category are each a single string; this API splits them into "preset selection" and "free input".
URI
Response (200 OK)
{
"ok": true,
"data": {
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": { "presets": ["認知度の把握"], "customText": "" },
"deliveryArea": { "preset": "全国", "customText": "" },
"categories": { "labels": ["ブランド"], "freeText": "" },
"promptText": "",
"status": "下書き"
}
}
| Field | Type | Notes |
|---|---|---|
| objective.presets | string[] | Selected preset research objectives |
| objective.customText | string | Free-input research objective |
| deliveryArea.preset | string | null | Selected preset delivery area |
| deliveryArea.customText | string | Free-input delivery area |
| categories.labels | string[] | Selected categories |
| categories.freeText | string | Free-input category |
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Survey does not exist, or permission is missing | 404 | Not Found |
Update the Survey Theme
Overview
Updates the survey's theme in the structured form. The structure received is serialized into the strings stored in the database.
URI
Request Body
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": { "presets": ["認知度の把握"], "customText": "" },
"deliveryArea": { "preset": "全国", "customText": "" },
"categories": { "labels": ["ブランド"], "freeText": "" },
"promptText": ""
}
Validation Rules
| Field | Rule |
|---|---|
| title | Required. String |
| clientName | Required. String |
| objective | Required. presets (string array) and customText (string) |
| deliveryArea | Required. preset (string or null) and customText (string) |
| categories | Required. labels (string array) and freeText (string) |
| promptText | Required. String |
Response (200 OK)
Returns the updated theme.
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
Survey does not exist, or edit permission is missing |
404 | Not Found |
Get Theme Suggestions
Overview
Suggests related categories, similar past questions, and a recommended section structure from the theme being entered. It can be called before a survey is created, and the suggestions come from the surveys the user can see plus the question library.
URI
Request Body
{
"title": "ブランド認知度調査",
"clientName": "株式会社サンプル",
"objective": "認知度の把握",
"deliveryArea": "全国",
"category": "ブランド",
"promptText": "",
"selectedCategories": ["ブランド"]
}
Validation Rules
| Field | Rule |
|---|---|
| title | Required. String |
| clientName | Required. String |
| objective | Required. A string or the structured form |
| deliveryArea | Required. A string or the structured form |
| category | Required. A string or the structured form |
| promptText | Optional. Empty string when omitted |
| selectedCategories | Optional. String array. Derived from category when omitted |
Response (200 OK)
{
"ok": true,
"data": {
"suggestedCategories": ["ブランド", "購買行動"],
"relatedQuestions": [
{
"id": "…",
"category": "ブランド",
"sectionTitle": "認知",
"promptText": "以下のブランドのうち、知っているものをすべてお選びください。",
"questionType": "multi"
}
],
"recommendedSections": ["スクリーニング", "認知", "利用実態"]
}
}
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
Processing Flow
- Fetch the visible surveys and the question library
- Concatenate the theme fields and split them into keywords
- Score each library question by matches in the prompt text (4), category (3), and section title (2)
- Sort entries scoring at least 1 in descending order and return the top five
- Suggest related categories from a candidate pool built from the surveys and the library
- Build a recommended section structure from the categories and the related questions
Save and Create a New Version
Overview
Copies the entire current latest version into a new version and makes it the latest.
URI
The two are aliases for the same operation.
Response (201 Created)
{
"ok": true,
"data": {
"id": "…",
"versionNo": 4,
"createdAt": "2026-08-18T00:00:00.000Z",
"createdBy": "…",
"status": "下書き",
"snapshotSections": [],
"sourceVersionId": "…"
}
}
Error Handling
| Description | Status code | Status name |
|---|---|---|
Survey does not exist, or edit permission is missing |
404 | Not Found |
Processing Flow
- Check
editpermission - Get the ID of the latest version
- Load the latest version's snapshot
- Create a new version and copy the snapshot. Stable IDs are carried over unchanged
- Update the survey's latest version number and the latest-version pointer
Why stable IDs are carried over
Row IDs are re-assigned per version. Without carrying stable IDs over, the question library would keep pointing at an older snapshot and reuse could no longer locate the question.
Duplicate a Survey
Overview
Duplicates the survey with the content of its latest version, creating a new survey. The title gets a "複製" (duplicate) suffix, and sharing permissions are carried over.
URI
Response (201 Created)
Returns the duplicated survey schema.
Error Handling
| Description | Status code | Status name |
|---|---|---|
Survey does not exist, or view permission is missing |
404 | Not Found |
Processing Flow
- Check
viewpermission - Load the source survey and its latest version snapshot
- Create a new survey (version 1) in a transaction
- Carry over all permissions from the source
- Insert the snapshot's sections and questions
Duplicate from a Survey or Version
Overview
Creates a new survey from a survey, or from a specific version of it. With sourceVersionNo the copy comes from that version; otherwise from the latest version.
URI
Request Body
Validation Rules
| Field | Rule |
|---|---|
| sourceSurveyId | Required. UUID of the source survey |
| sourceVersionNo | Optional. Integer of 1 or greater. Latest version when omitted |
Response (201 Created)
Returns the duplicated survey schema.
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
| Survey or version does not exist, or permission is missing | 404 | Not Found |
Renumber the Question Codes
Overview
Renumbers every question code in the survey into a clean sequence following the order of appearance.
| Question type | Code after renumbering |
|---|---|
Intro step (intro) |
T1 / T2 / … |
| Everything else | Q1 / Q2 / … |
The sequence runs across the whole survey, not per section. Along with the codes, branch condition sources (sourceQuestionCode), branch destinations (destinationQuestionCode), and visibility condition sources are re-pointed automatically at the new codes.
The frontend calls this API automatically after any operation that changes the question order (reordering, deleting, duplicating, importing, and auto-creating an "other" follow-up question).
URI
| Parameter | Type | Required | Notes |
|---|---|---|---|
| surveyId | string | ◯ | Survey UUID |
Response (200 OK)
Returns the survey schema after renumbering. If no renumbering was needed (the codes were already sequential), the current survey is returned unchanged.
Error Handling
| Description | Status code | Status name |
|---|---|---|
Survey does not exist, or edit permission is missing |
404 | Not Found |
Processing Flow
- Check
editpermission - Load the latest version's snapshot
- Walk the sections and questions in order, assigning
Tnumbers tointroquestions andQnumbers to the rest - Build an old-code → new-code map covering only the questions that actually change
- Update the question codes in a transaction
- Re-point branch destinations, branch condition sources, and visibility condition sources using the map
- Return the renumbered survey
Sequence Diagram
sequenceDiagram
participant Client
participant API
participant DB
Client->>API: POST /api/surveys/{surveyId}/questions/renumber
API->>API: Check edit permission
API->>DB: Load the latest version's snapshot
API->>API: Assign T numbers to intro, Q numbers to the rest
alt No change
API-->>Client: 200 OK (the current survey)
else
API->>DB: Begin transaction
API->>DB: Update the question codes
API->>DB: Re-point destinations and branch condition sources
API->>DB: Re-point visibility condition sources
API->>DB: Commit
API-->>Client: 200 OK
end
References to unchanged codes are left alone
So that a mutual rename such as swapping Q2 and Q3 is not substituted twice, re-pointing is applied once per row against the values read before renumbering. References to questions whose code did not change are kept as they are.
A failure does not undo the original operation
The frontend only surfaces a failure of this API as a warning, because the original operation (reorder, delete, and so on) has already completed. Codes may therefore be left out of sequence.
Archive a Survey
Overview
Changes the survey's status to Archived. Equivalent to calling PATCH /api/surveys/{surveyId} with status set to Archived.
URI
Response (200 OK)
Returns the updated survey schema.
Error Handling
| Description | Status code | Status name |
|---|---|---|
Survey does not exist, or edit permission is missing |
404 | Not Found |
Export JSON
Overview
Exports the survey as questionnaire JSON, the input the Chrome extension uses when pushing into CS.
The export has side effects.
- The status of the survey and of the latest version becomes Exported
- All of the survey's questions are registered into the question library (existing entries from the same survey are replaced)
URI
The two are aliases for the same operation.
Response (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": []
}
]
}
]
}
}
| Field | Type | Notes |
|---|---|---|
| exportedAt | string | Export timestamp (ISO 8601) |
| metadata | object | The survey's theme information and latest version number |
| sections[].questions[] | object[] | The full question configuration |
Error Handling
| Description | Status code | Status name |
|---|---|---|
Survey does not exist, or edit permission is missing |
404 | Not Found |
Processing Flow
Sequence Diagram
sequenceDiagram
participant Client
participant API
participant DB
participant Library as Question library
Client->>API: POST /api/surveys/{surveyId}/export
API->>API: Check edit permission
API->>DB: Load the survey and latest version snapshot
API->>DB: Begin transaction
API->>DB: Set the survey status to Exported
API->>DB: Set the latest version status to Exported
API->>Library: Delete this survey's entries and re-register them
API->>DB: Commit
API->>API: Build the questionnaire JSON
API-->>Client: 200 OK
Set or Clear a Favorite
Overview
Sets or clears the survey's favorite state. Favorites are tracked per user.
URI
Request Body
Validation Rules
| Field | Rule |
|---|---|
| favorite | Required. Boolean. true to add, false to remove |
Response (200 OK)
Error Handling
| Description | Status code | Status name |
|---|---|---|
| Malformed request body | 400 | Bad Request |
| Survey does not exist, or permission is missing | 404 | Not Found |