Form capacity
POST /v1/forms creates a draft using a form slot. Active and paused forms count; archived forms do not. DELETE /v1/forms/{id} archives a form and frees its slot. Changing an archived form to active or paused with PATCH /v1/forms/{id} requires a slot again.
Creating or restoring a form at capacity returns 409 Conflict with error code form_limit_reached. The entire request is rolled back, including configuration or name changes. No form or source is partially created. After a downgrade selection period, new intake to an excess workspace or form returns 403 with plan_capacity_restricted. A matching existing idempotent receipt is still returned. Excess configured webhooks do not reject an otherwise valid response; the plan allowance at receipt time determines which enabled actions run. See limits by plan.
Verification is required
All submission endpoints require an active, verified customer owner in the workspace. This applies to HTML, JSON, authenticated server sources, attachments and idempotent retries. Until then, requests return 403 with error code email_verification_required, without storing a submission or using quota.
Management API keys require their customer account to be verified and the workspace to have a verified owner. These checks also apply to previously issued keys, on every request. Verify at your account verification page.
Public ingestion
HTML sources accept standard form posts and JSON requests. A source key selects the source; it does not grant management access. Server sources additionally require Authorization: Bearer YOUR_SOURCE_SECRET. This is the source secret, not a workspace management key. JSON ingestion uses a plain object of fields, such as {"email":"[email protected]","message":"Hello"}, without a fields wrapper.
Request a JSON response with Accept: application/json. The success envelope separates stored acceptance from later processing:
{
"ok": true,
"receipt": {
"id": "RECEIPT_REFERENCE",
"status": "accepted",
"received_at": "2026-09-10 12:00:00",
"duplicate": false
}
}The receipt status can be accepted or quarantined. A receipt contains no submitted field values. HTML requests receive a redirect only after the storage transaction completes.
Idempotency
Provide an Idempotency-Key header for a logical submission. Within the 24-hour retention window, a retry on the same source with the same key and normalized content returns the original receipt without a second accepted-submission charge. A different payload or attachment content under that key returns 409 Conflict.
For ordinary HTML retries, _idempotency_key is the hidden-field equivalent of the header. Keep the key stable for the same content. All underscore-prefixed metadata fields are stripped from stored business data.
Input limits
Up to 64 top-level business fields plus eight reserved metadata fields, 20 KB per business field, and 1 MiB of JSON/form data are accepted. Nested values are bounded to three levels and 32 items. Attachment limits are described in the file guide.
Ingestion errors
Errors use {"ok":false,"error":{"code":"ERROR_CODE","message":"Explanation"}}. Rate-limit responses include Retry-After in seconds; email limits report the remaining hourly window.
| HTTP status | What to check |
|---|---|
| 400 | Request structure, field shape, or malformed JSON. |
| 401 / 403 | Source credentials or an origin/access restriction. |
| 404 | The endpoint key and source availability. |
| 409 | An idempotency conflict, replayed browser token, or matching-content limit. |
| 405 | The ingestion endpoint requires POST; OPTIONS handles browser preflight. |
| 413 | Payload or attachment size limits. |
| 415 | An unsupported request content type. |
| 422 | Published field rules or attachment validation. |
| 425 | Wait for the enhanced protection readiness delay. |
| 429 | Source protection, email frequency, or workspace allowance limits. |
| 5xx | A temporary infrastructure failure. A missing response is not proof that storage failed; retry with the original idempotency key. |
Optional browser protection
Enhanced HTML connections require a signed intent and its empty randomized honeypot on every new submission, including JSON. Use the CDN script’s prepare() helper or initialize with GET /f/{source_public_key}/intent on the submit host. Initialization requires an active, published source and a verified owner. Standard HTML and trusted-server authentication keep their existing contracts. Read the complete integration and error guide.
Customer management API
Open API keys in your current workspace. Verified owners and administrators can create a key when the workspace has an active, verified owner. Choose read-only or read-and-write access, then save the full key when it is shown; it is displayed only once. Send the key as a bearer token from your server. Customer management keys and source ingestion credentials are separate.
curl "https://api.formbastion.com/v1/forms" \
-H "Authorization: Bearer YOUR_WORKSPACE_API_KEY" \
-H "Accept: application/json"| Method | Path | Purpose |
|---|---|---|
| GET / POST | /v1/forms | List or create forms. |
| GET / PATCH / DELETE | /v1/forms/{id} | Read, update, or archive a form. DELETE preserves its existing submissions. |
| GET | /v1/submissions | List submissions. Filters: form_id, status, q, page. |
| GET / DELETE | /v1/submissions/{id} | Read or delete a submission. |
| POST | /v1/submissions/{id}/release | Release a quarantined submission, subject to quota. |
| POST | /v1/files/{id}/download | Create a workspace-scoped, single-use download URL valid for 60 seconds; requires write scope. |
| POST | /v1/actions/{id}/replay | Replay an eligible action. |
Every operation is limited to the key’s workspace and scope. Do not expose management keys in frontend JavaScript or public repositories. Revoke unused keys in your workspace.
Creating and publishing
POST a JSON object with name, optional project_id, and optional publish: true. New forms start with name, email and message fields. Set config to a full form configuration to replace the draft; PATCH accepts name, status, config, and publish. The form editor provides the same validation and publication workflow. Lists return data plus pagination with 25 records per page. Form responses include their source endpoints; secrets are never returned.
Boundary rules
- Submitted fields cannot select a different tenant, webhook destination, or privileged recipient.
- Published form configuration decides validation, protection, attachment limits, and actions.
- Submission responses do not contain private inbox data.