Create a form
Creates a form or survey with its own public page that anyone can open and answer.
$0.01 a call
From your agent’s balance. A call that fails costs nothing.
An example
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.
Your agent callsforms_create$0.01 a call
The example business is Halverson Cycle & Repair, a bike shop with a repair workshop in Portland, Oregon. The reply is the one the tool really gives.
{
"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)"
}
]
}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.
What it does
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.
What comes back
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. Every reply also carries cost_usd and balance_usd.
Inputs
| Name | Type | What it is |
|---|---|---|
titleRequired | string | 1 to 200 characters. |
fieldsRequired | array of objects | The questions in order. When changing a form, this replaces the whole list. 1 to 100 items. |
fields[].id | string | 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[].typeRequired | string | One of: short_text,long_text,email,phone,url,number,choice,multi_choice,rating,nps,date,yes_no,consent,statement. |
fields[].label | string | 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 | Smaller text under the question. Up to 2,000 characters. |
fields[].include_time | boolean | date: a time too (answers like 2026-11-03T09:30). |
fields[].range | boolean | date: a first and a last day (2026-11-03/2026-11-07). |
fields[].earliest | string or null | date: the first day that can be picked: "2026-11-01", "today", "today+1". Up to 20 characters. |
fields[].latest | string or null | date: the last day that can be picked: "2026-12-31", "today+60", "today". Up to 20 characters. |
fields[].required | boolean | Default: false. |
fields[].placeholder | string | short_text, long_text, email, phone, url and number only. Up to 200 characters. |
fields[].default_country | string or null | phone: the country of numbers typed without a +, like "US". Exactly 2 characters. |
fields[].min | number or null | number: the smallest answer. |
fields[].max | number or null | number: the largest answer. |
fields[].integer | boolean | number: whole numbers only. |
fields[].options | array of string or object | 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 | multi_choice: the fewest options. At least 1. |
fields[].max_selections | integer or null | multi_choice: the most options. At least 1. |
fields[].scale | integer | rating: 3 to 10 (default 5). 3 to 10. |
fields[].low_label | string | rating and nps: words under the lowest score. Up to 60 characters. |
fields[].high_label | string | rating and nps: words under the top score. Up to 60 characters. |
fields[].show_if | object or null | 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.fieldRequired | string | An earlier field's id. |
fields[].show_if.equalsRequired | any | 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 | Shown under the title. Up to 2,000 characters. |
submit_label | string | The button's words (default "Submit"). 1 to 40 characters. |
thank_you_title | string | Shown after sending (default "Thank you"). 1 to 120 characters. |
thank_you_message | string | Up to 1,000 characters. |
redirect_url | string or null | An https:// page to send people to after they submit. Empty or null: none. Up to 2,000 characters. |
close_at | string or null | 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 | Stop after this many responses. 0 or null: no limit. 0 to 1,000,000. |
notify_email | string or null | 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 | 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 | 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[].actionRequired | string | One of: open_ticket,create_deal,add_row. |
on_response[].priority | string | One of: low,normal,high,urgent. |
on_response[].pipeline | string | Up to 80 characters. |
on_response[].stage | string | Up to 80 characters. |
on_response[].amount_field | string | Up to 40 characters. |
on_response[].table | string | Up to 80 characters. |
on_response[].columns | object | |
save_to_crm | boolean | 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 | 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. |
The call
Over MCP, call forms_create on https://api.conecto.chat/mcp/forms. Over REST:
curl -X POST 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)"}]}'When it refuses
A refused call costs nothing and says what to do next.
| Code | When | What to do |
|---|---|---|
invalid_input400 | 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_outbound402 | 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). |
conflict409 | The form could not get its link just now. | Call again. |
More Forms tools
All 12 tools- Change a form
forms_updateChanges a form's fields or settings; only what you pass changes.$0.01 a call - Get a form
forms_getOne form with its fields, settings, public link, whether it takes responses (and why not) and its response count.Free* - List forms
forms_listThe business's forms, newest first, with their links, whether each takes responses, and their response counts.Free* - List responses
forms_list_responsesA form's responses, newest first, each answer with its question and a readable value.Free* - Get a response
forms_get_responseOne response by its response_id, with every answer readable.Free* - Summarize responses
forms_summaryA form's results at a glance: choice counts, rating averages, the NPS score, yes and no shares, numbers and the latest text answers.Free* - Export responses to CSV
forms_export_responsesSaves a CSV of a form's responses in the file store and returns a download link.$0.001 a call - Close a form
forms_closeStops a form taking responses; its page then says it is closed.$0.001 a call
Give this to your agent.
Set up Conecto from https://conecto.chat/SKILL.md