---
name: "forms_create"
area: "forms"
title: "Create a form"
price: "$0.01"
method: "POST"
url: "https://api.conecto.chat/v1/tools/forms_create"
mcp_server: "https://api.conecto.chat/mcp/forms"
auth: "Authorization: Bearer <conecto_sk_ key>"
docs_url: "https://conecto.chat/tools/forms/forms_create"
---

# Create a form (`forms_create`)

Creates a form or survey with its own public page that anyone can open and answer.

Create a form or survey with its own public page at https://cncto.co/f/<slug>, which anyone can open and answer; share that link. Field types: short_text, long_text, email, phone (default_country), url, number (min, max, integer), choice and multi_choice (options; multi_choice also min_selections, max_selections), rating (scale 3 to 10, default 5; low_label, high_label), nps (0 to 10; low_label, high_label), date (include_time for a time too, range for a first and a last day, earliest and latest as "2026-11-01" or "today", "today+7", "today-30"; answers read 2026-11-03, 2026-11-03T09:30, 2026-11-03/2026-11-07), yes_no, consent (a checkbox; its label may hold one link written [text](https://...)), statement (text only, no answer). Every field takes type, label, help, required, an id (generated from the label when left out; answers are keyed by it) and show_if {"field": "<an earlier field's id>", "equals": <answer>} to show it only when that answer was given. Each response received costs $0.01, up to 10,000 a month per account.

Price: $0.01 a call. A call that fails costs nothing.

## Use it when

The business wants to collect answers from people: requests, applications, feedback, sign-ups.

