A form schema is an object with a fields list (1 to 100 fields). The same schema drives validation, the embed widget, notification emails and the dashboard.
{
"fields": [
{ "name": "name", "type": "text", "label": "Your name", "required": true, "max": 120 },
{ "name": "email", "type": "email", "required": true, "message": "We need an email to reply to." },
{ "name": "website", "type": "url", "placeholder": "https://" },
{ "name": "phone", "type": "tel", "pattern": "^[0-9 +()-]{6,20}$" },
{ "name": "seats", "type": "number", "integer": true, "min": 1, "max": 50 },
{ "name": "start", "type": "date", "min": "today" },
{ "name": "plan", "type": "select", "options": ["starter", "pro"] },
{ "name": "topics", "type": "checkboxes", "options": [
{ "value": "api", "label": "REST API" },
{ "value": "mcp", "label": "MCP" }
], "min": 1 },
{ "name": "contact_by", "type": "radio", "enum": ["email", "phone"] },
{ "name": "message", "type": "textarea", "min": 10, "max": 2000, "help": "Tell us a bit about your project." },
{ "name": "cv", "type": "file", "accept": ["pdf", "docx"], "max_size_kb": 4096 },
{ "name": "terms", "type": "checkbox", "accepted": true, "label": "I accept the terms" },
{ "name": "campaign", "type": "hidden", "default": "autumn" }
]
}Field types
| Type | Accepts | min / max | Notes |
|---|---|---|---|
text |
String | Length | Up to 1000 characters. |
textarea |
String | Length | Up to 10000 characters. |
email |
RFC email address | Length | Up to 254 characters. Used as reply-to and for the autoresponder. |
url |
http or https URL | Length | Up to 2048 characters. |
tel |
String | Length | Up to 1000 characters. Combine with pattern. |
number |
Number | Value | Set integer to accept whole numbers only. |
date |
Date | Earliest / latest date | Bounds are dates such as 2026-01-01 or "today". |
select |
One option value | Count (with multiple) | Needs options. Set multiple to accept a list, with no repeats and no longer than the options. |
radio |
One option value | Needs options. | |
checkbox |
Boolean | Values like on, 1 and true become booleans. Set accepted to require it ticked. |
|
checkboxes |
List of option values | Count | Needs options. Post as name[] from HTML. A plain list with no repeats, no longer than the options. |
hidden |
String | Length | Up to 1000 characters. The embed fills it from default. |
file |
Upload | Post the file as multipart, or send an upl_... ID from a direct upload in JSON. accept lists extensions, max_size_kb caps the size. Stored as name, size, mime, disk and path either way. See file uploads. |
|
ranking |
Every option value, best first | - | Needs options. Post as name[] from HTML. A partial ranking is rejected. |
matrix |
{row: column} |
- | Needs rows and options (the columns). Post as name[row] from HTML. A required matrix needs every row. |
signature |
Stored file | - | Drawn on the hosted page or embed and saved as a PNG up to 512 KB. Delivered like a file. This records a drawn signature and is not an e-signing service. |
calculated |
Number | - | Needs a formula. Worked out from earlier answers. Anything sent for it is ignored. |
Field options
| Key | Type | Description |
|---|---|---|
name |
string | Required and unique. Starts with a letter, then letters, numbers, dashes or underscores, up to 64 characters. |
type |
string | Required. One of the types above. |
label |
string | Shown to people and used in error messages. Defaults to the name with dashes and underscores as spaces. |
placeholder |
string | Input placeholder. For a single checkbox, the text next to it. |
help |
string | Help text under the field. |
message |
string | A custom error message used for every rule on this field. Not included in the public schema. |
required |
boolean | Defaults to false. |
min |
number or date | Lower bound. Means length, value, count or date depending on the type. |
max |
number or date | Upper bound, as above. Length limits never exceed the type ceiling. |
integer |
boolean | number only. |
multiple |
boolean | select only. |
accepted |
boolean | checkbox only. The box must be ticked. |
pattern |
string | A regular expression the value must match. Applies to text-like fields and numbers. |
options |
array | For select, radio and checkboxes. Strings, or {"value", "label"} objects. Up to 500. |
enum |
array | Alias for options. |
accept |
array | file only. Allowed extensions such as ["pdf", "png"]. For direct uploads, checked against the file name when the upload URL is issued. |
max_size_kb |
integer | file only. Cannot exceed the installation upload cap. For direct uploads, checked when the upload URL is issued and again on the stored file. |
default |
any | Default value. The embed uses it for hidden fields. |
show_when |
array | Conditions on earlier questions. See conditional questions. |
Showing earlier answers
Use {{field_name}} in a label or help to show an answer given earlier in the form, as people type. Notification emails fill them in too.
Calculated fields
A calculated field works out a number from earlier answers:
{ "name": "total", "type": "calculated", "label": "Total", "formula": "{{quantity}} * {{price}} + 5", "decimals": 2, "prefix": "£" }| Property | Type | What it does |
|---|---|---|
formula |
string | Numbers, {{field}}, + - * / and brackets. Up to 500 characters. It can only use number, select, radio, checkbox, checkboxes and calculated questions that come before it. |
decimals |
integer | 0 to 4. Defaults to 2. |
prefix, suffix |
string | Shown around the result, up to 12 characters each. |
display |
boolean | false keeps the result off the form, for scores. It’s still stored. |
An option adds its score, for example {"value": "large", "label": "Large", "score": 9.5}, or its value if that’s a number. Several ticked options add up, a ticked checkbox is 1, and an unanswered or hidden question is 0. Dividing by zero stores no result.
Conditional questions
Add show_when to show a question only for certain answers. Every condition must match, up to 10 per question.
{
"name": "order_number",
"type": "text",
"required": true,
"show_when": [{ "field": "topic", "operator": "equals", "value": "support" }]
}operator is equals, not_equals, contains, is_set or is_empty. A single checkbox counts as yes when ticked.
A condition can only use a question that comes before it, and not a file field. The hosted page and the embed show and hide questions as people answer. The server applies the same conditions whichever way a submission arrives: a question that isn’t shown isn’t required, and any answer sent for it is dropped.