> ## Documentation Index
> Fetch the complete documentation index at: https://docs.puntego.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conditional and multistep Forms

> Author bounded Forms with ordered steps, deterministic branches, typed required fields, and durable submission receipts.

Forms are an Experience type for collecting required, typed responses inside the customer's product. Every Form is a sequence of ordered steps with deterministic branching.

## Author a form

Create a **Form** in **Dashboard → Guides**. A new Form starts with two steps, which you can reorder, branch, or extend up to the limits below.

Each step has:

* A stable ID, title, and optional description.
* One to five required text, single-choice, or scale fields.
* An optional condition based on one single-choice or scale field from an earlier step.

Conditions support `equals` and `not_equals`. Text comparisons, references to the current or a later step, nested expression trees, and arbitrary code are not supported. These boundaries keep branch evaluation deterministic in the guide editor, the visitor runtime, and the Worker.

## Limits

| Limit | Maximum |
| - | -: |
| Steps per Form | 2 to 8 |
| Fields per step | 5 |
| Fields across the Form | 20 |
| Choices per single-choice field | 10 |
| Text response length | 1,000 characters |

Every field in a visible step is required. A hidden step is omitted from the submission. The Worker recalculates the visible branch from the submitted answers and rejects missing visible fields, answers for hidden fields, unknown options, out-of-range scales, duplicate question IDs, and forward condition references.

## Definition shape

Form content carries its fields in `steps`. A Form needs at least two of them:

```ts theme={null}
const content = {
  kind: 'form',
  title: 'Plan request',
  tone: 'brand',
  dismissible: true,
  presentation: 'modal',
  submitLabel: 'Send request',
  thankYouMessage: 'Thanks. Your request was saved.',
  steps: [
    {
      id: 'plan',
      title: 'Choose a plan',
      questions: [
        {
          id: 'plan_type',
          kind: 'single_choice',
          label: 'Which plan are you evaluating?',
          options: [
            { id: 'starter', label: 'Starter' },
            { id: 'enterprise', label: 'Enterprise' },
          ],
        },
      ],
    },
    {
      id: 'rollout',
      title: 'Plan the rollout',
      showWhen: {
        questionId: 'plan_type',
        operator: 'equals',
        value: 'enterprise',
      },
      questions: [
        { id: 'rollout_size', kind: 'scale', label: 'How large is the rollout?', max: 10 },
      ],
    },
  ],
};
```

## Visitor submission

The built-in embed submits the completed visible branch to `POST /api/visitor/experiences/engage` as one `form_response` event:

```json theme={null}
{
  "kind": "form_response",
  "value": {
    "surveyAnswers": [
      { "questionId": "plan_type", "surveyOptionId": "enterprise" },
      { "questionId": "rollout_size", "surveyScale": 7 }
    ]
  }
}
```

An accepted response includes a durable `submissionReceiptId`. Retrying an identical request with the same idempotency key returns the same receipt with `duplicate: true`; changing the payload under that key is rejected.

<Note>
  Step progress and draft answers stay inside the active Experience. Puntego does not write Form progress into the host product's URL. A refresh starts the visitor surface again unless the host implements its own headless persistence.
</Note>

## Current boundaries

* Conditions use one prior choice or scale field; AND/OR condition groups are not available.
* All visible fields are required; optional fields are not available.
* Forms collect responses. They do not execute arbitrary code or a write action on submit.
* Form submission analytics count one accepted response, regardless of the number of visible fields.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.