Create forms, retrieve submissions, and manage your form backend programmatically. Full CRUD access with API key authentication.
https://formslist.com/api/v1All API requests require a Bearer token using your API key. Generate API keys from your dashboard under Account → API Keys.
API keys are hashed (SHA-256) before storage and cannot be retrieved after creation. Keep your key secure — treat it like a password. If compromised, revoke it immediately from the dashboard and generate a new one.
Authorization: Bearer fl_your_api_key_herecurl https://formslist.com/api/v1/forms \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"const response = await fetch('https://formslist.com/api/v1/forms', {
headers: {
'Authorization': 'Bearer fl_live_a1b2c3d4e5f6',
'Content-Type': 'application/json',
},
});
const { data } = await response.json();
console.log(data); // Array of formsimport requests
headers = {"Authorization": "Bearer fl_live_a1b2c3d4e5f6"}
response = requests.get("https://formslist.com/api/v1/forms", headers=headers)
data = response.json()["data"]
print(data) # List of formsSecurity: Never expose your API key in client-side JavaScript (browser code). API keys should only be used in server-side code, environment variables, or CI/CD pipelines.
All endpoints are rate-limited to 100 requests per 60-second window per API key. Exceeding the limit returns 429 Too Many Requests.
All successful responses return JSON with a data field. List endpoints include a meta field with pagination info.
{
"data": { ... },
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"total_pages": 2
}
}{
"error": "Missing or invalid Authorization header"
}Create, read, update, and delete form endpoints. Each form has a unique hash used as the submission endpoint at /f/{hash}.
/api/v1/formsReturns all forms belonging to your team.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Optional | Unique form ID |
name | string | Optional | Form name |
hash | string | Optional | Public form hash for the submission endpoint |
endpoint | string | Optional | Full submission path (/f/{hash}) |
submission_count | number | Optional | Total submissions received |
is_active | boolean | Optional | Whether the form accepts submissions |
created_at | string | Optional | ISO 8601 timestamp |
curl https://formslist.com/api/v1/forms \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"{
"data": [
{
"id": "frm_8kTn2xLm",
"name": "Contact Form",
"hash": "abc123def",
"endpoint": "/f/abc123def",
"submission_count": 47,
"is_active": true,
"created_at": "2026-03-15T10:30:00Z"
}
],
"meta": { "total": 1 }
}/api/v1/formsCreates a new form endpoint.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Form name |
description | string | Optional | Form description |
curl -X POST https://formslist.com/api/v1/forms \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6" \
-H "Content-Type: application/json" \
-d '{"name": "Contact Form", "description": "Main site contact"}'{
"data": {
"id": "frm_9pQr3yMn",
"name": "Contact Form",
"hash": "xyz789abc",
"endpoint": "/f/xyz789abc",
"is_active": true,
"created_at": "2026-03-22T14:00:00Z"
}
}/api/v1/forms/:formIdReturns details for a single form.
curl https://formslist.com/api/v1/forms/frm_8kTn2xLm \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"/api/v1/forms/:formIdUpdates a form's properties. All fields are optional.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Optional | New form name |
description | string | Optional | New description |
is_active | boolean | Optional | Enable or disable the form |
curl -X PATCH https://formslist.com/api/v1/forms/frm_8kTn2xLm \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Contact Form", "is_active": false}'/api/v1/forms/:formIdPermanently deletes a form and all its submissions. This action cannot be undone.
curl -X DELETE https://formslist.com/api/v1/forms/frm_8kTn2xLm \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"{
"data": { "deleted": true }
}Retrieve form submissions programmatically. Submissions are created when users submit forms via the /f/{hash} endpoint — they cannot be created via the API.
/api/v1/forms/:formId/submissionsReturns paginated submissions for a form, newest first.
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | Optional | Page number (default: 1) |
per_page | number | Optional | Results per page (max 100) (default: 25) |
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Optional | Submission ID |
data | object | Optional | Submitted form data as key-value pairs |
is_spam | boolean | Optional | Whether flagged as spam by AI scoring |
created_at | string | Optional | ISO 8601 timestamp |
curl "https://formslist.com/api/v1/forms/frm_8kTn2xLm/submissions?page=1&per_page=50" \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"{
"data": [
{
"id": "sub_4jKp7rWs",
"data": {
"name": "Sarah Chen",
"email": "sarah@example.com",
"message": "Interested in your Pro plan. Can we schedule a demo?"
},
"is_spam": false,
"created_at": "2026-03-22T09:15:00Z"
},
{
"id": "sub_2mNq9tYu",
"data": {
"name": "Marcus Rivera",
"email": "marcus@agency.co",
"message": "We build 20+ client sites per year. Is there an agency plan?"
},
"is_spam": false,
"created_at": "2026-03-21T16:42:00Z"
}
],
"meta": {
"page": 1,
"per_page": 50,
"total": 47,
"total_pages": 1
}
}/api/v1/submissions/:submissionIdReturns a single submission with full details including metadata.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Optional | Submission ID |
form_id | string | Optional | Parent form ID |
data | object | Optional | Submitted form data |
metadata | object | null | Optional | Request metadata (IP geolocation, user agent, UTM params) |
is_spam | boolean | Optional | Whether flagged as spam |
is_read | boolean | Optional | Whether marked as read in the dashboard |
created_at | string | Optional | ISO 8601 timestamp |
curl https://formslist.com/api/v1/submissions/sub_4jKp7rWs \
-H "Authorization: Bearer fl_live_a1b2c3d4e5f6"{
"data": {
"id": "sub_4jKp7rWs",
"form_id": "frm_8kTn2xLm",
"data": {
"name": "Sarah Chen",
"email": "sarah@example.com",
"message": "Interested in your Pro plan."
},
"metadata": {
"ip": "203.0.113.42",
"country": "US",
"city": "San Francisco",
"user_agent": "Mozilla/5.0...",
"utm_source": "twitter",
"utm_medium": "social"
},
"is_spam": false,
"is_read": true,
"created_at": "2026-03-22T09:15:00Z"
}
}Form submissions are sent to https://formslist.com/f/{hash} — this is a separate endpoint from the REST API and does not require authentication.
<form action="https://formslist.com/f/your_form_hash" method="POST">
<input name="name" type="text" required />
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>Set Accept: application/json to receive a JSON response instead of a redirect.
const response = await fetch('https://formslist.com/f/your_form_hash', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
name: 'Sarah Chen',
email: 'sarah@example.com',
message: 'Hello from JavaScript!',
}),
});
const result = await response.json();
// { "success": true, "submission_id": "sub_..." }| Parameter | Type | Required | Description |
|---|---|---|---|
_redirect | string | Optional | URL to redirect to after submission (HTML forms only) |
_replyto | string | Optional | Email address for auto-responder (overrides "email" field) |
_gotcha | string | Optional | Honeypot field — leave empty. If filled, submission is marked as spam |
_captcha | string | Optional | CAPTCHA token (reCAPTCHA, Turnstile, or hCaptcha) |
| Status | Meaning | Common Cause |
|---|---|---|
400 | Bad Request | Missing required fields (e.g., name on form creation) |
401 | Unauthorized | Missing, malformed, or invalid API key |
403 | Forbidden | Team has reached its plan's form limit |
404 | Not Found | Resource does not exist or belongs to a different team |
429 | Too Many Requests | Rate limit exceeded (100 req/min per key) |
500 | Server Error | Internal error — contact support if persistent |
API access is available on Pro ($15/mo) and Business ($45/mo) plans.