Forms API reference
Manage form content, provider settings, fields, and draft lifecycle through the public REST API.
Use forms to collect contact details in flows. These endpoints save form configuration. They don't submit a contact or send data to an email platform.
Authentication and form operations
Paths below follow https://api.rightmessage.com/v1/{teamPid}. GET requires read or write; mutations require write. The * ability satisfies both. The shared request conventions cover bearer authentication, headers, project access, and rate limits.
| Method and path | Request | Success |
|---|---|---|
GET /forms | No filters or pagination parameters | 200, {"data":[RESOURCE]} |
GET /forms/{form} | Resource ID from the list | 200, {"data":RESOURCE} |
POST /forms | Create body below | 201, {"data":RESOURCE} |
PUT or PATCH /forms/{form} | Partial body below | 200, {"data":RESOURCE} |
DELETE /forms/{form} | No body | 204, empty body |
PUT and PATCH have the same partial-update behavior. An omitted top-level field retains its value. A collection with no resources returns {"data":[]}. Reads return the draft when one exists, otherwise the stable configuration.
Errors and draft effects
The shared error contract applies. Invalid request fields return 422 with message and field-keyed errors. Full-configuration validation can return 500 instead.
Mutations save a draft, not live changes. Publishing applies the whole project draft, including edits made elsewhere. The draft contract covers snapshots, dashboard updates, and save failures.
Form request fields
Only name is required on create. All fields are optional on update.
| Field | Type and validation | Create default |
|---|---|---|
name | Nonempty string, maximum 255 | Required |
is_enabled | Boolean | true |
parts | Object | Defaults below |
parts.title | String, maximum 500 | Untitled Form |
parts.description | Nullable string | null |
parts.button_text | Nullable string, maximum 255 | Submit |
action | Object | Form action |
action.settings | Object | Default fields and visible labels |
action.settings.platform | Provider-name string | Unset |
action.settings.event_name | Nonblank string, trimmed and stored as one event name | Unset |
action.settings.form_ids | Array. The request has no item-level rule; repair normalizes form-action IDs into strings. | [] after repair |
action.settings.fields | Array of field objects | Email and submit fields |
action.settings.fields[].display_type | Required string for each supplied field | No default on supplied fields |
action.settings.fields[].label | String, maximum 255 | Supplied placeholder, or empty string, after repair |
action.settings.fields[].width | Integer, 1 through 6 | 6 after repair |
The default email field has label: "Email address", placeholder: "Your email address", displayType: "email", width: 6, and options: {}. The default submit field starts with displayType: "submit", width: 6, and options: {}; configuration repair also fills its placeholder and label with empty strings.
Nested objects are not closed allowlists. The service also recognizes parts.image_url; action.type; and settings url, thanks_message, tag_ids, list_id, automation_id, show_labels, redirect_url, and redirectFunnel. Those keys lack dedicated rules in the forms HTTP validator. Their stored representation still undergoes configuration validation. Use the offers settings contract for their mapping. show_labels maps to formSettings.showLabels; redirectFunnel takes precedence over redirect_url.
The shared mapper currently stores singular list and automation identifiers, while visitor actions expect plural keys. As explained in the offers reference, saving list_id or automation_id alone does not establish a working provider action.
Field objects preserve additional keys. Write-side display_type, question_id, and question_display become displayType, segmentGroupId, and questionDisplay. This CRUD path does not validate referenced question fields separately.
Nested parts, action, and action.settings merge by supplied key. A supplied fields array replaces the list before configuration repair. Repair then adds an email field and a submit field if either is missing, so fields: [] restores those 2 fields rather than producing an empty form. It fills omitted field widths with 6, caps widths at 6, supplies empty options and placeholders, and defaults an omitted label to its placeholder.
For form actions, repair trims and splits form_ids strings at commas and newlines, removes empty entries, and also converts integer entries to strings. Omitted IDs become []. A non-link action gets a redirect flow when one is absent; an empty redirect flow gains a message node using thanks_message, or Thank you! when that value is empty. Changing thanks_message later does not replace an existing nonempty redirect flow.
Form responses and classification limits
The response contains id, name, is_enabled, parts, and action. parts contains title, description, button_text, and image_url. action.type is always serialized as form. Its settings contains platform, form_ids, thanks_message, fields, and show_labels. Field objects use stored camelCase keys, not the write-side snake_case aliases. Settings not named here are not echoed.
The forms list includes every non-link action, including tag, event, list, automation, and contact actions. Item GET, update, and delete accept only the exact stored action type form. A listed non-form action can therefore return 404 at its forms item URL. This is a production inconsistency, not a missing permission. Its offer item URL can still be usable.
Deleting a form clears matching offerId references in flow nodes. It does not delete the flow nodes or previously collected contacts.
Illustrative requests and responses
These illustrative examples use the fictional WorkForge project. The same resource schema covers every CRUD response.
The PATCH example also works with PUT. The create, item-read, and update envelopes have this shape. The list places these resource objects in its data array. An update returns the updated values. DELETE returns no JSON.