Build
Create surveys from scratch or iterate on existing ones. This page covers the document model, question and block operations, and the configuration surface area available through the API and the conversational agent.
Document model
A survey contains an ordered list of blocks. Each block contains an ordered list of questions. Each question has a type, text, options (where applicable), configuration, and optional logic (skip rules and display conditions).
Survey
└─ Block A ("Screener")
│ ├─ Q1 select/single "What is your age range?"
│ └─ Q2 select/multi "Which brands have you purchased?"
└─ Block B ("Evaluation")
├─ Q3 grid "Rate each brand on these attributes"
├─ Q4 text "What else should we know?"
└─ Q5 nps "How likely are you to recommend us?"
The full document is stored as JSON in every survey version. Draft surveys have a single version; published surveys accumulate versions as edits are made (see Lifecycle).
Creating a survey
REST API
curl -X POST https://surveys.flashpoint.ai/api/v1/surveys \
-H "Content-Type: application/json" \
-H "X-Service-Token: $TOKEN" \
-H "X-Team-ID: $TEAM_ID" \
-H "X-User-ID: $USER_ID" \
-d '{
"name": "Brand Perception Study Q1 2026",
"objective": "Understand how B2B SaaS buyers perceive our brand vs. competitors after the rebrand",
"language": "en",
"subtype": "online",
"audience_description": "US adults 25-54 who have purchased SaaS products in the last 12 months",
"sample_size": 500,
"survey_time_minutes": 12
}'
Response (201 Created):
{
"id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"name": "Brand Perception Study Q1 2026",
"objective": "Understand how B2B SaaS buyers perceive our brand vs. competitors after the rebrand",
"status": "draft",
"stage": "design",
"language": "en",
"subtype": "online",
"current_version": 1,
"revision": 1,
"audience_description": "US adults 25-54 who have purchased SaaS products in the last 12 months",
"sample_size": 500,
"survey_time_minutes": 12,
"published_at": null,
"created_at": "2026-05-26T14:00:00Z",
"created_by": "f0e1d2c3-b4a5-6789-0123-456789abcdef",
"document": { "blocks": [] }
}
Agent
"Create a survey called Brand Perception Study Q1 2026 targeting US adults 25-54 who have purchased SaaS products in the last 12 months. The objective is to understand how B2B SaaS buyers perceive our brand vs. competitors after the rebrand."
The agent calls create_survey and returns the survey ID for subsequent operations.
Adding questions
Questions are added one at a time via add_question. Each call appends the question to a target block (creating the block if it does not exist). Labels are auto-assigned (Q1, Q2, ...) unless you specify one.
For the complete list of question types and their configuration options, see Question types.
Example: single-select with options
Via the API, add questions by including them in the document when calling PATCH /api/v1/surveys/{id}. Each question needs an id, type, label, text, options, and config. The server validates the document against the canonical schema on save.
The agent approach is simpler — it calls add_question with just the essentials and the server fills in IDs, labels, timestamps, and canonical field shapes:
"Add a single-select question asking about the respondent's age range with options 18-24, 25-34, 35-44, 45-54, and 55+. Include a 'Prefer not to say' option. Put it in a block called Screener."
Supported question types
| Type | Subtype | What it captures |
|---|---|---|
select | single | Pick one from a list |
select | multi | Pick any number from a list |
text | — | Free-form open response |
number | — | Numeric input with optional min/max |
nps | — | Net Promoter Score (0-10 scale) |
ranking | — | Drag to rank options by preference |
grid | (empty) | Matrix: one answer per row |
grid | multi | Matrix: multiple answers per row |
maxdiff | — | Best/worst scaling exercise |
conjoint | — | Choice-based conjoint analysis |
van-westendorp | — | Price sensitivity meter (four price points) |
currency | — | Currency amount input |
percentage | — | Single 0-100 percentage |
multi-percentage | — | Multiple percentage inputs |
percent-sum | — | Allocate percentages that must total 100 |
year | — | Year input |
zipcode | — | Postal code with locale-specific validation |
contact-form | — | Structured contact fields (name, email, phone) |
ai-chat | — | Conversational AI follow-up probe |
transition | — | Display-only text between sections (no answer collected) |
terminate | — | Ends the survey (for disqualification routing) |
variable | — | Computed hidden field |
Blocks
Blocks are the structural unit of a survey. They group related questions and control section-level behavior.
Creating a block
The agent creates blocks on demand. If you call add_question with a block_name that does not exist, the block is created automatically. To create an empty block ahead of time:
"Add a block called Demographics"
Via the API, blocks are part of the document. Add a new entry to the blocks array in a PATCH /api/v1/surveys/{id} call.
Block configuration
| Field | Type | Description |
|---|---|---|
name | string | Display name shown to survey authors (not respondents) |
config.randomize | boolean | Randomize question order within this block per respondent |
config.loop | boolean | Repeat this block for each option selected in a source question |
config.loopSourceQuestionId | string | UUID of the question whose selected options drive the loop |
Block operations
| Operation | Agent command | What it does |
|---|---|---|
| Rename | "Rename the Demographics block to Background" | Changes the block's display name |
| Duplicate | "Duplicate the Screener block" | Deep-copies the block and all questions with new IDs and labels |
| Delete | "Delete the Evaluation block" | Removes the block and all its questions; cleans up skip logic references |
Options configuration
Options on select, ranking, grid, and maxdiff questions support these configuration properties:
| Config field | Type | Effect |
|---|---|---|
config.randomize | boolean | Shuffle option order per respondent to reduce order bias |
config.ui | string | Rendering mode: radio (default for single), checkbox (default for multi), dropdown |
config.minSelections | integer | Minimum number of selections required (multi-select only) |
config.maxSelections | integer | Maximum number of selections allowed (multi-select only) |
config.options.groups | array | Option grouping for grouped randomization |
Special option types
type value | Behavior |
|---|---|
user | Standard option (default) |
nota | "None of the above" — exclusive; clears other selections in multi-select |
other | Write-in option with a text field |
dontknow | "Don't know" escape option |
optout | "Prefer not to say" |
notapplicable | "Not applicable" |
Opt-out
Questions can be configured with a top-level optout object to let respondents skip the question:
{
"optout": {
"allowed": true,
"text": "Prefer not to answer"
}
}
Reordering questions
To reorder questions, pass the complete list of question UUIDs in the desired order. Questions are redistributed proportionally across existing blocks.
"Reorder the questions so Q3 comes before Q2"
Via the API, the agent uses the reorder_questions tool, which requires every question UUID in the survey:
{
"survey_id": "a1b2c3d4-...",
"question_order": [
"uuid-of-q1",
"uuid-of-q3",
"uuid-of-q2",
"uuid-of-q4",
"uuid-of-q5"
]
}
Survey settings
Metadata fields can be updated independently of the document via PATCH /api/v1/surveys/{id}:
| Field | Type | Description |
|---|---|---|
name | string | Survey display name |
objective | string | Research objective (used by the agent for context) |
language | string | ISO 639-1 language code (en, es, fr, ja, ...) |
subtype | string | online or phone — affects export format and rendering |
audience_description | string | Target audience description |
sample_size | integer | Target number of complete responses |
survey_time_minutes | integer | Expected completion time in minutes |
distribution_preference | string | Default distribution method |
research_plan | string | Free-form research plan text |
settings | object | Additional key-value settings |
Reading a survey
curl https://surveys.flashpoint.ai/api/v1/surveys/$SURVEY_ID \
-H "X-Service-Token: $TOKEN" \
-H "X-Team-ID: $TEAM_ID" \
-H "X-User-ID: $USER_ID"
The response includes all metadata fields plus the full document from the latest version:
{
"id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"name": "Brand Perception Study Q1 2026",
"status": "draft",
"current_version": 1,
"revision": 3,
"document": {
"blocks": [
{
"id": "blk-001",
"label": "A",
"name": "Screener",
"config": {},
"questions": [
{
"id": "q-001",
"type": "select",
"subtype": "single",
"label": "Q1",
"text": "What is your age range?",
"config": { "required": true, "ui": "radio" },
"options": [
{ "id": "opt-1", "text": "18-24", "label": "1", "type": "user" },
{ "id": "opt-2", "text": "25-34", "label": "2", "type": "user" }
],
"skips": []
}
]
}
]
}
}
For published surveys with pending edits, GET returns the latest version (the working draft), while current_version in the metadata still points at the live version respondents see.
Listing surveys
curl "https://surveys.flashpoint.ai/api/v1/surveys?status=draft&limit=10" \
-H "X-Service-Token: $TOKEN" \
-H "X-Team-ID: $TEAM_ID" \
-H "X-User-ID: $USER_ID"
Response:
{
"items": [
{
"id": "a1b2c3d4-...",
"name": "Brand Perception Study Q1 2026",
"status": "draft",
"stage": "design",
"created_by": "f0e1d2c3-...",
"created_at": "2026-05-26T14:00:00Z"
}
],
"total": 1,
"limit": 10,
"offset": 0
}
Filtering options: status (draft, active, paused, completed, archived), workspace_id, limit (1-200), offset.
Pre-publish validation
Before publishing, run the spellcheck endpoint to catch broken logic references, invalid DSL expressions, and unreachable questions:
curl https://surveys.flashpoint.ai/api/v1/surveys/$SURVEY_ID/spellcheck \
-H "X-Service-Token: $TOKEN" \
-H "X-Team-ID: $TEAM_ID" \
-H "X-User-ID: $USER_ID"
{
"unknown_identifiers": [],
"invalid_dsls": [],
"unreachable_questions": [],
"post_logic_identifiers": []
}
An empty result means the survey is clean. Non-empty arrays describe specific issues — fix them before publishing.
Next steps
- Take a draft live and manage versions: Lifecycle & versioning
- Start from a pre-built design: Templates
- Hand the survey to respondents: Distribute
- Import an existing survey from a Word doc: Import & export