Forms API
Create, read, update and delete forms, including their fields, settings and theme. A form created through the API is identical to one built in the form builder: it appears in your dashboard, can be edited visually, and is published at its hosted URL or embedded on any site.
All endpoints require a bearer token and operate on the token's workspace.
The form object
{
"id": 42,
"name": "Contact us",
"internal_name": "Website contact form",
"slug": "website-contact-form-k3j9xa",
"status": "published",
"url": "https://rapidform.co/f/website-contact-form-k3j9xa",
"embed": {
"script_url": "https://rapidform.co/embed.js",
"snippet": "<div data-rapidform=\"website-contact-form-k3j9xa\"></div><script src=\"https://rapidform.co/embed.js\" async></script>"
},
"settings": {
"description": "We reply within one business day.",
"submit_button_text": "Send message",
"thank_you_message": "Thanks! We'll be in touch.",
"heading_alignment": "left",
"display_mode": "standard",
"show_branding": false
},
"theme": {
"background": "#ffffff",
"text": "#18181b",
"button": "#2547e0",
"accent": "#2547e0",
"font": "Inter",
"border_radius": "rounded",
"mode": "light"
},
"fields": [ "…see the field object below…" ],
"submissions_count": 128,
"created_at": "2026-09-01T10:15:00+00:00",
"updated_at": "2026-09-04T08:02:11+00:00"
}
| Field | Type | Description |
|---|---|---|
id |
integer | Unique form ID. Use it in every other form endpoint. |
name |
string | Public title shown to respondents at the top of the form. |
internal_name |
string | Name shown in your dashboard only. Defaults to name. |
slug |
string | URL-safe identifier used in the hosted URL and embed codes. Generated on create and never changes. |
status |
string | draft or published. Only published forms accept submissions. |
url |
string | The hosted form page respondents can open directly. |
embed.script_url |
string | The embed script to load on your site. |
embed.snippet |
string | Ready-to-paste HTML that renders the form inline. See Embedding Forms for modal and other modes. |
settings |
object | Behaviour and copy — see Settings. |
theme |
object | Colours and typography — see Theme. |
fields |
array | Ordered field objects. Present on GET /forms/{form}, POST /forms and PATCH /forms/{form}; omitted from the list endpoint. |
submissions_count |
integer | Total submissions received. |
created_at / updated_at |
ISO 8601 datetime | Timestamps in UTC. |
Settings
All keys are optional. Omitted keys keep their current value (or the default on create).
| Key | Type | Default | Description |
|---|---|---|---|
description |
string, max 2000 | — | Text shown under the form title. |
submit_button_text |
string, max 100 | Submit |
Label of the submit button. |
thank_you_message |
string, max 2000 | Thank you for your submission! |
Shown after a successful submission. Also returned to the embed script. |
heading_alignment |
left | center |
left |
Alignment of the title and description. |
display_mode |
standard | one_per_step |
standard |
standard shows all fields on one page; one_per_step shows one field at a time, typeform-style. |
show_branding |
boolean | false |
Whether the "Powered by RapidForm" badge is shown. |
custom_css |
string, max 20000 | — | Extra CSS applied to the hosted and embedded form. Business plan only; silently ignored on other plans. |
Theme
All keys are optional. Colours must be hex (#rgb or #rrggbb).
| Key | Type | Default | Description |
|---|---|---|---|
background |
hex colour | #ffffff |
Form background. |
text |
hex colour | #18181b |
Labels and body text. |
button |
hex colour | #2563eb |
Submit button background. |
accent |
hex colour | #2563eb |
Focus rings, checkboxes, links. |
font |
string, max 100 | Inter |
Any Google Font family name. |
border_radius |
none | rounded | pill |
rounded |
Corner style for inputs and buttons. |
mode |
light | dark |
light |
Base colour scheme. |
The field object
Fields are returned in display order. When you create or replace fields, array order becomes the display order.
{
"id": 311,
"type": "dropdown",
"label": "Topic",
"placeholder": "Choose one",
"default_value": "",
"required": true,
"width": "full",
"options": ["Sales", "Support", "Partnership"],
"validation_rules": {},
"conditional_logic": {},
"position": 2
}
| Field | Type | Required on write | Description |
|---|---|---|---|
id |
integer | read-only | Field ID. Fields are recreated whenever a form's field list is written, so IDs change on every update. |
type |
string | yes | One of the field types. |
label |
string, max 255 | yes | Label shown to respondents. Submission answers are keyed by this label, so keep labels unique within a form. |
placeholder |
string, max 255 | no | Placeholder text inside the input. |
default_value |
string, max 1000 | no | Pre-filled value. For hidden fields this is the value submitted unless overridden by prefilling. |
required |
boolean | no, default false |
Whether the respondent must answer. |
width |
full | half |
no, default full |
half places two fields side by side. |
options |
array of strings, max 100 | yes for dropdown, radio, checkbox |
Choices shown to the respondent. At least one non-empty string. Ignored for other types. |
validation_rules |
object | no | See Validation rules. |
conditional_logic |
object | no | See Conditional logic. |
position |
integer | read-only | Zero-based display order. |
Field types
type |
Input | Notes |
|---|---|---|
text |
Single-line text | Max 5000 characters. |
textarea |
Multi-line text | Max 5000 characters. |
email |
Email address | Validated as an email. |
phone |
Phone number | Free text, no format enforced. |
number |
Numeric input | Must be numeric. |
dropdown |
Select one from options |
Needs options. |
radio |
Radio buttons, one of options |
Needs options. |
checkbox |
Checkboxes, many of options |
Needs options. Answer is an array. |
date |
Date picker | Answer is YYYY-MM-DD. |
file |
File upload | Up to 10 MB; images, PDF, Office, CSV, TXT, ZIP. See File Uploads. |
hidden |
Not shown | Submits default_value or a prefilled value. Ideal for attribution such as source or campaign. |
Validation rules
Optional extra constraints on text-like fields. See Validation Rules for how they are enforced.
| Key | Type | Description |
|---|---|---|
min_length |
integer ≥ 0 | Minimum number of characters. |
max_length |
integer 1–5000 | Maximum number of characters. |
pattern |
string, max 500 | A regular expression the answer must match, e.g. /^[A-Z]{2}\d{4}$/. |
Conditional logic
Show a field only when another field has a certain value. The source field is referenced by its index in the fields array. See Conditional Logic.
| Key | Type | Description |
|---|---|---|
enabled |
boolean | Turn the rule on. Without enabled: true the field is always visible. |
field_index |
integer ≥ 0 | Index of the field whose value is checked. |
operator |
equals | not_equals | contains | is_empty | is_not_empty |
Comparison to apply. |
value |
string, max 255 | Value to compare against. Not needed for is_empty / is_not_empty. |
Example: show "Company size" only when "Are you a business?" (the first field) equals Yes:
{ "type": "dropdown", "label": "Company size", "options": ["1-10", "11-50", "51+"],
"conditional_logic": { "enabled": true, "field_index": 0, "operator": "equals", "value": "Yes" } }
List forms
GET /forms
| Query parameter | Type | Description |
|---|---|---|
status |
draft | published |
Only return forms with this status. |
page |
integer | Page number, starting at 1. |
per_page |
integer 1–100 | Forms per page. Default 25. |
Forms are ordered newest first and returned without their fields — fetch a single form to get them.
curl "https://rapidform.com/api/v1/forms?status=published&per_page=50" \
-H "Authorization: Bearer $RAPIDFORM_API_KEY"
{
"data": [
{ "id": 42, "name": "Contact us", "slug": "website-contact-form-k3j9xa", "status": "published", "submissions_count": 128, "…": "…" }
],
"links": { "first": "…?page=1", "last": "…?page=1", "prev": null, "next": null },
"meta": { "current_page": 1, "from": 1, "last_page": 1, "per_page": 50, "to": 1, "total": 1 }
}
Create a form
POST /forms
| Body parameter | Type | Required | Description |
|---|---|---|---|
name |
string, max 255 | yes | Public title. |
internal_name |
string, max 255 | no | Dashboard name. Defaults to name. Also used to build the slug. |
status |
draft | published |
no, default draft |
Publish immediately by passing published. |
fields |
array of field objects, 1–100 | yes | At least one field. |
settings |
settings object | no | Merged over the defaults. |
theme |
theme object | no | Merged over the defaults. |
curl -X POST https://rapidform.com/api/v1/forms \
-H "Authorization: Bearer $RAPIDFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Contact us",
"internal_name": "Website contact form",
"status": "published",
"fields": [
{ "type": "text", "label": "Name", "required": true, "width": "half" },
{ "type": "email", "label": "Email", "required": true, "width": "half", "placeholder": "[email protected]" },
{ "type": "dropdown", "label": "Topic", "options": ["Sales", "Support", "Partnership"], "required": true },
{ "type": "textarea", "label": "Message", "required": true, "validation_rules": { "max_length": 2000 } },
{ "type": "hidden", "label": "source", "default_value": "website" }
],
"settings": {
"submit_button_text": "Send message",
"thank_you_message": "Thanks! We reply within one business day."
},
"theme": { "button": "#2547e0", "accent": "#2547e0" }
}'
Responds 201 Created with the full form object, including fields with their IDs, the hosted url and the embed snippet.
Errors: 422 with errors for invalid input, or 422 with code: form_limit_reached if your plan's form limit is reached.
Get a form
GET /forms/{form}
Returns the form object with fields and submissions_count. Responds 404 if the form is not in this key's workspace.
curl https://rapidform.com/api/v1/forms/42 \
-H "Authorization: Bearer $RAPIDFORM_API_KEY"
Update a form
PATCH /forms/{form}
Every body parameter is optional. Only what you send changes:
| Body parameter | Behaviour |
|---|---|
name, internal_name, status |
Replaced. The slug never changes, so existing links and embeds keep working. |
settings |
Merged key by key over the current settings. |
theme |
Merged key by key over the current theme. |
fields |
Replaces the whole field list. Send every field you want to keep, in order. Field IDs are regenerated. |
# Publish a draft and tweak the button colour
curl -X PATCH https://rapidform.com/api/v1/forms/42 \
-H "Authorization: Bearer $RAPIDFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "published", "theme": { "button": "#177b4b" } }'
Responds 200 OK with the updated form object.
Changing fields does not affect existing submissions; their answers stay keyed by the labels in use at the time they were submitted.
Delete a form
DELETE /forms/{form}
Deletes the form and stops it accepting submissions. Existing submissions are retained. Responds 204 No Content.
curl -X DELETE https://rapidform.com/api/v1/forms/42 \
-H "Authorization: Bearer $RAPIDFORM_API_KEY"
List a form's fields
GET /forms/{form}/fields
Returns {"data": [ …field objects… ]} in display order.
Replace a form's fields
PUT /forms/{form}/fields
| Body parameter | Type | Required | Description |
|---|---|---|---|
fields |
array of field objects, 1–100 | yes | The complete new field list, in display order. |
Behaves like fields on PATCH /forms/{form} but leaves everything else untouched. Responds 200 OK with {"data": [ …the new fields… ]}.
curl -X PUT https://rapidform.com/api/v1/forms/42/fields \
-H "Authorization: Bearer $RAPIDFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{ "type": "email", "label": "Email", "required": true },
{ "type": "radio", "label": "Plan", "options": ["Free", "Pro", "Business"] },
{ "type": "checkbox", "label": "Interests", "options": ["Product news", "Webinars"] }
]
}'