The config JSON
A form is defined by a single JSON document. It holds the fields, the validation rules, the emails to send, the webhooks to call, and a few settings. Everything about how a form behaves lives here, and it is stored as one value so it can never drift out of sync with itself.
You edit it either as raw JSON or through the structured editor. Both are views of the same document.
Top-level shape
Section titled “Top-level shape”{ "fields": [ /* the inputs the form accepts */ ], "sections": [ /* optional: group the fields into cards or steps */ ], "email": { /* notifications and autoresponders */ }, "webhooks": [ /* endpoints to POST each submission to */ ], "settings": { /* submit label, thank-you screen, layout, and more */ }}Only fields is required. Everything else is optional. Note that email is a single object, not an array, and webhooks is an array because a form can call several endpoints.
A complete example
Section titled “A complete example”Here is a contact form that emails you, sends the visitor a confirmation, and posts to a webhook:
{ "fields": [ { "name": "name", "type": "text", "label": "Your name", "rules": [{ "r": "required" }] }, { "name": "email", "type": "email", "label": "Email", "rules": [{ "r": "required" }, { "r": "email" }] }, { "name": "phone", "type": "tel", "label": "Phone", "rules": [{ "r": "tel" }] }, { "name": "message", "type": "textarea", "label": "Message", "rules": [{ "r": "required" }, { "r": "max:2000" }] }, { "name": "consent", "type": "checkbox", "label": "I agree to be contacted", "rules": [{ "r": "required" }], "consent": true } ], "email": { "notification": { "enabled": true, "to": ["sales@example.com"] }, "confirmation": { "enabled": true, "toField": "email" } }, "webhooks": [ { "url": "https://hooks.example.com/octaforms", "active": true, "secret": "a-long-random-secret-at-least-32-chars" } ], "settings": { "submitLabel": "Send message", "thankYouTitle": "Thanks!", "thankYouText": "We will get back to you shortly." }}The sections
Section titled “The sections”fields (required)
Section titled “fields (required)”An array of the inputs your form accepts. Each field has at least a name and a type, usually a label, and optional validation rules. Field names must be unique.
{ "name": "email", "type": "text", "label": "Email", "rules": [{ "r": "required" }, { "r": "email" }] }Every type and every option is covered in Field types. The rule format is covered in Validation rules.
sections
Section titled “sections”Long forms read better in groups. A section gives a group of fields a title, an optional short text above the fields and an optional note below them:
"sections": [ { "title": "Contact details", "text": "How we can reach you.", "fields": ["name", "email", "phone"] }, { "title": "Your tax return", "fields": ["business", "tax_number", "documents"], "note": "Leave out anything you are not sure about." }]A form has three ways to show its fields:
| Config | What the visitor sees |
|---|---|
no sections |
every field one under another, as before |
sections |
each section as a card, one under another |
sections and settings.layout set to "steps" |
one section at a time, with Back and Next buttons and “Step 2 of 5” |
Sections only change how the form looks. Submissions, webhooks and the CSV export keep the plain list of fields. The notification email and the submission screen follow your sections, with the section titles as headings.
- A section lists field names in the order to show them. The
title,textandnoteare all optional, so a card can have just a short text and no heading. - A field can be in one section only.
- A field you did not put in any section still shows, in a final card without a title, and the editor warns you about it. In the email and on the submission screen those fields come under “Other details”.
- A section whose fields all wait for an answer (
showIf) stays hidden until one of them appears. In steps it is skipped and not counted in “Step 2 of 5”. A section with no fields, only a text, always shows.
In steps, Next checks the fields of the current step on the server before the visitor moves on, so they see the same messages the final submit would give. Without JavaScript every section shows one under another. In the editor, sections are headings in the Fields list, and the steps switch is in the Settings tab.
Controls what gets sent when a submission arrives: a notification to you, and an optional confirmation to the person who submitted. Full details, including subjects, bodies and attachments, are on the Emails page.
webhooks
Section titled “webhooks”An array of endpoints that receive a signed POST for every submission. Each active webhook needs an https URL and a secret of at least 32 characters, used to sign the payload. See Webhooks.
settings
Section titled “settings”Small tweaks to how the form behaves:
| Setting | Effect |
|---|---|
submitLabel |
Text on the submit button. Defaults to “Send”. |
layout |
"steps" shows one section at a time. Leave it out to show sections as cards one under another. See sections. |
thankYouTitle and thankYouText |
The success message shown after submitting. Both fall back to a translated default if left empty. |
redirectUrl |
If set, the visitor is redirected here after a successful submit instead of seeing the thank-you message. Takes priority over the thank-you text. The address can carry answers from the form, see Thank-you page address. |
requireToken |
Defaults to true. Set to false only as a last resort if a security plugin blocks the token endpoint. Honeypot and rate limiting stay active either way. See Anti-spam. |
Thank-you page address
Section titled “Thank-you page address”A thank-you page often needs something from the submission, such as the package someone picked or a number for a conversion tag. Put a field name in braces and OctaForms fills it in:
"redirectUrl": "https://example.com/thanks?package={package}"After someone picks Premium & VIP, they land on https://example.com/thanks?package=Premium%20%26%20VIP&id=123.
{field_name}is that field’s answer.{lead_id}is the submission number and{form_id}the form’s ID. These two win over a field with the same name.- Every value is encoded, so an
&,#or/typed into the form stays part of the value and cannot change where the visitor goes. - A checkbox group gives the ticked options separated by commas. A single checkbox gives
1when ticked. - A name that matches no field, an empty answer and a field hidden by
showIfall give an empty value. Renaming a field therefore never puts{old_name}in the address bar. id=<submission number>is always added at the end, unless your address setsiditself.
How it is stored and validated
Section titled “How it is stored and validated”The config is validated every time you save. Problems come in two kinds:
- Errors block the save. For example, a select field with no options, or an active webhook with a weak secret.
- Warnings let the save through but flag a risk. For example, a honeypot field with a name browsers tend to autofill.
Each problem is tied to the exact place it came from, so the editor can point you straight at it. On save, the previous version is kept, so the raw JSON editor offers a one-step undo.