Skip to content
Join our Slack

Nodes

A node is one block on a page: a question, a Text, Image, or Divider block, a layout row, the Actions button row, the Form Title, or the Thank You screen. Every node shares the same envelope, and its type selects the shape of meta. This page covers the fields and rules every node type shares; each type’s reference page covers only what is specific to it.

Every common node field is listed in the request body of Replace the draft document, under pages › nodes.

public_id is optional on write and always present on read; see Identity. sort_order is required on write, but the server renumbers it from array order within each parent and column, so sending 1, 2, 3 in array order is enough.

There are 33 node types. Each reference page lists the type’s meta fields, its defaults, and a minimal example from the Docs Example Form, and links to the matching editor component.

Each node type has its own page under Node types in the sidebar.

Nine types are not questions: actions, text, image, media, divider, layout_row, form_title, progress_bar, and thank_you. The other 24 collect answers.

  • An omitted meta key that has a product default receives it, and every read returns it. Each reference page lists the defaults. A key without a default stays absent until you set it, which means the same as null.
  • meta is strict: a key the type does not define is rejected with 400 INVALID_INPUT.
  • Enum values, number ranges, and text limits are checked on write.

These rules apply to all 24 question types:

  • Required by default. An omitted validation makes the question required. Send validation: { "required": false } for an optional question.
  • Question text. question is inline rich text with at most 500 visible characters.
  • Placeholder. Where a type has placeholder, it is plain text of up to 200 characters.
  • Default value. default_value pre-fills the answer. Its shape depends on the type. A default the question would not accept as an answer, such as one outside the allowed range or one matching no option, is ignored when the form renders.
  • Placement. A question sits at the page root or in a layout row column (every type except Matrix), and can host supporting content.

These rules apply to the types that take options from select_options_data: Dropdown, Multiselect, Multi Choice, Checkboxes, Yes/No, and Ranking. Matrix uses the same option shape for its rows and columns.

  • Option shape. Each option has a value (up to 1,000 characters) and a label (up to 500). label_formatted is the label as inline rich text; it is derived from label when omitted. Answers store the value, so keep values stable once the form collects responses.
  • Count. select_options_data defaults to an empty list and accepts up to 1,000 options. Publishing needs at least one (FORM_PUBLISH_MISSING_OPTIONS).
  • Default value. default_value names options by value. Values that match no option are ignored.
  • Random order. select_options_randomize: true shuffles the options for each respondent. Default false.
  • Other option. On Dropdown, Multiselect, Multi Choice, and Checkboxes, an option whose value is other is the “Other” choice. The server keeps it last, even in random order. Respondents who pick it must type an answer, and select_options_other_placeholder sets that field’s placeholder (default “Type your answer”).
  • Option layout. On Multi Choice, Checkboxes, Yes/No, and Ranking, select_options_layout applies only when is_select_options_layout_override is true; otherwise the theme’s option layout applies and the server drops the key. Sending select_options_layout without is_select_options_layout_override turns the override on. select_options_colored: null follows the theme’s option colors.

Some text fields take HTML. The server sanitizes it on write and keeps only h1 to h3, p, ul, ol, li, a, strong, em, u, br, and span. Length limits count visible text, not markup.

  • Inline rich text, such as question, label_formatted, and image_caption, is a single line. Plain text is wrapped in a <span>.
  • Block rich text, such as a Text node’s content, can hold several paragraphs, headings, and lists. Plain text is wrapped in a <p>.

Plain-text fields, such as placeholder and button labels, are not sanitized as HTML.

A Layout Row places nodes side by side. The row is a node with column_count in its meta (1 to 3). Its children are ordinary nodes of the same page that point back at it:

  • parent_node_id and column_index are set together. Both are null for a node at the page root.
  • The parent is a layout_row on the same page. Children can appear anywhere in the page’s nodes array; within a column, array order sets their order.
  • column_index is zero-based and must be below the row’s column_count.
  • A row needs at least one child, and a three-column row needs content in every column.
  • Rows cannot be nested: a layout_row never has a parent_node_id.

Every question type except Matrix can sit in a column, and so can Text, Image, Media, and Divider. Actions, Form Title, Progress Bar, Thank You, and another Layout Row cannot.

This page fixture places a Dropdown and a Phone node side by side. The caller chose the row’s public_id so the children can reference it in the same write:

A page with a two-column layout row
{
"public_id": "pQ02",
"name": "Travel",
"type": "normal",
"nodes": [
{
"public_id": "nRow",
"sort_order": 1,
"type": "layout_row",
"meta": {
"column_count": 2
}
},
{
"public_id": "nCty",
"parent_node_id": "nRow",
"column_index": 0,
"sort_order": 1,
"type": "dropdown",
"meta": {
"question": "<span>Country</span>",
"placeholder": "Choose a country",
"select_options_data": [
{
"value": "de",
"label": "Germany"
},
{
"value": "nl",
"label": "Netherlands"
},
{
"value": "pl",
"label": "Poland"
}
],
"validation": {
"required": true
}
}
},
{
"public_id": "nPhn",
"parent_node_id": "nRow",
"column_index": 1,
"sort_order": 1,
"type": "phone_number_input",
"meta": {
"question": "<span>Phone number</span>",
"validation": {
"required": false
}
}
},
{
"public_id": "nNxt",
"sort_order": 2,
"type": "actions",
"meta": {
"label": "Next"
}
}
]
}

Multi-column layouts describes what respondents see, including how columns stack on small screens.

A question can host Text, Image, and Divider nodes between its title and its input. It uses the same parent-and-column pair, with the question as the parent:

  • Set the question’s supporting_content_column_count to 1.
  • Give each child a parent_node_id pointing at the question and a column_index of 0.
  • supporting_content_column_0_alignment on the question aligns the column vertically: top, middle, or bottom.

Only questions can host supporting content, and only those three types can be hosted. A question that sets supporting_content_column_count without any child is rejected; leave the field null on questions without supporting content. The editor side is described in Supporting content.

A node with is_hidden: true stays in the draft, is skipped by Publish Validation, and is absent from the published document:

  • The children of a hidden layout row or question are stripped with it.
  • A layout row whose children are all hidden is stripped too, and a three-column row that loses a whole column contracts to two.
  • Sort orders are renumbered after stripping, so published positions can differ from draft positions.

In the Docs Example Form, the hidden “Company” question (nCmp) is absent from the published “Your details” page, and the Actions node after it moves up one position. See Hidden pages and nodes.

Your next form could be the best-looking thing on your site.

Free forever. Unlimited responses. No signup to start.