Site
A website/domain in FormBox. Sites own Hooks, timezone overrides, and scoped dashboard views.
FormBox.ai docs
FormBox gives websites secure Hooks, ordered Inbox submissions, notification routing, private files, AI review, approved webhooks, reports, and API/MCP operations. Your website keeps ownership of the visible form.
Product boundary
FormBox handles submission intake, storage, review, routing, and delivery. The website controls its visible fields and validation.
Docs menu
Jump to any section
Quickstart
Create a Site using the website's canonical domain.
Create a Hook for the form or workflow.
Configure notification routing, allowed origins, and optional approved-webhook delivery.
Build the visible form in the website or install a maintained adapter.
Submit the browser form to a same-origin site handler.
Validate the request and verify Turnstile or captcha before forwarding.
Forward the request to the Hook with the intake secret on the trusted server.
Run a safe test and verify Inbox, Activity, files, and expected delivery behavior.
Hook intake URL
https://hooks.formbox.ai/f/{hookId}/{slug}. Treat the paired intake secret as a server-side credential.Access
Model
A website/domain in FormBox. Sites own Hooks, timezone overrides, and scoped dashboard views.
A secure intake URL for one form or workflow. Hooks store notification routing, allowed origins, status, approved-webhook settings, and an intake secret.
The operational queue of submissions. Each item keeps readable fields, raw payload JSON, metadata, files, delivery activity, and AI review state.
Filtered submission totals, charts by day/site/Hook, failed-delivery counts, and CSV export.
Workspace defaults for timezone, email templates, internal copies, operational alerts, AI review, users, API keys, and delivery ops.
REST/OpenAPI is the machine-readable source of truth. The local MCP server maps agent workflows to the same API.
Integration
Browser form
Collect visible fields and attribution. Never receive or expose the Hook secret.
Same-origin site handler
Validate required fields, normalize values, and verify Turnstile or captcha.
FormBox Hook
Authenticate intake, store the Inbox item and files, then start review and delivery work.
Keep credentials behind the website
X-FormBox-Secret. Send it only from a trusted server, serverless function, or terminal. Never place the intake secret in browser HTML, browser JavaScript, a hidden field, a public repository, or analytics data.Fail closed before FormBox
Quick check
Use this request to verify Hook connectivity from a trusted terminal or server.
# Run from a trusted server or terminal only.
curl "$FORMBOX_HOOK_URL" \
-H "Content-Type: application/json" \
-H "X-FormBox-Secret: $FORMBOX_HOOK_SECRET" \
--data '{
"payload": {
"name": "Test Lead",
"email": "test@example.com",
"message": "Testing FormBox intake"
}
}'This creates a real Inbox item
Intake contract
A trusted site backend sends POST /f/{hookId}/{slug} to the intake host. JSON may contain flat business fields or a payload/metadata envelope; URL-encoded and multipart requests are also accepted.
Validate the receipt, not just an HTTP success
201, ok: true and a valid UUID inboxItemId. The response also includes integer fileCount and boolean deduplicated. This confirms storage only: AI review, client delivery, agency copies and webhooks finish separately. A generic 2xx or HTML body is not this receipt.| Idempotency-Key | One stable key per submission attempt | 16–128 characters from A–Z, a–z, digits, dot, underscore, colon and hyphen. Reuse it only with the same business payload, files and direct-upload claim. |
|---|---|---|
| Completed retry | 201, original inboxItemId, deduplicated: true | No additional Inbox item, file upload or notification is created. |
| Changed content | 409 idempotency_conflict | Do not retry a changed submission under the old attempt key. |
| Concurrent attempt | 409 idempotency_in_progress | Honor Retry-After: 1 and retry the unchanged request. Use a fresh key only for a genuinely new attempt. |
| No key | Accepted without attempt deduplication | Repeated requests can create duplicate Inbox items. |
| Archive / pause | Archived Site or Hook: 404; paused Hook: 409 | Archive is a soft lifecycle change, not deletion of historical Inbox/files. Site archive shuts down all its Hook intake/upload authorization. Archived records cannot be reactivated with ordinary PATCH. |
JSON/URL-encoded bodies are limited to 64 KiB; payloads allow up to 100 fields, string values up to 10,000 characters and depth 64. Multipart uses a separate parser limit. Your hosting platform or website adapter can impose a smaller transport budget. Ordinary intake allows absent Origin/Referer, www-normalized hosts and configured wildcards. The secret is the authentication boundary; Origin is not captcha.
Data contract
Visitor-submitted business fields. FormBox preserves these values and shows them in client-facing field tables.
Page, referrer, user-agent, UTM, click-ID, source, and system context. Keep it out of visible business fields.
Send metadata.fieldOrder for JSON or _formbox_field_order for multipart requests.
Files
| Multipart intake | Up to 5 files, 10 MiB each | JPG, JPEG, PNG, WEBP, HEIC, HEIF, PDF, DOC, DOCX, and TXT. |
|---|---|---|
| Direct PDF upload | One PDF, up to 20 MiB | Authorize through the Hook upload endpoint, validate the returned versioned policy, upload to private R2, then submit the one-time claim ID. |
| Combined intake | Up to 6 files, 70 MiB total | Five multipart attachments plus one direct PDF. Website transport limits remain separate. |
| Storage | Private objects | FormBox stores file metadata in the database and file bytes in private object storage. |
| Downloads | Protected delivery | Dashboard downloads require organization access; email links use signed FormBox routes and private-storage redirects. |
Use the Hook descriptor as the contract
directUpload descriptor only when the secret, exact allowed origin, and storage configuration are ready. Integrations must validate its version, limits, content type, organization, Hook, and storage host before sending bytes.Privacy
Routing
Store first, deliver second
Operational failure alerts
Outbound
An approved webhook is an optional outbound delivery for systems that should receive only AI-confirmed legitimate submissions. It is separate from client notification email.
| Event / version | inbox.item.approved / 2026-07-22 | JSON contains version, event, deliveryId and submission (id, referenceNumber, submittedAt, payload, metadata, hook, site, files, approval). OpenAPI includes its exact schema. |
|---|---|---|
| Headers | x-formbox-event, x-formbox-delivery-id, x-formbox-key-version | Also x-formbox-timestamp (Unix seconds) and x-formbox-signature (v1= plus lowercase hex HMAC-SHA256). |
| Derived signing key | HMAC-SHA256(configured secret, formbox-approved-webhook-signing-v1) | Keep the raw digest bytes as the signing key, not its hex string. |
| Signed message | timestamp.deliveryId.rawBody | UTF-8 concatenation with literal dots. HMAC-SHA256 using the derived key; compare the hex signature in constant time. Verify the original request bytes before parsing or re-serializing JSON. |
| Receiver replay protection | Timestamp tolerance and deliveryId deduplication | Choose a bounded clock-skew window (for example five minutes), persist deliveryId before side effects, and return a 2xx for an already processed retry. Each retry has a fresh timestamp/signature. |
| Receiver response | Any 2xx acknowledges delivery | Redirects are not followed. Most 4xx are terminal; 408/425/429, 5xx and network failures use bounded retries. Receiver timeout is ten seconds. |
Automation
POST /api/v1/provision-site-intake creates one Site and between 1 and 50 Hooks in one authenticated workflow for a website integration.
| Request | Canonical domain, optional Site name, and 1–50 Hook definitions | Each Hook can include notification routing, allowed origins, and a paired approved-webhook URL and signing secret. |
|---|---|---|
| Validation | Strict and fail closed | Only documented properties are accepted. Duplicate generated Hook slugs and malformed domains, emails, origins, or webhooks are rejected before writes. |
| Limits | 256 KiB body and 10-second read deadline | Oversized and stalled requests return dedicated 413 and 408 errors. |
| Atomicity | All or nothing | If any Site or Hook write fails, no usable partial installation is returned. |
| Response | Site plus created Hooks | Each Hook includes its intake URL, one-time intake secret, and directUpload descriptor when available. |
Dashboard
| Inbox | Search and filter submissions by date, Site, Hook, delivery status, files, and payload text. Detail pages show submitted fields, raw JSON, metadata, files, Activity, AI review, and owner-only permanent delete. |
|---|---|
| Sites | Create Sites by domain, set a Site timezone, create connected Hooks, and review recent submissions for that Site. |
| Hooks | Copy the live Hook URL, explicitly reveal its intake secret as a manager or owner, send a test Inbox item, pause or reactivate intake, configure notification and CC emails, allowed origins, and an optional approved-submission webhook. |
| Reports | Run reports across all time, presets, custom ranges, Sites, and Hooks. Export CSV with ordered payload fields. |
| Settings / General | Set the account timezone used when a Site does not have its own timezone override. |
| Settings / Email | Configure Global BCC copy recipients, operational failure alerts, metadata visibility, table or plain-text format, subject and sender templates, and reference numbers. |
| Settings / AI Review | Enable spam review, choose label-only or block-high-confidence-spam behavior, and set the confidence threshold. |
| Settings / Users | Owner-only user creation, role changes, and non-owner user removal. Roles are owner, manager, and viewer. |
| Settings / API | Owner-only API key creation, creation-time secret return, later owner-authorized reveal/copy, revoke/reinstate, and delete. Presets include Agent — Read/Write, Agent — Read Only, and Admin. |
| Settings / Ops | Review pending, failed, or stuck delivery work and retry recoverable failures. |
| Account | Update the user profile name, agency workspace name, and view the current role and preferences. |
Roles
Automation
Use FormBox API keys for agents and automation. Send Authorization: Bearer with the key from a protected environment. OpenAPI operations declare required scopes in x-required-scopes; successful and error bodies are specified. Management bodies reject unknown fields, invalid types and ambiguous mutations before writes.
Site creation/update supports name; an explicit null timezone clears the override, while omission retains it. Hook blank/omitted signing secret preserves the existing secret. API-key PATCH requires explicit boolean revoked: true revokes, false reinstates. User-role PATCH requires an explicit valid role; owner assignment requires literal Admin *. A key can create only a subset of its own scopes.
| Sites | GET/POST /api/v1/sites | GET/PATCH/DELETE /api/v1/sites/{siteId} |
|---|---|---|
| Hooks | GET/POST /api/v1/hooks | Generic reads exclude intake secrets. GET /api/v1/hooks/{hookId}/secret requires hooks:secrets:read; PATCH/DELETE and secret rotation remain separate privileged operations. |
| Inbox | GET /api/v1/inbox | GET /api/v1/inbox/{inboxItemId}; file, download, delivery, and retry routes |
| Settings | GET/PUT /api/v1/settings/email | API key, user, and delivery-ops routes under /api/v1/settings and /api/v1/ops |
| Provisioning | POST /api/v1/provision-site-intake | Atomically creates one Site plus one or more Hooks. |
| OpenAPI | GET /api/v1/openapi.json | Authoritative machine-readable request, response, validation, and error contract. |
| Agent — Read/Write | sites:*, hooks:*, inbox:*, settings:*, api_keys:*, users:*, ops:*, provision:write |
|---|---|
| Agent — Read Only | sites:read, hooks:read, inbox:read, settings:read, api_keys:read, users:read, ops:read |
| Admin | * |
Choose privileges explicitly
agent_rw, agent_readonly, admin) or a nonempty explicit scope list. Missing, misspelled or conflicting selections are rejected, not upgraded to a broad default. Agent Read/Write includes team/key management, email settings, Hook-secret reveal/rotation and provisioning. Use only what your agent needs. API creation returns the key secret; owners can reveal it again in Settings / API, while key listing stays secret-free.The local stdio MCP wrapper exposes these workflow tools and maps them directly to REST:
list_sitescreate_siteget_siteupdate_sitearchive_sitelist_hookscreate_hookget_hookreveal_hook_secretupdate_hookarchive_hookrotate_hook_secretlist_inboxget_inbox_itemlist_inbox_filesget_inbox_file_download_urllist_inbox_deliveriesretry_inbox_deliveryget_email_settingsupdate_email_settingslist_api_keyscreate_api_keyrevoke_api_keydelete_api_keylist_userscreate_userupdate_user_roleremove_userlist_ops_deliveriesprovision_site_intakeVerification
Help
| 403 invalid_form_secret | The Hook secret is missing or wrong. | Send X-FormBox-Secret only from a trusted server-side integration. Browser forms should submit to a same-origin site handler. |
|---|---|---|
| 403 origin_not_allowed | A supplied Origin or Referer fails the configured ordinary-intake allowlist. | Ordinary intake allows absent headers, normalizes www and supports configured wildcards. Direct uploads require a mandatory exact allowed Origin; keep the Hook secret server-side. |
| 400 submitted_too_fast / spam_trap_triggered | The bot-trap values look suspicious. | Keep _formbox_hp empty. _formbox_started_at uses Unix milliseconds and a two-second minimum when valid. Missing/invalid timing is not a captcha check; the website must verify captcha itself. |
| 409 hook_paused | The Hook is paused. | Reactivate the Hook in the dashboard or PATCH the Hook status through the API. |
| 429 rate_limit_exceeded | Too many submissions reached the same Hook/IP window. | Honor Retry-After and reduce automated test traffic. |
| Fields appear in the wrong order | No valid field-order hint was sent. | Send metadata.fieldOrder for JSON or _formbox_field_order for multipart, matching visible business-field order. |
| Metadata appears as visible fields | Tracking values were sent in payload. | Move page URL, referrer, user agent, UTMs, and click IDs into metadata or supported reserved _formbox_* fields. |
| Attribution is missing after navigation | The website captured attribution only on the form page. | Capture first-touch attribution before navigation, then forward it as metadata when the visitor submits. |
| Submission stores but no email arrives | No recipient is configured, AI blocked delivery, or delivery failed. | Check Hook routing, AI Review, submission Activity, and Settings / Ops. |
| Approved webhook did not fire | The submission was not confirmed legitimate or webhook delivery failed. | Check AI verdict and Activity. Approved webhooks are deliberately withheld unless AI confirms a legitimate lead. |
| File upload rejected | The request exceeded the selected upload path's count, size, type, origin, or storage requirements. | Check the multipart limits or the Hook's directUpload descriptor and policy. |
Start with the Inbox item