Integration details
Description
Build and manage Walla forms from ChatGPT: create a form, add and edit questions (including conditional jump logic, appearance, and page sections), publish it for respondents, and read submitted responses with PII automatically masked. Users can also connect webhook automations that deliver responses to their own endpoint, and Enterprise teams can build reusable custom field types from a natural-language description. Six built-in reference documents describe the form model and editing payloads so the assistant can author correct edits on the first try.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Form & Survey Builders
- Secondary Subcategories
- None listed
- Brand
- Walla
- Access
- Account required
- First tracked
- 2026-08-21
- Tool count
- 20
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competing in ChatGPT Form & Survey Builders
View Category20 tools agents can invoke
Register a ready_to_review build as a reusable custom field TYPE + immutable VERSION, after the member has reviewed the preview. This deploys and verifies the field, so it may take a minute; if it returns try_again or internal, call get_custom_field_build then approve again — it resumes safely without creating a duplicate. Returns customFieldTypeId + customFieldVersionId; then attach it with form_apply_edits (add_field, fieldType CUSTOM, that customFieldTypeId). Idempotent: re-approving returns the same version. Preconditions: state ready_to_review. This is where the per-plan cap on how many custom field types a team may OWN is finally enforced (Free 1, Pro 5, Enterprise unlimited): approving a build that would register a NEW type past the cap returns payment_required — the build stays approvable, so relay the upgrade nudge rather than starting over. A build with a targetTypeId only adds a version to an existing type and is never capped.
approve_custom_field_build
Cancel a custom field build you no longer intend to approve, freeing the in-flight build slot it holds. A team can have only a few builds in flight at once; an abandoned build keeps its slot until it is cancelled (or expires after ~24h), so start_custom_field_build fails with "too many in-flight builds" until one is freed. Use this to discard a build you started but will not finish, or to unblock start when all slots are taken. Do NOT use it to change a built field: to fix the code and rebuild, call submit_custom_field again; to keep the field, call approve_custom_field_build. An already-approved build CANNOT be cancelled — its registered field version stays live. Preconditions: a teamId from list_teams and a buildId from start_custom_field_build / get_custom_field_build. Cancelling an already-finished build (failed/expired) succeeds as a no-op. Cancelling does NOT free room under the per-plan limit on how many custom field types a team may own — that limit counts registered types, not builds; only deleting a type does. Side effect: marks the build terminal and tears down any deployed preview for it; this is not reversible — start a new build to try again. Returns { buildId, state } with state build_failed.
cancel_custom_field_build
Poll a custom field build. Returns a single member-facing state: preparing → awaiting_your_code → building → ready_to_review → approved (or build_failed). When awaiting_your_code, call get_custom_field_scaffold then submit_custom_field. When build_failed, read errors and re-submit. When ready_to_review, share previewUrl with the member — it is a ready-to-open link that renders the field for review (do not paste the raw build URL, which shows blank outside the host page) — then approve_custom_field_build. Preconditions: a buildId from start_custom_field_build.
get_custom_field_build
Create an automation that runs an action when the form receives a response. v1 supports one action type: a webhook (action.type:'webhook') that sends an HTTP request to an endpoint. By default the webhook sends the full response data as a JSON payload; optionally supply action.config.body to send a custom body with @[label]{{ID}} mentions that inject response values (field ids from get_published_form as res:<fieldId> or bare <fieldId>, hidden fields as hidden:<key>, or special variables responseKey/customerKey/projectKey/timestamp). The default payload also carries the response's hidden-field values (what the form captured from URL query parameters) — set action.config.includeHiddenFields:false to leave them out. Optionally attach conditions so it fires only when a response matches (e.g. a rating equals 5). Call it ONLY when the user explicitly asks to send responses to a webhook/their server — never as a side effect of reading. Do NOT use it for email or Google Sheets automations: those are not offered here (they require connecting a Google account in the dashboard first — tell the user to set them up there), so action.type accepts only 'webhook'. Do NOT use it to edit/delete/enable an existing automation (use update_automation, or the dashboard), nor to route different responses to different actions (multiple routes — dashboard). To edit the form's questions use form_apply_edits. Preconditions: a published formId from list_forms (a Live/Closed form — automations attach to the published form); the user must be a member of the form's workspace or the call returns forbidden. To add conditions or body mentions, first read the form (get_form / get_published_form) to get real field ids and, for choice fields, option ids — an unknown field id (in a condition or a body mention) returns invalid_args; the operator/condition shape matches walla://reference/branch-logic (readable via the read_reference tool if your client can't open resources). Consider list_automations first to avoid duplicates. Side effect: creates ONE automation (additive). It is created INACTIVE (isActive:false) — the user must enable it (in the dashboard or via update_automation) before it will actually fire, so tell them so. Returns the created automation summary (id, name, type, trigger, isActive:false, and the conditions you set). `actionTypes` is the ordered, de-duplicated list of action-node types; `actionSummary` is optional sanitized metadata emitted only for exactly one action node and omitted for multi-action graphs.
create_automation
Create a new TITLE-ONLY form shell in a workspace. It is a data-changing (write) tool; call it ONLY when the user explicitly asks to create a form, never as a side effect of reading. Use it to start a brand-new empty form. Do NOT use it to add questions/fields or to edit an existing form — it creates only an empty titled shell (a default submit step is added automatically); to add or change a form's questions, set descriptions, edit branch logic, or add a CUSTOM field, use form_apply_edits instead. To inspect what was created, re-read with get_form or list_forms. Preconditions: teamId and workspaceId, both taken from list_teams / list_workspaces, plus a title (1–255 characters); the user must have create permission in that workspace or the call returns forbidden, and bad/missing input returns invalid_args. Side effect: creates one new form (additive, not destructive) attributed to the calling user. Returns the newly created form record (the empty titled shell).
create_form
Apply a batch of edits to an EXISTING form's draft: add, update, delete, or reorder fields, set rich-text field descriptions (HTML), set or clear a field's conditional jump logic (set_field_logic / clear_field_logic), set the form's appearance (background/button colors + next-button, set_form_appearance), and set a question group's page-break boundary and label (set_group). Edits go through the live collaborative document, so changes appear to anyone currently editing and are saved to the draft (the user publishes separately). Read the form first with get_form to obtain real field ids and the current layout; never invent field ids. To add a field and set its conditional logic in ONE call, give the add_field a tempId (and each choice option a key) and reference them as @tempId / @key in the same batch's set_field_logic — the server resolves them to the assigned ids and echoes the mapping under the result's `added`, so no re-read is needed. For set_field_logic, pass option ids as choiceIds (the opaque option ids read from get_form, not labels or values) to match a choice answer, and a literal value for text/number/date answers; a rule's conditions use a per-condition connector ('and'/'or') that folds left-to-right with no precedence; see walla://reference/branch-logic and walla://reference/editing-contract for the full contract (readable via the read_reference tool if your client can't open resources). When building a multi-question survey, consider grouping related questions into labeled sections instead of leaving each in its own flat group: anchor follow-up fields to the section's first field with intoGroup:true, then set_group{groupId,label} to name each section (see the server instructions and walla://reference/editing-contract). Preconditions: a formId from list_forms and at least one op; the user must have edit permission on the form's team/workspace or the call returns forbidden, and bad input returns invalid_args. Side effect: mutates the form's questions (add is additive; delete/reorder can remove or reshuffle fields). Call ONLY when the user explicitly asks to change a form's questions, never as a side effect of a read. Returns { formId, applied, added } where applied is the number of operations applied and added has one entry per add_field op echoing the server-minted field/option ids (the receipt for any tempId/key alias).
form_apply_edits
Get a single form's editable DRAFT: the form record, a lean per-field projection in layout order, and the page/group view. Use when you need the working/editable version of a form — its questions, settings, and page structure — and to get real field ids and the current layout before editing with form_apply_edits. Do NOT use it for the live published version — use get_published_form instead; and do NOT guess a form id — take one from list_forms. Preconditions: formId, taken from a list_forms result; the user must have read permission on the form's team/workspace or the call returns forbidden, and an unknown id returns not_found. Read-only; no data is changed. Returns { form, fields, groups }: the draft form record; one lean object per field (id, label, fieldType, properties, validations, plus outputType and friendly logic when the field has any — CUSTOM fields also carry customFieldTypeId, customFieldVersionId, and outputSchema) in layout order; and the derived groups view (page sections with their chaining/label and fieldIds). fields is empty when the draft has no ordered fields.
get_form
Get a form's LIVE published version plus its form settings and a lightweight field list (each field's id, label, type, output type, and published option IDs). Use when you need the published/live form as respondents see it, or when you need fields' output types. Do NOT use it for the editable draft or full field rows — use get_form instead; a form that has no published version returns not_found (it does NOT return empty fields), so use get_form to read a draft that was never published. Preconditions: formId, taken from a list_forms result; the user must have read permission on the form's team/workspace or the call returns forbidden, and an unknown id returns not_found. Read-only; no data is changed. Returns { form, fields }: the published form with its settings, plus the lightweight field list.
get_published_form
Fetch the editable scaffold for a build started with start_custom_field_build: the SDK types, an example, the contract notes, and the current file tree. While the scaffold is still being prepared this returns { notReady: true, retryAfterMs } — wait that long and call again. Once ready, WRITE the field's code and send it with submit_custom_field. The contract notes define the root-level declaration files that drive registration (outputSchema.json, propertiesSchema.json, defaultProperties.json, observeFields.json) — read them before writing code. Preconditions: a buildId from start_custom_field_build.
get_custom_field_scaffold
List the automations wired to a published form as sanitized summaries: each automation's id, name, type, trigger, whether it is active, `actionTypes` (unique action-node types in first-seen order; legacy settings-based Google Sheets, Zapier, and basic-webhook rows derive this from `automationType`), optional `actionSummary` metadata only when exactly one valid action node exists (for a webhook: method + endpointHost — the URL's host only — whether it uses a custom body (bodyMode + hasCustomBody), and includeHiddenFields, the effective answer to whether the builder-generated payload (default/auto) carries the response's hidden-field values — omitted when a custom body decides the payload, because the flag does not shape it; never the body contents, URL, headers, or secrets), and a friendly summary of any router conditions. `actionSummary` is omitted for zero or multiple action-node graphs so multi-action automations are never presented as a single action. Use to survey what a form already does on submission, to get an id for update_automation, or to check for duplicates before creating a new one with create_automation. Do NOT use it to read the form's questions (use get_form / get_published_form), to read submitted responses (use list_responses), or to read automation RUN history/logs (not available here). Preconditions: a formId from list_forms (a Live/Closed form — automations attach to the published form; a never-published draft has none); the user must be a member of the form's workspace or the call returns forbidden. Read-only; nothing is changed. Returns { result }: an array of automation summaries. `conditions` is the router condition decompiled to the same friendly shape create_automation / update_automation accept (an empty array means it fires on every response); it is null with a `conditionsNote` when the automation's graph is too complex to summarize (multiple routes, an unsupported operand, or a hand-built custom graph) — open those in the dashboard.
list_automations
List a form's submitted responses (answers), one page at a time, with PII automatically masked. Use after get_form / get_published_form when the user wants to read what respondents actually answered — to summarize, filter, or quote submissions. Do NOT use it to read the form's QUESTIONS or structure (use get_form / get_published_form) or to export files (that is a separate download grant). Preconditions: a formId from list_forms; the caller's token must hold the project:response.read scope (a read-only token that only has project:read will not see this tool), and the user must have response-read permission on the form's team/workspace or the call returns forbidden. Read-only; nothing is changed. Values are returned MASKED (emails/phones/names redacted per the form's masking settings) — this tool cannot return unmasked PII. File-upload answers are omitted (returned as a `[file]` placeholder, never the file URL) — downloading files is a separate grant done from the dashboard. Rows are ordered newest submission first (by submitted_at descending, ties broken by responseId ascending) — a deterministic order, but not a stable snapshot: because ordering is newest-first, a submission that arrives between two page reads shifts rows across page boundaries, so offset paging can return a row twice or skip one. Re-read from offset 0 if you need a consistent snapshot. Responses are paginated: pass offset/limit and page with repeated calls (keep going while hasMore is true). Returns { formId, rows, fields, offset, limit, returned, totalCount, hasMore }: `rows` is an array of response objects containing only the fixed responseId, customerKey, and submittedAt keys plus currently published response-sheet columns; submittedAt is an ISO 8601 string or null. `fields` is the label map for those published column keys — [{ id, label, outputType }] where each id matches a row key exactly (join on it to show human labels; empty [] if the form has never been published); `totalCount` is the exact number of responses across all pages; and `hasMore` is true when more pages remain (offset + returned < totalCount). If the team has disabled external AI, the call returns forbidden (the team opted its response data out of AI tools).
list_responses
List the custom (extension) field types this team already has, so you can REUSE one instead of asking for a new build. Returns each type's customFieldTypeId, name, description, its latest version id, and that version's outputSchema (the shape of the value the field saves). Use this before adding a custom field: if a suitable type exists, attach it with form_apply_edits (add_field, fieldType CUSTOM) using its customFieldTypeId. This is also the only way to learn valid customFieldTypeIds — never invent one. Preconditions: a teamId from list_teams. Every plan can use custom fields; what the plan limits is HOW MANY types a team may own (Free 1, Pro 5, Enterprise unlimited), and that limit applies only when creating a new one — listing, attaching, and using existing types are never blocked by it. The list is team-scoped — only this team's own types, not shared/platform ones. Read-only; nothing is changed. Returns an array of custom field type summaries (empty if the team has none).
list_custom_field_types
List the forms in one workspace as lightweight summary cards (id, title, status, response count, tags, and limit/schedule fields). Use after list_workspaces to find a form id, or to survey a workspace's forms and their status. Do NOT use it to read a single form's full content or its questions — for that take a form id from here and call get_form (draft) or get_published_form (published). Preconditions: teamId and workspaceId, both taken from list_teams / list_workspaces; the user must be a member of that workspace or the call returns forbidden. Read-only; no data is changed. Returns an array of form cards (summaries, not full forms), each carrying a computed status of Draft, Live, or Closed.
list_forms
List the teams the authenticated user belongs to. Use this FIRST, as the entry point of the discovery chain — it takes no input and returns the team ids every other tool needs. Do NOT use it to list workspaces or forms; once you have a team id, call list_workspaces(teamId). Preconditions: none (the user identity comes from the access token). Read-only; no data is changed. Returns an array of teams, each with id, name, and profileUrl.
list_teams
List the workspaces the authenticated user can access within one team. Use after list_teams, when you have a team id and need its workspaces before reaching forms. Do NOT use it to list forms — once you have a workspace id, call list_forms(teamId, workspaceId). Preconditions: teamId, taken from a list_teams result (not fabricated); the user must be a member of that team or the call returns forbidden. Read-only; no data is changed. Returns an array of the workspace records the user can access in the team.
list_workspaces
Publish a form's current draft as the LIVE version respondents can open. Use this only when the user explicitly asks to publish (or re-publish) a form, after its questions are ready — never as a side effect of reading or editing. Publishing does NOT edit the draft; it snapshots the current draft into the live published version, so edit first with form_apply_edits (which saves to the draft), then publish. Do NOT use it to change questions (use form_apply_edits) or to read the result (use get_published_form). Preconditions: teamId, workspaceId, and formId, all taken from list_teams / list_workspaces / list_forms; the user must have edit permission on the form or the call returns forbidden. Re-publishing an already-published form updates the live version in place (idempotent — the same draft re-published makes no further change). Side effect: makes the form's current draft publicly live to respondents. If the draft contains paid field types the team's plan does not include, the call returns payment_required (relay the upgrade nudge; the form stays unpublished until the plan covers it or those fields are removed). Returns the published form record (its published_form_id).
publish_form
Read one long-form Walla reference document by name and get its full markdown body back. Use this as a FALLBACK when your client cannot consume MCP resources (i.e. you cannot open `walla://reference/...` URIs): it delivers the exact same reference bodies through a plain tool call, which every client can make. The docs describe the form model and the exact editing payloads — read the relevant one before building or editing a form (field-types, editing-contract, and branch-logic are the authoritative schemas). When NOT to use: if your client CAN read MCP resources, prefer resources/read on `walla://reference/<name>` instead (same content); and do NOT use this to read a user's teams, workspaces, forms, or responses — those are the list_*/get_* tools. Preconditions: none (no id needed; takes only a fixed document name). Read-only; changes nothing and touches no user data. Returns the selected document as markdown text. Names: form-model, field-types, branch-logic, field-descriptions, custom-fields, editing-contract.
read_reference
Begin building a NEW custom (extension) field for this team from a natural-language description (e.g. a signature pad, a catalog picker). Building is ASYNC and takes a few minutes — this returns a buildId immediately with status 'building'; poll get_custom_field_build with that id until status is 'preview_ready', then share the preview with the member. Propose a short `name` for the reusable field type and have the member confirm it. To revise an existing field type instead, pass its customFieldTypeId as targetTypeId (a new version is minted on approve). Preconditions: a teamId from list_teams; too many in-flight builds returns invalid_args. Every plan can use custom fields, but each plan caps how many types a team may own (Free 1, Pro 5, Enterprise unlimited): starting a build for a NEW type when the team is already at its cap returns payment_required — relay the upgrade nudge, and offer to revise an existing type instead. Revising via targetTypeId does NOT count against the limit (it adds a version to a type the team already owns), so it works even for a team at or over its cap. The limit is re-checked at approve, so it can also surface there. Does NOT attach anything to a form — approve first, then add a CUSTOM field with form_apply_edits.
start_custom_field_build
Send the field's source files for a build (a MERGE patch over the scaffold — omitted paths are left unchanged). Root-level files double as REGISTRATION declarations: outputSchema.json (required) plus optional propertiesSchema.json / defaultProperties.json / observeFields.json. A field that must read OTHER fields' answers (carry-forward, cross-field filtering) MUST include observeFields.json with {"mode":"configured"} — omitted, the version registers as mode "none" and the live field receives NO form context (it renders its empty state even when the observed answers exist). Which specific fields it observes is then set per placement after attach — via form_apply_edits (properties._observedFields, host-validated refs) or the dashboard field settings; the dashboard shows a field-picker UI only if propertiesSchema.json ALSO declares an _observedFields node with the tagged-ref array shape (see walla://reference/custom-fields, readable via the read_reference tool if your client can't open resources). The build then compiles and previews ASYNC; poll get_custom_field_build for state. If it returns try_again the build is busy applying your last change — wait briefly and retry the SAME call. On a build_failed state, read the returned errors, fix the files, and submit again. Preconditions: a buildId whose state is awaiting_your_code.
submit_custom_field
Change an existing automation's name, conditions, or webhook settings (endpoint, method, custom body), or turn it on/off (isActive). Only the fields you pass change; the rest are kept. Call it ONLY when the user explicitly asks to modify / rename / re-target / enable / disable an existing automation — first run list_automations to get its id and current state. Do NOT use it to create a new automation (use create_automation), to delete one (dashboard; no MCP tool yet), or to edit the form's questions (form_apply_edits). It can only edit a simple single-route webhook automation (the kind create_automation makes); a dashboard-built complex automation (multiple routes, an email/Sheets action, or a hand-built custom graph) returns invalid_args — edit those in the dashboard. Preconditions: an automationId from list_automations; to change conditions, the endpoint, or a body with mentions, read the form (get_form / get_published_form) for real field/option ids — the operator/condition shape matches walla://reference/branch-logic (readable via the read_reference tool if your client can't open resources). To set a custom webhook body use action.config.body with @[label]{{ID}} mentions (same syntax as create_automation); send action.config.body:"" (empty) to remove the custom body and revert to the default full-response payload. Side effect: updates ONE automation. Turning it ON (isActive:true) means responses START being sent to the endpoint from that moment — always tell the user this; isActive:false stops firing. Other edits do not change whether it is active. Returns the updated automation summary. `actionTypes` is the ordered, de-duplicated list of action-node types; `actionSummary` is optional sanitized metadata emitted only for exactly one action node and omitted for multi-action graphs.
update_automation
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Walla alternatives on ChatGPT?
As of 2026-09-13, Walla competes with CalcForms, Clipform, Cognito MCP, CrowdHum, Dayalogs, Formbyte, FormEdge, Formester, Formfacade, FormHug, Forms AI, Formspry, Fyrebox, Jotform, Letsfind, Neartail, PlatoForms, SurveyMonkey, SurveySparrow: Forms & Surveys, Tally, Typeform in ChatGPT Form & Survey Builders, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.