REST API for managing forms and submissions programmatically. Available on all plans.
API version: v1 · Base URL: https://formblade.com
Download Postman Collection v1
Personal plan — read-only access.
Personal (free) accounts are limited to GET requests only. You can list forms, view submissions, export data, and download files — but you cannot create, update, or delete anything via the API.
Upgrade to Pro for full read + write API access.
Get started:
Create an API key from the API Keys page in your dashboard. Personal plan users get read-only keys; Pro users can choose between read-only and full-access keys.
All API requests require a Bearer token in the Authorization header:
Authorization: Bearer fb_sk_your_api_key_here
There are two layers of access control:
The scope is set when you create the key and determines which HTTP methods are allowed.
| Scope | Allowed methods | Who can create |
|---|---|---|
read | GET only | All plans |
full | GET, POST, PATCH, DELETE | Pro+ only |
Your plan determines what scope you can create:
| Plan | Can create read keys | Can create full keys |
|---|---|---|
| Personal | Yes | No |
| Pro | Yes | Yes |
Personal plan users can only create read-scoped keys. Even if you could somehow obtain a full-scoped key, write requests would still be rejected because your plan does not support it. See Troubleshooting below.
All errors return JSON with a detail field:
{"detail": "Form not found"}
Invalid or missing API key. The request has no Authorization header, or the key doesn't match any active key.
Common causes:
Authorization: Bearer fb_sk_... headerYou don't have permission for this action. Multiple possible causes:
| Message | Cause | Fix |
|---|---|---|
This API key is read-only | Write request with a read-scoped key | Upgrade to Pro for full-access keys, or create a full scope key if already on Pro |
Full-access API keys require a Pro plan | Creating a full key on Personal plan | Upgrade to Pro |
Form limit reached | Hit max forms (Personal: 5, Pro: 100) | Delete unused forms or upgrade |
This captcha provider requires a Pro plan | Setting captcha_type to reCAPTCHA, Turnstile, or GeeTest (hCaptcha and math are free) | Use hCaptcha or upgrade to Pro |
Auto-responder requires a Pro plan | Setting auto_respond: true | Upgrade to Pro |
Custom theme colors require a Pro plan | Setting form_theme_custom with color overrides | Use a preset theme or upgrade to Pro |
The resource doesn't exist or doesn't belong to your account. Form IDs, submission IDs, and file names are scoped to your account — you cannot access other users' data.
A file upload exceeds your plan's limits:
| Message | Limit |
|---|---|
File exceeds X MB limit | Personal: 1 MB/file, Pro: 25 MB/file |
Storage limit reached | Personal: 100 MB total, Pro: 1 GB total |
Delete old submissions or files to free space, or upgrade.
The request body is malformed or missing required fields. Check the endpoint documentation for the expected fields and types.
Monthly submission limit reached. This applies to form submissions via POST /f/{endpoint_id}, not to API management calls.
| Plan | Limit |
|---|---|
| Personal | 300 submissions/month |
| Pro | 3,000 submissions/month |
GET /api/forms/stats → submissions_this_month vs submissions_limit| Field | Type | Example | Description |
|---|---|---|---|
id | uuid | "a1b2c3d4-e5f6-..." | Unique form identifier |
name | string (3–64) | "Contact Form" | Form name |
endpoint_id | string (6–12) | "contact" | Short ID used in /f/{endpoint_id} URL |
notify_email | string | null | "you@example.com" | Email address for submission notifications |
redirect_url | string (max 500) | null | "https://site.com/thanks" | URL to redirect to after submission |
is_active | boolean | true | Whether the form accepts submissions |
honeypot_field | string (max 100) | null | "_fb_hp" | Custom honeypot field name (default: _fb_hp) |
js_honeypot | boolean | true | JS verification enabled (default: true) |
js_honeypot_field | string (max 100) | null | "_fb_js" | Custom JS honeypot field name (default: _fb_js) |
captcha_type | string | "none" | none, math, hcaptcha, recaptcha_v2, recaptcha_v3, turnstile, geetest_v4 |
captcha_site_key | string | null | null | Captcha provider site/public key |
captcha_min_score | float | null | 0.5 | reCAPTCHA v3 minimum score (0.0–1.0) |
form_theme | string | "corporate" | minimal, corporate, glass, dark, warm, compact |
form_fields | array | null | see below | Hosted form field configuration |
auto_respond | boolean | false | Auto-responder enabled (Pro+) |
consent_required | boolean | false | Require consent checkbox |
ip_anonymize | boolean | false | Anonymize stored IP addresses |
store_ip | boolean | true | Store submitter IP |
store_user_agent | boolean | true | Store submitter user agent |
data_retention_days | integer | null | 90 | Auto-delete submissions after N days (null = plan default) |
view_count | integer | 342 | Hosted form page view count (read-only) |
submission_count | integer | 57 | Total non-spam submissions (read-only) |
created_at | ISO 8601 | "2026-03-15T10:30:00Z" | When the form was created (read-only) |
updated_at | ISO 8601 | "2026-03-20T14:22:00Z" | When the form was last modified (read-only) |
The form_fields array defines the hosted form layout. Each entry is an object with a type and optional properties:
[
{"type": "heading", "name": "heading", "label": "Contact us"},
{"type": "text", "name": "name", "label": "Name", "placeholder": "Your name", "required": true},
{"type": "email", "name": "email", "label": "Email", "placeholder": "you@example.com", "required": true},
{"type": "textarea", "name": "message", "label": "Message", "placeholder": "How can we help?", "required": true, "rows": 4},
{"type": "select", "name": "priority", "label": "Priority", "options": ["Low", "Medium", "High"], "required": true},
{"type": "submit", "name": "", "label": "Send message", "required": false}
]
Supported field types: heading, text, email, textarea, select, file, submit.
List all your forms with submission counts (excludes spam).
curl -H "Authorization: Bearer fb_sk_..." \ https://formblade.com/api/forms
Response: Array of form objects (see fields above).
Create a new form. Returns 201 Created.
curl -X POST -H "Authorization: Bearer fb_sk_..." \
-H "Content-Type: application/json" \
-d '{"name": "Contact Form", "notify_email": "you@example.com"}' \
https://formblade.com/api/forms
Request body:
| Field | Type | Required | Example | Notes |
|---|---|---|---|---|
name | string (3–64) | Yes | "Contact Form" | |
notify_email | string (max 255) | No | "you@example.com" | Defaults to account email |
redirect_url | string (max 500) | No | "https://site.com/thanks" | URL after submission |
honeypot_field | string (max 100) | No | "_fb_hp" | Default: _fb_hp |
js_honeypot | boolean | No | true | Default: true |
js_honeypot_field | string (max 100) | No | "_fb_js" | Default: _fb_js |
Response: Form object.
Get a single form by ID.
Path: form_id — uuid (required)
Response: Form object.
Update form settings. Send only the fields you want to change.
curl -X PATCH -H "Authorization: Bearer fb_sk_..." \
-H "Content-Type: application/json" \
-d '{"name": "Updated Name", "is_active": false}' \
https://formblade.com/api/forms/{form_id}
Request body (all optional):
| Field | Type | Example | Notes |
|---|---|---|---|
name | string (3–64) | "Updated Name" | |
notify_email | string (max 255) | "team@example.com" | |
redirect_url | string (max 500) | "https://site.com/thanks" | |
is_active | boolean | false | Enable/disable the form |
honeypot_field | string (max 100) | "_fb_hp" | |
js_honeypot | boolean | true | |
js_honeypot_field | string (max 100) | "_fb_js" | |
form_fields | array | see form fields above | Hosted form field config |
form_theme | string | "corporate" | minimal free, others Pro+ |
captcha_type | string | "hcaptcha" | math & hcaptcha free, others Pro+ |
captcha_site_key | string (max 255) | "10000000-ffff-..." | Required with captcha_type |
captcha_secret_key | string (max 255) | "0x..." | Required with captcha_type |
captcha_min_score | float (0.0–1.0) | 0.5 | reCAPTCHA v3 only |
auto_respond | boolean | true | Pro+ |
auto_respond_subject | string (max 255) | "Thanks for reaching out" | |
auto_respond_body | text | "We received your message..." | |
data_retention_days | integer | 90 | Capped to plan limit |
consent_required | boolean | true | |
consent_message | text | "I agree to the privacy policy" | |
ip_anonymize | boolean | true | |
store_ip | boolean | true | |
store_user_agent | boolean | true |
Response: Updated form object.
Delete a form and all its submissions and files. This action is irreversible.
Response: 204 No Content
Dashboard statistics: submission counts, storage usage, recent activity.
{
"total_forms": 3,
"total_submissions": 150,
"submissions_today": 5,
"submissions_this_week": 28,
"submissions_this_month": 95,
"spam_count": 4,
"storage_used_mb": 12.5,
"storage_limit_mb": 50,
"submissions_limit": 300,
"forms_limit": 5,
"plan": "free",
"recent_submissions": [...],
"top_forms": [...]
}
Send a test notification email using the form's email configuration.
{"ok": true, "message": "Test email sent to you@example.com"}
| Field | Type | Example | Description |
|---|---|---|---|
id | uuid | "106f069f-..." | Unique submission identifier |
data | object | {"name": "Jane", "email": "jane@example.com"} | Key-value pairs of submitted form data |
files | object | null | null | Uploaded files metadata (field → {filename, stored_name, size_bytes, content_type}) |
ip_address | string | null | "203.0.113.42" | Submitter IP (if stored, may be anonymized) |
user_agent | string (max 500) | null | null | Raw user agent string (if stored) |
device | object | null | {"device_type": "desktop", "browser": "Chrome 145", "os": "Windows 10"} | Parsed device info |
is_spam | boolean | false | Whether flagged as spam |
spam_flags | string[] | null | null | Which checks triggered: honeypot, js_honeypot, captcha |
created_at | ISO 8601 | "2026-03-23T11:02:05Z" | When the submission was received |
List submissions with pagination and spam filtering.
| Query param | Type | Default |
|---|---|---|
page | integer | 1 |
per_page | integer (1–100) | 50 |
spam | boolean | all (omit to include everything) |
curl -H "Authorization: Bearer fb_sk_..." \
"https://formblade.com/api/forms/{form_id}/submissions?page=1&per_page=25&spam=false"
Response:
{
"items": [
{
"id": "106f069f-...",
"data": {"name": "Jane", "email": "jane@example.com", "message": "Hello!"},
"files": null,
"ip_address": "203.0.113.42",
"device": {"device_type": "desktop", "browser": "Chrome 145.0.0", "os": "Windows 10"},
"is_spam": false,
"spam_flags": null,
"created_at": "2026-03-23T11:02:05Z"
}
],
"total": 42,
"page": 1,
"per_page": 25
}
Export submissions as CSV, JSON, or Excel. Excludes spam. Returns a file download.
| Query param | Options | Plan |
|---|---|---|
format | csv (default), json, xlsx | xlsx requires Pro+ |
curl -H "Authorization: Bearer fb_sk_..." \
-o submissions.csv \
"https://formblade.com/api/forms/{form_id}/submissions/export?format=csv"
Toggle the spam flag on a submission. Returns the new state.
{"ok": true, "is_spam": true}
Resend the notification email for a submission.
{"ok": true, "message": "Notification resent to you@example.com"}
Delete a submission and its uploaded files.
Response: 204 No Content
Download an uploaded file. The stored_name comes from the submission's files object.
curl -H "Authorization: Bearer fb_sk_..." \
-o document.pdf \
https://formblade.com/api/forms/{form_id}/submissions/{id}/files/{stored_name}
List all uploaded files across your forms with filtering and pagination.
| Query param | Type | Description |
|---|---|---|
form_id | uuid | Filter by form |
file_type | string | Filter by extension (e.g. pdf) |
search | string | Search by filename or form name |
page | integer | Default: 1 |
per_page | integer | Default: 50 (max 100) |
| Limit | Personal (free) | Pro |
|---|---|---|
| API keys | 1 (read-only) | 10 (read + full) |
| Submissions/month | 300 | 3,000 |
| Forms | 5 | 100 |
| File upload size | 1 MB | 25 MB |
| Storage | 100 MB | 1 GB |
| Submission archive | 90 days | 1 year |
| Excel export | No | Yes |
| Captcha providers | Honeypot + hCaptcha | All (reCAPTCHA, Turnstile, GeeTest, hCaptcha) |
| Auto-responder | No | Yes |
Import the collection into Postman to test all endpoints. Set the api_key variable to your API key and base_url to https://formblade.com.
Download Postman Collection v1
There are currently no rate limits on the API beyond your plan's monthly submission quota. We reserve the right to introduce rate limiting in the future if needed.
Common issues and how to resolve them. See Error responses above for the full list of status codes.
Most likely a scope or plan issue. Check these in order:
full-scoped key.read key it will reject write requests. Create a new full key from API Keys.The key doesn't match. Verify:
Authorization: Bearer fb_sk_... (with space after Bearer)The monthly limit counts submissions across all your forms combined, not per form. Spam-flagged submissions also count because they were accepted before being flagged.
Check your usage: GET /api/forms/stats returns submissions_this_month and submissions_limit.
Limits: Personal 300/month, Pro 3,000/month. Resets on the 1st at midnight UTC.
Two possible causes:
Check storage usage via GET /api/forms/stats → storage_used_mb and storage_limit_mb.
New forms get default fields (name, email, message) automatically. If you want custom fields, set form_fields in a follow-up PATCH request with your field configuration array.
Still stuck? Contact us with your error message and we'll help.