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.

KeyRequiredWhat it contains
modeNoDisplay mode: typeform, tally, page, compact, quiz, or special. create_form sets an omitted mode to page.
startNoOptional welcome page with an id, type: "start", and optional ui elements and button_label.
pagesYesAn array of question pages. Each page has type: "form" and can have an id, ui elements, button_label, next routing, and randomize_order.
endNoOne 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_logicNoRules 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.
designNoVisual 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.