- For a newsletter sign-up with confirmed addresses, use [newsletters_create](https://conecto.chat/tools/newsletters/newsletters_create.md).

## Say this to your agent

> Make a sign-up form for our ride club: name, email, their bike, how they ride, miles a week, and agreeing to the club rules. Add riders to the CRM.

## Inputs

| Name | Type | Required | Description | Allowed values | Default |
|---|---|---|---|---|---|
| `title` | string | yes | 1 to 200 characters. |  |  |
| `fields` | array of objects | yes | The questions in order. When changing a form, this replaces the whole list. 1 to 100 items. |  |  |
| `fields[].id` | string | no | Stable id; answers are keyed by it. Generated from the label when left out. Pass it back when you change the form, or a renamed field becomes a new one. Matches ^[a-z0-9_]{1,40}$. |  |  |
| `fields[].type` | string | yes, in each item of `fields` |  | `"short_text"`, `"long_text"`, `"email"`, `"phone"`, `"url"`, `"number"`, `"choice"`, `"multi_choice"`, `"rating"`, `"nps"`, `"date"`, `"yes_no"`, `"consent"`, `"statement"` |  |
| `fields[].label` | string | no | The question. A statement's label is the text it shows. A consent label may hold one link: "I agree to the [terms](https://acme.com/terms)". Up to 1,000 characters. |  |  |
| `fields[].help` | string | no | Smaller text under the question. Up to 2,000 characters. |  |  |
| `fields[].include_time` | boolean | no | date: a time too (answers like 2026-11-03T09:30). |  |  |
| `fields[].range` | boolean | no | date: a first and a last day (2026-11-03/2026-11-07). |  |  |
| `fields[].earliest` | string or null | no | date: the first day that can be picked: "2026-11-01", "today", "today+1". Up to 20 characters. |  |  |
| `fields[].latest` | string or null | no | date: the last day that can be picked: "2026-12-31", "today+60", "today". Up to 20 characters. |  |  |
| `fields[].required` | boolean | no |  |  | `false` |
| `fields[].placeholder` | string | no | short_text, long_text, email, phone, url and number only. Up to 200 characters. |  |  |
| `fields[].default_country` | string or null | no | phone: the country of numbers typed without a +, like "US". Exactly 2 characters. |  |  |
| `fields[].min` | number or null | no | number: the smallest answer. |  |  |
| `fields[].max` | number or null | no | number: the largest answer. |  |  |
| `fields[].integer` | boolean | no | number: whole numbers only. |  |  |
| `fields[].options` | array of string or object | no | choice and multi_choice: ["Basic", "Pro"], or [{"id": "basic", "label": "Basic"}] to keep ids stable when you rename an option. 1 to 100 items. |  |  |
| `fields[].min_selections` | integer or null | no | multi_choice: the fewest options. At least 1. |  |  |
| `fields[].max_selections` | integer or null | no | multi_choice: the most options. At least 1. |  |  |
| `fields[].scale` | integer | no | rating: 3 to 10 (default 5). 3 to 10. |  |  |
| `fields[].low_label` | string | no | rating and nps: words under the lowest score. Up to 60 characters. |  |  |
| `fields[].high_label` | string | no | rating and nps: words under the top score. Up to 60 characters. |  |  |
| `fields[].show_if` | object or null | no | Show this field only when an earlier field has this answer (for multi_choice: when that option is among the choices). A hidden field is never required. |  |  |
| `fields[].show_if.field` | string | yes, when `fields[].show_if` is given | An earlier field's id. |  |  |
| `fields[].show_if.equals` | any | yes, when `fields[].show_if` is given | The answer that shows the field: an option id (choice, multi_choice), true or false (yes_no, consent), a number (number, rating, nps), a date (date) or text (short_text, email). |  |  |
| `description` | string | no | Shown under the title. Up to 2,000 characters. |  |  |
| `submit_label` | string | no | The button's words (default "Submit"). 1 to 40 characters. |  |  |
| `thank_you_title` | string | no | Shown after sending (default "Thank you"). 1 to 120 characters. |  |  |
| `thank_you_message` | string | no | Up to 1,000 characters. |  |  |
| `redirect_url` | string or null | no | An https:// page to send people to after they submit. Empty or null: none. Up to 2,000 characters. |  |  |
| `close_at` | string or null | no | Stop taking responses at this time (ISO 8601, like 2026-12-31T23:59:00Z; UTC when no offset is given). Empty or null: never. Up to 40 characters. |  |  |
| `max_responses` | integer or null | no | Stop after this many responses. 0 or null: no limit. 0 to 1,000,000. |  |  |
| `notify_email` | string or null | no | Email this address about new responses: at most one email a minute per form, later responses grouped into the next one. Free credit can only notify the owner's email. Empty or null: off. Up to 254 characters. |  |  |
| `confirm_to_respondent` | boolean | no | Email each respondent their answers in the brand kit (form_confirmation wording), to the address they typed in the first email field. $0.002 each; paid accounts only; at most three a day to one address. |  |  |
| `on_response` | array of objects | no | What each response also does on its own, while you are away ($0.01 per action done): {"action": "open_ticket", "priority": "normal"} opens a help desk ticket for the respondent; {"action": "create_deal", "pipeline": "Sales", "stage": "New", "amount_field": "budget"} creates a deal with them as contact; {"action": "add_row", "table": "Leads", "columns": {"Email": "email", "Budget": "budget"}} adds a row, each column from a field id. [] or null: none. Up to 3 items. |  |  |
| `on_response[].action` | string | yes, in each item of `on_response` |  | `"open_ticket"`, `"create_deal"`, `"add_row"` |  |
| `on_response[].priority` | string | no |  | `"low"`, `"normal"`, `"high"`, `"urgent"` |  |
| `on_response[].pipeline` | string | no | Up to 80 characters. |  |  |
| `on_response[].stage` | string | no | Up to 80 characters. |  |  |
| `on_response[].amount_field` | string | no | Up to 40 characters. |  |  |
| `on_response[].table` | string | no | Up to 80 characters. |  |  |
| `on_response[].columns` | object | no |  |  |  |
| `save_to_crm` | boolean | no | Save the person behind each response as a CRM contact. The first email field is the email; a short_text field with id name or full_name (or first_name and last_name) is the name; the first phone field the phone. An existing contact only gets empty fields filled. |  |  |
| `hidden_fields` | array of strings | no | Link values kept with each response: ["ref", "utm_source"] keeps them from https://cncto.co/f/<slug>?ref=abc&utm_source=newsletter. Up to 10 items. |  |  |

## Example

Written for Halverson Cycle & Repair, a bike shop with a repair workshop in Portland, Oregon.

MCP: call `forms_create` on the MCP server `https://api.conecto.chat/mcp/forms` with these arguments:

```json
{
  "title": "Join the ride club",
  "description": "10% off service, and a group ride from the shop every Saturday morning.",
  "save_to_crm": true,
  "fields": [
    {
      "id": "full_name",
      "type": "short_text",
      "label": "Your name",
      "required": true
    },
    {
      "id": "email",
      "type": "email",
      "label": "Email",
      "required": true
    },
    {
      "id": "bike",
      "type": "short_text",
      "label": "Your bike",
      "required": true
    },
    {
      "id": "riding",
      "type": "choice",
      "label": "How do you ride?",
      "options": [
        "Commuting",
        "Gravel",
        "Road",
        "A bit of everything"
      ]
    },
    {
      "id": "miles",
      "type": "number",
      "label": "Miles a week",
      "min": 0,
      "integer": true
    },
    {
      "id": "rules",
      "type": "consent",
      "required": true,
      "label": "I agree to the [club rules](https://halversoncycle.example/ride-club)"
    }
  ]
}
```

REST:

```bash
curl https://api.conecto.chat/v1/tools/forms_create \
  -H "Authorization: Bearer $CONECTO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Join the ride club", "description": "10% off service, and a group ride from the shop every Saturday morning.", "save_to_crm": true, "fields": [{"id": "full_name", "type": "short_text", "label": "Your name", "required": true}, {"id": "email", "type": "email", "label": "Email", "required": true}, {"id": "bike", "type": "short_text", "label": "Your bike", "required": true}, {"id": "riding", "type": "choice", "label": "How do you ride?", "options": ["Commuting", "Gravel", "Road", "A bit of everything"]}, {"id": "miles", "type": "number", "label": "Miles a week", "min": 0, "integer": true}, {"id": "rules", "type": "consent", "required": true, "label": "I agree to the [club rules](https://halversoncycle.example/ride-club)"}]}'
```

## Response

```json
{
  "call_id": "5f0c8a2e-3b7d-4c1e-9a64-2d8e1f7b0c93",
  "tool": "forms_create",
  "status": "succeeded",
  "replayed": false,
  "cost_usd": "$0.01",
  "balance_usd": "$19.75",
  "result": {
    "form": {
      "form_id": "d06fb065-da83-4a05-8154-0c92b4d74ccb",
      "slug": "join-the-ride-club",
      "url": "https://cncto.co/f/join-the-ride-club",
      "title": "Join the ride club",
      "status": "open",
      "accepting_responses": true,
      "closed_reason": null,
      "responses": 0,
      "last_response_at": null,
      "created_at": "2026-10-14T08:00:00+00:00",
      "description": "10% off service, and a group ride from the shop every Saturday morning.",
      "fields": [
        {
          "id": "full_name",
          "type": "short_text",
          "label": "Your name",
          "help": "",
          "required": true,
          "placeholder": "",
          "show_if": null
        },
        {
          "id": "email",
          "type": "email",
          "label": "Email",
          "help": "",
          "required": true,
          "placeholder": "",
          "show_if": null
        }
      ],
      "removed_fields": [],
      "submit_label": "Submit",
      "thank_you": {
        "title": "Thank you!",
        "message": "Your response was sent.",
        "redirect_url": null
      },
      "close_at": null,
      "max_responses": null,
      "notify_email": null,
      "save_to_crm": true,
      "confirm_to_respondent": false,
      "on_response": [],
      "hidden_fields": [],
      "updated_at": "2026-10-14T08:00:00+00:00"
    }
  }
}
```

`result`: The form with its form_id, slug, public url, status, whether it takes responses, its fields and settings, and notes when something needs a look.

## Errors

| Code | Status | When | Fix |
|---|---|---|---|
| `invalid_input` | 400 | A field or setting is not valid: a field type that does not take an option, a missing list of options, a show_if on a later field, a close_at in the past, or save_to_crm without an email field. | Fix what the message names; it points at the field by its place, like fields[2]. |
| `payment_required_for_outbound` | 402 | notify_email is not the owner's email, and the balance is still free credit. | Notify the owner's email, or top up once (POST /v1/topups). |
| `conflict` | 409 | The form could not get its link just now. | Call again. |

The refusals every tool can give (401 key, 402 balance, 429 limits) are on the errors page: https://conecto.chat/docs/errors.md

## Related

- [forms_update](https://conecto.chat/tools/forms/forms_update.md): Changes a form's fields or settings; only what you pass changes. $0.01 a call.
- [forms_get](https://conecto.chat/tools/forms/forms_get.md): One form with its fields, settings, public link, whether it takes responses (and why not) and its response count. Free up to 1,000,000 reads a month.
- [forms_list](https://conecto.chat/tools/forms/forms_list.md): The business's forms, newest first, with their links, whether each takes responses, and their response counts. Free up to 1,000,000 reads a month.
- [forms_list_responses](https://conecto.chat/tools/forms/forms_list_responses.md): A form's responses, newest first, each answer with its question and a readable value. Free up to 1,000,000 reads a month.
- [forms_get_response](https://conecto.chat/tools/forms/forms_get_response.md): One response by its response_id, with every answer readable. Free up to 1,000,000 reads a month.
- [forms_summary](https://conecto.chat/tools/forms/forms_summary.md): A form's results at a glance: choice counts, rating averages, the NPS score, yes and no shares, numbers and the latest text answers. Free up to 1,000,000 reads a month.
- [forms_export_responses](https://conecto.chat/tools/forms/forms_export_responses.md): Saves a CSV of a form's responses in the file store and returns a download link. $0.001 a call.
- [forms_close](https://conecto.chat/tools/forms/forms_close.md): Stops a form taking responses; its page then says it is closed. $0.001 a call.
- [forms_open](https://conecto.chat/tools/forms/forms_open.md): Lets a closed form take responses again. $0.001 a call.
- [forms_delete](https://conecto.chat/tools/forms/forms_delete.md): Deletes a form and all its responses for good; its link stops working. $0.001 a call.
- [forms_delete_response](https://conecto.chat/tools/forms/forms_delete_response.md): Deletes one response for good, for a person who asks to be forgotten, or for spam. Free.
