Skip to main content
Glama

Create a FoxForm form

foxform_create_form

Create a new form, including per-screen conditional logic. Requires a WRITE-scoped API key.

Args:

  • title (string): form title (required)

  • description (string, optional)

  • theme (string, optional): one of amber|base|midnight|ocean|sunset|forest|lavender|minimal (default amber, the copper-to-amber FoxForm theme)

  • questions (array, optional): array of screen objects ({ id, type, title, required, variableName?, choices?, logic?, ... }); omit to start empty

  • thank_you_message (string, optional)

  • format ('single_question' | 'single_page' | 'chatbot', optional): how the form is presented (see below)

  • sections (array, optional): single_page page groups, [{ id }]

  • chatbot_skin ('instagram' | 'whatsapp', optional): chatbot chrome

  • chatbot_profile (object, optional): chatbot header profile ({ name, handle, followers_text, phone, status, verified, avatar_url })

Returns: { form } with the created form (including its id and slug). The form starts as a draft — call foxform_publish_form to make it live.

Screen fields are validated: unknown fields are REJECTED instead of being stored and ignored, and branching rules are cross-checked against the screen ids in the same payload.

Form format (DEVF-296 / DEVF-322): pass format to choose how the form is presented.

  • 'single_question' (default): one screen at a time (classic).

  • 'single_page': every screen on one scrollable page. Optionally group screens into pages with sections: [{ id }] in order (the 'Section N' label comes from position; no editable title).

  • 'chatbot': an Instagram/WhatsApp DM-style conversation. Set chatbot_skin ('instagram' | 'whatsapp', default instagram) and chatbot_profile (all fields optional, each with a fallback). The question/branching engine is unchanged — only the presentation differs. These fields require the account's form-format feature to be enabled (live in production); when off the API ignores them and the form stays single_question.

CONDITIONAL LOGIC (branching), per screen — stored in questions[].logic:

logic.conditionalNavigationV2 = { enabled: true, groups: [ // groups are OR-joined; FIRST matching group wins { id: "grp-1", conditions: [ // conditions inside a group are AND-joined { id: "cond-1", left: "{{quer_testar}}", operator: "equal_to", right: "Ainda não" } ], then: { type: "specific_screen", targetScreenId: "s-motivos" } } ] }

  • then.type: 'next_screen' | 'previous_screen' | 'specific_screen' (needs targetScreenId = another screen's id) | 'end_form'. Add then.url (+ optional openNewTab) to redirect to an external URL instead.

  • operator: 'equal_to' | 'not_equal_to' | 'greater_than' | 'greater_or_equal_than' | 'less_than' | 'less_or_equal_than' | 'contains'.

  • left/right are EXPRESSION strings: a literal ("10", "Ainda não"), a variable ("{{score}}", "{{minha_var}}" = the screen's variableName), or arithmetic ("calc({{peso}}/(({{altura}}/100)*({{altura}}/100)))").

  • Comparing an ANSWER: use left: "{{<variableName of the deciding screen>}}" and right = the option's label OR its value (both match).

  • {{score}} is the running sum of points on the options picked so far (choices[].points, images[].points) — that is how score-based branching works.

  • A navigation group with no conditions NEVER matches. enabled: false stores the rules but disables them.

  • Screen-level conditional display uses the same group shape: logic.display = { enabled: true, groups: [...], showAfterSeconds?: n } (then is ignored — THEN means "show").

  • Other logic keys: logic.autoAdvance = { enabled, delaySeconds? }, logic.navigationBehavior = { onButtonClick?, onAutoAdvance?, targetScreenId? }.

  • logic.conditionalNavigation (legacy, pre-DEVF-161) is still read and migrated on load — don't author new rules with it.

Unknown fields are REJECTED (they used to be stored and silently ignored): logic as an array, or rules/branching/conditions/goto/jump/nextScreen anywhere, are not read by any renderer.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
themeNoTheme key: amber|base|midnight|ocean|sunset|forest|lavender|minimal (default amber)
titleYesForm title
formatNoForm format: 'single_question' (default — one screen at a time), 'single_page' (all screens on one scrollable page, grouped by `sections`), or 'chatbot' (an Instagram/WhatsApp DM-style conversation; set `chatbot_skin` + `chatbot_profile`).
sectionsNosingle_page only: the page groups as `[{ id }]`, in order. The 'Section N' label is derived from position; sections have no editable title.
questionsNoScreen objects; omit for an empty form. Conditional logic goes in each screen's `logic` (see the tool description).
descriptionNoOptional description
chatbot_skinNochatbot only: chat chrome to imitate — 'instagram' (default) or 'whatsapp'.
chatbot_profileNochatbot only: the profile shown in the chat header.
thank_you_messageNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / theme / description
      Previous value: -"Theme key (default sunset/Ember)"New value: +"Theme key: amber|base|midnight|ocean|sunset|forest|lavender|minimal (default amber)"
  2. Changed4 schema fields changed
    • addedInput schema / properties / chatbot_profile
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "chatbot only: the profile shown in the chat header.",
      +  "properties": {
      +    "avatar_url": {
      +      "description": "Avatar image URL; falls back to the name's initials.",
      +      "type": "string"
      +    },
      +    "followers_text": {
      +      "description": "Free text under the name, e.g. followers/posts (Instagram only).",
      +      "type": "string"
      +    },
      +    "handle": {
      +      "description": "Instagram @handle (Instagram skin only).",
      +      "type": "string"
      +    },
      +    "name": {
      +      "description": "Display name in the chat header (both skins; default 'Sua Marca').",
      +      "type": "string"
      +    },
      +    "phone": {
      +      "description": "Shown phone number (WhatsApp skin only).",
      +      "type": "string"
      +    },
      +    "status": {
      +      "description": "Header status line (both skins; empty on WhatsApp shows the phone).",
      +      "type": "string"
      +    },
      +    "verified": {
      +      "description": "Blue verified badge (Instagram only; default true).",
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / chatbot_skin
      Added value: +{
      +  "description": "chatbot only: chat chrome to imitate — 'instagram' (default) or 'whatsapp'.",
      +  "enum": [
      +    "instagram",
      +    "whatsapp"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / format
      Added value: +{
      +  "description": "Form format: 'single_question' (default — one screen at a time), 'single_page' (all screens on one scrollable page, grouped by `sections`), or 'chatbot' (an Instagram/WhatsApp DM-style conversation; set `chatbot_skin` + `chatbot_profile`).",
      +  "enum": [
      +    "single_question",
      +    "single_page",
      +    "chatbot"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / sections
      Added value: +{
      +  "description": "single_page only: the page groups as `[{ id }]`, in order. The 'Section N' label is derived from position; sections have no editable title.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "id": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  3. First observed

TDQS

Score is being calculated.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources