FormHug
Create forms, surveys, quizzes
- Category
- Productivity
- Primary Subcategory
- Calendar & Scheduling Apps
Integration details
Description
Create forms for registrations, surveys, quizzes, assessments, and bookings inside ChatGPT. Describe what you need in natural language, and FormHug generates a complete form with fields, descriptions, logic, and layout. You can refine forms through conversation, customize themes, publish forms, collect submissions, and analyze responses — all in the same chat. FormHug helps turn everyday data collection into a simple conversational workflow.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Calendar & Scheduling Apps
- Secondary Subcategories
- None listed
- Brand
- FormHug
- Access
- Account required
- First tracked
- 2026-06-17
- Tool count
- 37
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Get alerts for FormHug
Get updates when FormHug’s Discoverability Score or category rank changes.
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 Category37 tools agents can invoke
If you have not read `formhug://guide` this session, read it first. Add one or more fields to an existing form. By default they are appended to the end in order; give a field a `before` / `after` anchor (an **existing** field's api_code) to insert it immediately before / after that field. All placements apply in a single update, so the saved result is atomically valid. Each field is an object with a snake_case `type` and a `label`. Use `type` from this exact list: - Basic: `short_text`, `long_text`, `radio`, `checkbox`, `image_radio`, `image_checkbox`, `dropdown`, `number`, `email`, `phone`, `date`, `name`, `url`, `address`, `rating`, `nps`, `attachment`, `audio`, `signature`, `ranking`, `time`, `location` - Advanced: `cascade`, `matrix`, `matrix_rating`, `likert`, `table`, `product`, `booking`, `linked_form`, `formula` - Display-only (collect no input): `page_break`, `description` Choice fields (`radio`, `checkbox`, `dropdown`) take `choices` as an **array of objects**, not strings — one per option, each `{label, ...}`. Example: ```json {"type": "radio", "label": "How did you hear about us?", "choices": [{"label": "Friend"}, {"label": "Other", "is_other": true}]} ``` `page_break` marks the START of a page, not a separator between them: use either none, or one at the very top of the form plus one before each later page (so at least 2, and the form's first field must be a page_break). Its `label`/`notes` render at the top of the page it opens. For choice free-text roles (`is_other` / `allow_extended_text`), advanced-field shapes, per-type keys, and `api_code` rules, see `formhug://guide` and `formhug://field-types`. To paginate a `classic` form, add every `page_break` in ONE call with `before`/`after` anchors: a break opens a page, so the result needs one anchored before the form's current first field plus one before each later page. Appending a single break is rejected. For Quiz/Assessment forms, new fields may include `answers` / `answer_explanation` (same shape as `create_form`); see the guide on following up about score-based feedbacks. This tool re-sends the form's existing fields with their api_codes so they are preserved. If this form uses conditional logic (fields that show/hide based on answers, or post-submission redirects), use `get_field_rules` / `update_field_rules` to keep the rules in sync — adding, removing, reordering, or rechoicing rule-referenced fields can invalidate trigger/target api_codes. See `formhug://field-rules`.
add_fields
Finalize prepared `rich_text_image` uploads into stored images, returning each image's public `image_url` (same order as `upload_ids`). Embed the URLs as `<img src="<image_url>">` in rich-text HTML — form `description`, field `notes`, `after_submission.show_message.rich_text`, or report feedback `comment`. Flow: 1. `prepare_image_upload` with purpose `rich_text_image` (one call per image). 2. `PUT` each file's bytes to its `upload_url`. 3. Call this tool with the `upload_ids` (1-20 per call). 4. Write the returned `image_url`s into the HTML you pass to create_form / update_form / update_fields / update_form_settings. All-or-nothing: if any entry is invalid the whole request fails (422 with per-entry `error_details`) and nothing is consumed. Already-processed entries are remembered, so retrying with the same `upload_ids` does not create duplicates.
commit_rich_text_images
Create a new folder. By default the folder is created at the top level (desktop). Pass parent_folder_token to nest it under another folder.
create_folder
If you have not read `formhug://guide` this session, read it first. Create a new form. Each field is an object with a snake_case `type` and a `label`. Use `type` from this exact list: - Basic: `short_text`, `long_text`, `radio`, `checkbox`, `image_radio`, `image_checkbox`, `dropdown`, `number`, `email`, `phone`, `date`, `name`, `url`, `address`, `rating`, `nps`, `attachment`, `audio`, `signature`, `ranking`, `time`, `location` - Advanced: `cascade`, `matrix`, `matrix_rating`, `likert`, `table`, `product`, `booking`, `linked_form`, `formula` - Display-only (collect no input): `page_break`, `description` Choice fields (`radio`, `checkbox`, `dropdown`) take `choices` as an **array of objects**, not strings — one per option, each `{label, ...}`. Example: ```json {"type": "radio", "label": "How did you hear about us?", "choices": [{"label": "Friend"}, {"label": "Other", "is_other": true}]} ``` `page_break` marks the START of a page, not a separator between them: use either none, or one at the very top of the form plus one before each later page (so at least 2, and the form's first field must be a page_break). Its `label`/`notes` render at the top of the page it opens. For choice free-text roles (`is_other` / `allow_extended_text`), advanced-field shapes, per-type keys, and `api_code` rules, see `formhug://guide` and `formhug://field-types`. `header_image` (required): pass 1–2 English search keywords (e.g. "soccer field", "office workspace") and the server picks a suitable image. `layout` (optional): `classic` (default — many questions per scrollable page) or `card` (one question per screen). Only use `card` when the user explicitly asks for a one-question-at-a-time / conversational flow. `scene` (optional): `"quiz"` (exam with correct answers), `"assessment"` (every choice scored), or omit for a regular form. The guide covers per-field scoring keys, score-based feedbacks, and the post-create walkthrough. If this form uses conditional logic (fields that show/hide based on answers, or post-submission redirects), use `get_field_rules` / `update_field_rules` to keep the rules in sync — adding, removing, reordering, or rechoicing rule-referenced fields can invalidate trigger/target api_codes. See `formhug://field-rules`.
create_form
Create a webhook integration on a form. The webhook delivers a JSON payload to `url` whenever any of the subscribed `trigger_events` fires. Use `get_webhook_sample_payload` to preview the payload shape. Requires the `integration:write` scope.
create_webhook
Delete a folder. Forms and sub-folders inside it are moved to the desktop (top level).
delete_folder
Permanently delete a form and all its entries. This cannot be undone.
delete_form
Permanently delete a webhook integration. This cannot be undone. Requires the `integration:write` scope.
delete_webhook
Get info about the currently authenticated user: email, display name, avatar, account creation date, total created forms / entries, and billing account details (organization name and current subscription plan code/name/period_end/cancel_at). Useful for confirming who is signed in or checking the current plan.
get_me
Get a single entry by its serial number.
get_entry
Get a form's conditional logic: field display rules (show / abort) and post-submission redirect rules. Read `formhug://field-rules` for the rule shape. Use this before update_field_rules to see what's currently set.
get_field_rules
Get form detail including all field definitions (labels, types, choices). Use this to discover field api_codes before submitting entries or to understand the form structure. `owned` / `role` indicate whether the current user created the form or accesses it as a collaborator (see list_forms).
get_form
Get a form's settings: locale, timezone, after-submission behavior (show_message / redirect / report), availability (manual close, schedule window, entries cap, countdown), access control (password), and submission options (progress bar, field numbering). Use this before update_form_settings to see what's currently set.
get_form_settings
Get the current visual theme of a form: header image(s), wallpaper (color, or a card-layout background image), primary color, submit button style, typography (form_header / field_label / choice_style), general button, and form_container styling. Use this before update_form_theme to see what's currently set. Read formhug://themes for design guidance.
get_form_theme
Get the public structure of any published form as JSON: its public fields (with api_codes, types, choices) and conditional field-display rules (`field_rules`). Use this to discover field api_codes before calling submit_entry on a form you don't own. `fields` lists every public field, including ones a rule may hide while filling (compute visibility from `field_rules`). Private fields are never returned — however `field_rules` may still reference a private field's api_code as a trigger or target, so a rule can point to an api_code absent from `fields`. Owner-only settings are also excluded — use `get_form` for forms you own. For password-protected forms, pass the password to unlock the structure.
get_published_form
Get an example payload that the webhook would deliver for the given trigger_event. Useful for testing the receiver side. The payload has `event_type` plus a `data` object containing the form token/name and an `entry` keyed by each field's api_code with example values, alongside meta fields (serial_number, created_at, info_*, etc.). Requires the `form:read` scope.
get_webhook_sample_payload
List entries (submissions) for a form. Use get_form first to see field api_codes. Results are paginated — pass the response's next_cursor back as cursor to fetch the next page. Optionally narrow results with `filter` (conditions ANDed together; read `formhug://entries-filter` for the format) and order them with `sort`.
list_entries
List all folders owned by the current user (not paginated). Returns `{records}` where each folder includes parent_folder_token (null for top-level), child_folder_count, child_form_count, created_at, and ancestors — a list of {token, name} from the root down to the immediate parent (empty for top-level folders). Use the folder token when creating or moving forms.
list_folders
List forms the current user can access — forms they created plus forms shared with them as a collaborator. Each item carries `owned` (whether the user is the creator) and `role` (the collaboration role on a shared form: manager / data_maintainer / data_viewer / custom; null when owned). Optionally filter by name or folder. Results are paginated; pass next_cursor from the response back as cursor to fetch the next page.
list_forms
List candidate entries for a `linked_form` field on a published form, so you can pick a value and obtain the `entry_token` to submit via submit_entry. Use get_published_form first to find the `linked_form` field's api_code (and its key fields under `associated_fields`). Search with `q` against a key field (`associated_field_api_code` selects which; defaults to the first); `q` is required for a privacy-protected linked_form field. Values are rendered as the published form shows them — the searched key field as plain text, other key/display fields masked where configured. Results are paginated by cursor, ordered by the candidate's serial number descending; `pagination.total` is an upper bound (an in-page recheck may drop rows).
list_linked_form_options
List the entries YOU have submitted to a published form (one you filled out but do not own). Use `get_published_form` first to see field api_codes. Results are paginated — pass the response's next_cursor back as cursor to fetch the next page. Optionally narrow results with `filter` (conditions ANDed together; read `formhug://entries-filter` for the format) and order them with `sort`. Only your own submissions are returned; private fields are never included and cannot be filtered or sorted on. For entries on forms you own, use `list_entries`.
list_my_entries
List forms the current user has submitted entries to but does not own, ordered by most-recent submission. Each item carries the user's own participation stats (`entries_count`, `last_entry_created_at`) plus a form summary. Results are paginated — pass the response's next_cursor back as cursor to fetch the next page. Use `list_my_entries` to read your own submissions on one of these forms.
list_participated_forms
List webhook integrations configured on a form. Returns `{records}`; each webhook entry includes its id, delivery url, subscribed trigger_events (entry_created/entry_updated/entry_paid), enabled flag, and timestamps. Requires the `integration:read` scope on the access token.
list_webhooks
If you have not read `formhug://guide` this session, read it first. Reorder a field within a form by placing it immediately before or after another field. Pass exactly one of `before` or `after` — the anchor field's `api_code`. The moved field's `api_code` cannot be the same as the anchor. For bulk reorders, call this tool once per move. Use `get_form` or `preview_form` to discover api_codes and the current order.
move_field
Move a form into a folder for your own view (folder placement is per-user). Omit folder_token to move the form back to the desktop (root). Provide original_folder_token to authorize a cross-folder move when the form's current folder isn't one you manage. Use get_form to check the form's current folder.token, and list_folders to find available folder tokens. Returns the form's token and its new folder (null on the desktop). Any collaborator on the form may place it in a folder they manage, regardless of their role.
move_form_to_folder
Prepare a 2-step upload for an `attachment` field, returning a one-time `upload_id` and an `upload_url`. Use this so `submit_entry` can include file uploads (otherwise `attachment` fields must be skipped). This MCP cannot transfer file bytes — YOU (the client) upload the file directly: 1. Discover the form's field api_codes (`get_form` / `get_published_form`). 2. Call `prepare_entry_attachment_upload` with `form_token`, the attachment field's `field_api_code`, `file_name`, `content_type`, and `file_size` (bytes). For a file column inside a `table` / `matrix` field, also pass `dimension_api_code`. 3. `PUT` the raw file bytes to the returned `upload_url`, setting `Content-Type` to exactly the declared `content_type`. Use the URL exactly as returned. 4. Submit the `upload_id` under that field in `submit_entry`'s `field_values` — an array of upload_ids (a bare string is also accepted): - Plain attachment field: `{ "<field_api_code>": ["<upload_id>"] }` - Table column: `{ "<table_api_code>": [ { "<dimension_api_code>": ["<upload_id>"] } ] }` Call once per file; collect several upload_ids into the array for a multi-file field. The credential expires (see `expires_at`), so PUT and submit promptly. Constraints: `content_type` must satisfy the field's `media_type` config (never text/html, text/css, text/javascript, application/x-httpd-php); `file_size` ≤ the field's `max_size`.
prepare_entry_attachment_upload
Prepare a 2-step upload for a form-element image (theme, rich-text, or field-element images), returning a one-time `upload_id` and an `upload_url`. This MCP cannot transfer file bytes — YOU (the client) upload the file directly: 1. Call `prepare_image_upload` with the image's `purpose`, `file_name`, `content_type` (image/jpeg | image/png | image/webp | image/gif), and `file_size` (bytes, ≤ 5 MB). 2. `PUT` the raw file bytes to the returned `upload_url`, setting the `Content-Type` header to exactly the `content_type` you declared. Use the URL exactly as returned — e.g. `curl -X PUT --data-binary @cover.png -H "Content-Type: image/png" "<upload_url>"`. 3. Consume the `upload_id` per `purpose`: - `header_image` → `update_form_theme` `{ "header": { "images": [{ "upload_id": "<upload_id>" }] } }` (or skip uploads entirely by passing `header.image_keywords` — the server auto-picks an Unsplash photo). - `wallpaper_image` → `update_form_theme` `{ "wallpaper": { "image": { "upload_id": "<upload_id>" } } }` (only on `card`-layout forms). - `rich_text_image` → `commit_rich_text_images` to get a public `image_url` for rich-text HTML. - `choice_image` → `choices[].image.upload_id` on an `image_radio` / `image_checkbox` field (create_form / add_fields / update_fields). - `product_image` → `goods_items[].images[].upload_id` on a `product` field. - `booking_image` → `reservation_items[].images[].upload_id` on a `booking` field. The credential expires (see `expires_at`), so PUT and apply it promptly.
prepare_image_upload
Get a human-readable markdown preview of a form's structure. Shows the form title, description, shareable URL, and all fields with their types, requirements, and choices. Useful for quickly reviewing a form's layout.
preview_form
Read a FormHug reference document (`formhug://*`) by its URI and return its full text. This is a fallback for clients that cannot read MCP resources directly — if standard MCP resource reading is available, read the `formhug://*` resource that way instead of calling this tool.
read_reference
If you have not read `formhug://guide` this session, read it first. Remove a field from a form by its api_code. Use get_form or preview_form first to find the api_code of the field to remove. Removing a `page_break` also removes the page it opened: what remains must still be either 0 page_breaks or at least 2 with the form's first field being one, so drop the whole page's breaks together rather than one at a time.
remove_field
Submit a new entry. Works for both your own forms and any published form. This tool first tries the public-entry endpoint; if the form is not found that way (404/403), it falls back to the owner endpoint. Before submitting, discover field api_codes and types: - Your own forms: `get_form` (also exposes field attributes) - Any published form: `get_published_form` `field_values` is a JSON object keyed by each field's api_code. The value shape depends on the field's snake_case type. Plain text types (`short_text` / `long_text` / `email` / `url` / `name`) take a string and `number` takes a number. `name` is a single full-name string (e.g. `"Jane Doe"`) — do NOT pass `{first_name, last_name}` or a JSON string of it. The non-obvious shapes: - `phone`: object `{country_id, country_code?, number}` — e.g. `{"country_id": "US", "number": "6267807789"}` - `radio` / `dropdown`: object `{value, other_text?, extended_text?}` where `value` is the choice's api_code (dropdown does not support `extended_text`). A bare string is accepted as shorthand for `{value: <string>}`. Pass `null` to clear. - `checkbox`: array of `{value, other_text?, extended_text?}` (bare strings accepted as shorthand). Empty array clears the selection. - `image_radio` / `image_checkbox`: same as `radio` / `checkbox` but `{value}` only — no `other_text` / `extended_text`. - `rating`: integer 1..rating_max - `nps`: integer 0..10 - `date`: naive wall-clock string formatted per the field's `precision` (`"YYYY-MM"`, `"YYYY-MM-DD"`, `"YYYY-MM-DD HH:mm"`, `"YYYY-MM-DD HH:mm:ss"`); interpreted in the form's `timezone` (defaults to the account's timezone, falling back to UTC) - `address`: `{address_line1, address_line2, city, state, postal_code, country}` - `time`: `{hour, minute, second?}` (string values) - `location`: `{longitude, latitude, address}` - `attachment`: array of `upload_id` strings from `prepare_entry_attachment_upload` (prepare it, then PUT the file to the returned upload_url). A bare string is accepted; omit / empty array when no file. For nested/complex types (`cascade`, `matrix`, `matrix_rating`, `likert`, `ranking`, `table`, `product`, `booking`, `linked_form`) and a full reference, read the resource `formhug://entry-values`. `signature` (drawn in the browser) and `audio` (recorded in the browser) are read-only and cannot be submitted via this MCP — skip them and inform the user. Unknown api_codes are dropped silently by the server. Private fields (`private: true`): on the public-entry endpoint their keys are ignored and the server fills each private field's `predefined_value`, if any; only the owner fallback accepts submitted private-field values. Published forms also enforce their fill-frequency limits (per user, per IP, or per submitted field value; a per-device limit cannot identify API clients and does not restrict them), and the request IP and user agent are recorded as the entry's submission metadata.
submit_entry
Update one or more existing fields on a form, identified by `api_code`. Call `get_form` first to discover the current `api_code`, `type`, and existing nested shapes (choices, statements, dimensions). Each update entry contains the field's existing `api_code` plus any keys you want to change (label, required, placeholder, choices, statements, dimensions, …). A field's `type` is fixed at creation and stays as-is. Merge semantics: keys you supply replace the matching keys on the existing field; keys you omit are preserved. Merging is **shallow** — passing `choices` replaces the entire choices array, so include every choice you want to keep. For each choice: - Keep it unchanged: include the choice with its existing `api_code`. - Update it: include the existing `api_code` plus the keys to change. - Add it: include the choice with `api_code` omitted (server assigns one). - Delete it: leave it out of the array. `choices` is always an array of objects shaped `{label, api_code?, is_other?, allow_extended_text?, extended_text_required?, extended_text_placeholder?, selected?}` (`dropdown` ignores the `*extended_text*` keys). Example replacing the choices on a `radio` field: ```json {"api_code": "field_2", "choices": [ {"api_code": "choice_abc", "label": "Female"}, {"api_code": "choice_def", "label": "Male"}, {"label": "Prefer not to say"} ]} ``` The same shallow-replace rule with the same add/update/delete semantics applies to `statements`, `dimensions`, `sub_choices`, `goods_items`, and `reservation_items`. Fields not mentioned in `updates` are left untouched. To add new fields use `add_fields`; to delete a field use `remove_field`. For Quiz/Assessment forms: if your update changed any scorable field's `answers`/`score` values or its choice set, ASK THE USER whether the form's **score-based feedbacks** (post-submission score-range comments configured via `update_form_settings` → `after_submission.report.score_based_feedbacks`) need to be updated, since the total possible score or the meaningful thresholds may have shifted.
update_fields
Rename a folder. Only the folder name can be changed; folders cannot be moved into other folders via this tool.
update_folder
If you have not read `formhug://guide` this session, read it first. Update a form's name, description, locale, timezone, or layout. To move the form between folders, use move_form_to_folder instead. Theme changes are not done here — use update_form_theme.
update_form
Update a form's settings (locale, timezone, after-submission behavior, availability, access control, submission options) using partial-merge semantics. Top-level groups (and individual fields within each group) you omit are left unchanged; explicit `null` clears the corresponding feature. After-submission `mode` selects which branch is authoritative: - `show_message` (default for regular forms): set `after_submission.show_message`. Pick `style: "rich_text"` and supply HTML in `rich_text`, OR `style: "text"` and supply `text.title` / `text.description`. - `redirect`: set `after_submission.redirect.url`. Optionally append field values via `redirect.fields` (array of field api_codes). - `report`: quiz/assessment forms only. Set `after_submission.report.score_based_feedbacks` to a non-empty array of `{ start_point, end_point, comment }` ranges. Each entry defines a score interval (inclusive on both ends) and the HTML `comment` shown to the respondent after submission when their total falls in that interval — use this to give tiered feedback (e.g. low score → "review these topics", high score → "great work"). Ranges should cover the full 0..max-possible-score span without gaps; `comment` accepts HTML. Availability: - `manually_closed: true` closes the form regardless of schedule. - `schedule: { start_at, end_at }` (ISO 8601 date-times) defines an availability window. Pass `schedule: null` to clear. - `entries_limit` caps total submissions (positive integer, or null to remove the cap). - `show_countdown` / `show_form_before_open` toggle respondent-facing hints around the schedule. Access control: `access_password` gates the form behind a shared password (null to remove). Submission options: `show_progress` (progress bar) and `show_field_number` (numbered fields) are independent toggles.
update_form_settings
If you have not read `formhug://guide` this session, read it first. Update a form's visual theme using partial-merge semantics — keys you include are written, keys you omit are left unchanged, explicit `null` clears a value. Read `formhug://themes` first for design guidance, the full key catalog (fonts, weights, border widths, layout constraints), how to set the header / wallpaper image, palette auto-derivation, and the `primary_color` alias and layout-specific constraints.
update_form_theme
Update a webhook integration's url, subscribed trigger_events, or enabled flag. Only the fields you pass are changed; omit a field to leave it untouched. Use `list_webhooks` to find the webhook id. Requires the `integration:write` scope.
update_webhook
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 FormHug alternatives on ChatGPT?
As of 2026-09-28, FormHug competes with CalcForms, Clipform, Cognito MCP, CrowdHum, Dayalogs, Fillo, Formbyte, FormEdge, Formester, Formfacade, Formly, Forms AI, Formspry, FoxForm, Fyrebox, html.contact - Contact Forms, Jotform, Letsfind, Neartail, PlatoForms, SurveyMonkey, SurveySparrow: Forms & Surveys, Tally, Typeform, Walla 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.