Skip to content

Creating forms

Three ways to start a form - describe it to the AI form builder, start from a template, or start empty - in the dashboard, the REST API and MCP.

There are three ways to start a new form. The new form screen in the dashboard offers all three, and the REST API and MCP server can do the same.

Way to start Dashboard REST API MCP
Describe the form in plain English Describe it POST /api/v1/forms/generate generate-form
Start from a ready-made template Start from a template GET /api/v1/form-templates, then POST /api/v1/forms with template list-form-templates, then create-form with template
Start with your own fields Start empty POST /api/v1/forms with name and schema create-form with name and schema

Whichever way you start, the form is saved through the same action and checked against the same schema rules, so a form made one way can be edited any other way.

A new form is published as soon as it is created, unless you pass draft: true. Then it starts unpublished and takes sandbox submissions only until you publish it. See create an unpublished form.

Start from a template

Templates are ready-made drafts: a name, a description for the spam filter, a schema and settings. Some also turn on the autoresponder or add a smart rule.

Key Name Category Asks for Also sets
contact Simple contact form General Name (required), Email (required), Message (required) Autoresponder
service-business Service business enquiry Sales Name (required), Email (required), Phone, What do you need? (required), Preferred date, Tell us a bit more (required) Autoresponder; smart rule “Must be an enquiry about our services, not a sales pitch to us”
quote-request Quote request Sales Name (required), Work email (required), Company (required), Budget, Timeline, Project details (required) Smart rule “Must describe a real project they want quoted”
newsletter Newsletter signup Marketing Email (required), First name, I agree to receive emails (must be ticked) Notification email off
waitlist Product waitlist Marketing Work email (required), Company, Team size, What would you use it for? Autoresponder
content-download Content download Marketing First name (required), Last name (required), Work email (required), Company (required), Job title, Send me occasional product news Autoresponder; smart rule “Must use a company email address, not a personal one”
feedback Customer feedback Product How would you rate us? (required), What went well?, What could be better?, Email (if you would like a reply) Nothing extra
bug-report Bug report Product Email (required), How bad is it? (required), Steps to reproduce (required), Page where it happened, Screenshot Nothing extra
event-rsvp Event RSVP Events Name (required), Email (required), Can you make it? (required), Extra guests, Dietary requirements Autoresponder
job-application Job application Hiring Full name (required), Email (required), Role you are applying for (required), LinkedIn or portfolio, CV (required), Why you? Autoresponder

Create a form from a template

Pass "template": "<key>" when you create a form. The template’s fields and settings are used, and anything else you pass overrides them, so name and schema become optional. An unknown key is a 422 on template.

The example below uses illustrative values.

curl -X POST https://YOUR-QUICKFORMS-HOST/api/v1/forms \
  -H "Authorization: Bearer $QUICKFORMS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"template": "event-rsvp", "name": "Summer party RSVP", "mode": "sandbox"}'
{
  "tool": "create-form",
  "arguments": { "template": "event-rsvp", "name": "Summer party RSVP", "mode": "sandbox" }
}

The response is the created form, the same as any POST /api/v1/forms.

List the templates

GET /api/v1/form-templates returns every template with its key, name, summary, category, fields (the field labels) and the full draft. The MCP tool list-form-templates returns the same list without the draft. See the API reference for an example response.

Describe it to the AI form builder

Describe the form in plain English, for example “a quote request form for a garden landscaping business”, and the AI form builder returns a draft. The draft has:

  • A name and a schema of fields.
  • A description, which the spam filter reads as context.
  • Up to 3 smart rules for the spam filter.
  • A success message.
  • An autoresponder, turned on or off, with a subject and body.

Nothing is saved until you say so. In the dashboard the draft opens in the editor. Through the API and MCP you get the draft back, or pass save: true to create the form in one step.

What happens to the model’s answer

The builder asks an OpenAI model for a form in a fixed structure, then cleans the answer before you see it:

  • Fields with a type quickforms doesn’t support are dropped.
  • Field names are made safe (lowercase letters, numbers and underscores) and unique within the form.
  • Choice fields (select, radio, checkboxes) with no options are dropped.
  • Only the field keys that matter for each type are kept, and min and max are dropped from date fields.
  • The result is validated like any other schema.

Generate a draft

The example prompt and draft below are illustrative. The model’s answer varies from request to request.

curl -X POST https://YOUR-QUICKFORMS-HOST/api/v1/forms/generate \
  -H "Authorization: Bearer $QUICKFORMS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "A quote request form for a garden landscaping business", "save": false}'
{
  "tool": "generate-form",
  "arguments": { "prompt": "A quote request form for a garden landscaping business", "save": false }
}
{
  "data": {
    "draft": {
      "name": "Landscaping quote",
      "description": "Homeowners asking for a quote for garden landscaping work.",
      "schema": {
        "fields": [
          { "name": "name", "type": "text", "label": "Name", "required": true },
          { "name": "email", "type": "email", "label": "Email", "required": true },
          { "name": "postcode", "type": "text", "label": "Postcode", "required": true },
          { "name": "work", "type": "checkboxes", "label": "What work do you need?", "required": true, "options": ["Design", "Planting", "Paving", "Fencing"] },
          { "name": "details", "type": "textarea", "label": "Tell us about your garden", "required": false }
        ]
      },
      "settings": {
        "success_message": "Thanks, we will be in touch about your quote.",
        "autoresponder": { "enabled": true, "subject": "Thanks {{name}}, we got your quote request", "body": "..." },
        "spam": { "rules": ["Must be a request for garden landscaping work"] }
      }
    }
  }
}

The draft is in the same shape POST /api/v1/forms and create-form accept, so you can edit it and send it straight back to create the form. With save: true the response is the created form with status 201, the same as POST /api/v1/forms.

Errors and limits

Status When
422 on prompt The prompt is shorter than 5 or longer than 2000 characters.
422 on prompt The builder is not configured (no OPENAI_API_KEY, or QUICKFORMS_FORM_BUILDER is off).
422 on prompt The model could not create a form. Try again.
422 on schema.* The cleaned draft still fails schema validation.
429 The user has used their generated forms for the hour.

Generating is rate limited to 30 forms an hour per user by default (QUICKFORMS_FORM_BUILDER_PER_HOUR). The MCP tool returns an error saying to try again later instead of a 429.

Configuration

The builder uses laravel/ai with the OpenAI provider.

Variable Default What it does
OPENAI_API_KEY none OpenAI API key. The builder is unavailable without it.
QUICKFORMS_FORM_BUILDER true Turn the AI form builder on or off.
QUICKFORMS_FORM_BUILDER_MODEL gpt-6-luna OpenAI model used to design forms.
QUICKFORMS_FORM_BUILDER_PER_HOUR 30 Generated forms allowed per user per hour.

Start empty

Create a form with a name and your own schema. See the schema reference for every field type and option, and POST /api/v1/forms for a full example.

Type to search…

↑↓ navigate↵ selectEsc close