Form config overview
A form config describes the pages, fields, endings, and design of a form. Use it when you create or update a form.
Top-level keys
The config is stored as the form’s draft (preview_config) and published version (live_config). Form settings are a separate object.
| Key | Required | What it contains |
|---|---|---|
mode | No | Display mode: typeform, tally, page, compact, quiz, or special. create_form sets an omitted mode to page. |
start | No | Optional welcome page with an id, type: "start", and optional ui elements and button_label. |
pages | Yes | An array of question pages. Each page has type: "form" and can have an id, ui elements, button_label, next routing, and randomize_order. |
end | No | One ending or an array of endings. Endings can contain display blocks only; publishing rejects input fields on an ending with INVALID_END_PAGE_UI. |
end_logic | No | Rules for choosing an ending. It is validated when you publish. Conditional endings and per-ending redirects run in page and tally modes, or when mode is unset. |
design | No | Visual settings such as theme, colors, typography, and layout. |
Example
This config has two question pages, three fields, and one ending. The ui array holds fields and display blocks in their display order.
{
"mode": "page",
"pages": [
{
"type": "form",
"id": "p1",
"ui": [
{
"type": "short_text_input",
"name": "full_name",
"label": "What is your name?",
"required": true
},
{
"type": "email_input",
"name": "email",
"label": "What is your email?",
"required": true
}
]
},
{
"type": "form",
"id": "p2",
"ui": [
{
"type": "multiple_choice",
"name": "topic",
"label": "What would you like help with?",
"options": ["Getting started", "Billing", "Something else"]
}
]
}
],
"end": [
{
"id": "e0",
"type": "end",
"ui": [
{
"type": "text",
"copy": "Thanks for getting in touch."
}
]
}
],
"design": {
"theme": "light"
}
}Fields and pages
Every field needs a type and a non-empty name. The name is the key used for that field’s answer in submission data. The required property defaults to false.
A question page has type: "form". Its id and ui are optional. Use next for page routing and randomize_order to show each respondent the page’s questions in a different order.
Draft and published configs
preview_config is the draft config. live_config is the published version. Config updates replace the whole draft and require concurrency protection: REST uses draft_hash or If-Match, and MCP update_form uses expected_updated_at. Publishing is a separate operation. Publishing normalizes the draft, so its draft_hash changes. Re-read the form before the next draft write.
MCP create_form supplies a default ending if end is omitted: [{ "id": "e0", "type": "end", "ui": [] }].
Form settings are stored separately from both configs. Hidden fields are declared in settings, not in the config. CAPTCHA is also a form setting, not a config field. Configure it with the captcha settings key, such as { "enabled": true, "provider": "turnstile" }, through MCP update_form_settings. Settings changes apply to published forms immediately, without publishing.
Ending selection
When end_logic has multiple conditions, the first matching condition selects the ending. If none match, the default target is used; if there is no default, the first ending is used.
Publishing rejects invalid ending targets, invalid redirect URLs, unreachable endings, or end logic without endings with INVALID_END_LOGIC.
Get the config schema
The MCP tool get_form_config_schema takes no input and returns the form config’s draft-07 JSON Schema. It is generated from the same definitions the product validates with. The MCP workflow recommends calling it before generating a config.