{"openapi":"3.1.0","info":{"title":"FormBox API","version":"0.1.0","description":"REST management API for sites, form hooks, inbox, and provisioning workflows. Agent form-building guidance: Do not blindly add every standard field. Choose fields from the form purpose, site context, and lead-quality needs. Minimum common fields are name and phone; usually add email or project details when useful. Ask one concise question when full address vs city/ZIP is not obvious. Add address/city/state/ZIP, service dropdowns, checkboxes, radios, dates, or file uploads only when the workflow benefits from them or the user asks. For residential/commercial forms, use property_type radios and show company_name above name only for Commercial. Whenever you build or reorder a form, send _formbox_field_order as a JSON array matching the visible business-field order so emails and dashboard details mirror the website. For website forms, preserve first-touch attribution through navigation and send page URL, landing/referrer, user agent, UTMs, and click IDs as metadata or _formbox_* reserved fields only, never as visible payload fields. FormBox preserves submitted business fields exactly; agents should normalize and validate common fields in the website form or same-origin server/function before posting to FormBox. If collected, address is one line with address street words capitalized, city/state/ZIP stay separate, state exactly two uppercase letters, ZIP digits-only five characters, and phone 10 US digits with dashes like 801-555-1234."},"servers":[{"url":"https://app.formbox.ai"}],"components":{"securitySchemes":{"FormBoxApiKey":{"type":"http","scheme":"bearer","bearerFormat":"FormBox API key"}},"schemas":{"SiteCreate":{"type":"object","properties":{"domain":{"type":"string"}},"required":["domain"],"additionalProperties":false},"SiteUpdate":{"type":"object","properties":{"domain":{"type":"string"},"timeZone":{"type":["string","null"]}},"required":[],"additionalProperties":false},"HookUpdate":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["active","paused"]},"notificationEmail":{"type":["string","null"]},"notificationCcEmails":{"type":"array","items":{"type":"string","format":"email"}},"allowedOrigins":{"type":"array","items":{"type":"string"}}},"required":[],"additionalProperties":false},"ApiKeyCreate":{"type":"object","properties":{"name":{"type":"string"},"preset":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}},"required":["name"],"additionalProperties":false},"UserCreate":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"password":{"type":"string"},"role":{"type":"string","enum":["owner","manager","viewer"]}},"required":["email","password"],"additionalProperties":false},"UserUpdate":{"type":"object","properties":{"role":{"type":"string","enum":["owner","manager","viewer"]}},"required":["role"],"additionalProperties":false},"ParsedSource":{"type":"object","properties":{"channel":{"type":"string"},"source":{"type":"string"},"medium":{"type":"string"},"campaign":{"type":"string"},"keyword":{"type":"string"},"clickId":{"type":"string"},"clickIdType":{"type":"string","enum":["gclid","gbraid","wbraid","fbclid","msclkid"]},"landingPage":{"type":"string"},"referrerDomain":{"type":"string"},"isPaid":{"type":"boolean"}},"required":["channel","isPaid"],"additionalProperties":false},"InboxMetadata":{"type":"object","description":"Attribution/system metadata. Payload remains business fields only.","properties":{"ipAddress":{"type":["string","null"]},"userAgent":{"type":["string","null"]},"referrer":{"type":["string","null"]},"pageUrl":{"type":["string","null"]},"utm":{"type":"object","additionalProperties":{"type":"string"}},"clickIds":{"type":"object","additionalProperties":{"type":"string"}},"parsedSource":{"$ref":"#/components/schemas/ParsedSource"}},"additionalProperties":true},"InboxItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"payload":{"type":"object","description":"Business/customer fields only; attribution keys are stripped."},"payloadFields":{"type":"array","items":{"$ref":"#/components/schemas/PayloadField"},"description":"Ordered display fields derived from payload plus metadata.fieldOrder. Use this when key order matters."},"metadata":{"$ref":"#/components/schemas/InboxMetadata"},"parsedSource":{"$ref":"#/components/schemas/ParsedSource"}},"required":["id","payload","payloadFields","metadata"]},"PayloadField":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"type":"string"}},"required":["key","label","value"]},"HookCreate":{"type":"object","description":"Do not blindly add every standard field. Choose fields from the form purpose, site context, and lead-quality needs. Minimum common fields are name and phone; usually add email or project details when useful. Ask one concise question when full address vs city/ZIP is not obvious. Add address/city/state/ZIP, service dropdowns, checkboxes, radios, dates, or file uploads only when the workflow benefits from them or the user asks. For residential/commercial forms, use property_type radios and show company_name above name only for Commercial. Whenever you build or reorder a form, send _formbox_field_order as a JSON array matching the visible business-field order so emails and dashboard details mirror the website. For website forms, preserve first-touch attribution through navigation and send page URL, landing/referrer, user agent, UTMs, and click IDs as metadata or _formbox_* reserved fields only, never as visible payload fields. FormBox preserves submitted business fields exactly; agents should normalize and validate common fields in the website form or same-origin server/function before posting to FormBox. If collected, address is one line with address street words capitalized, city/state/ZIP stay separate, state exactly two uppercase letters, ZIP digits-only five characters, and phone 10 US digits with dashes like 801-555-1234.","properties":{"siteId":{"type":"string","format":"uuid"},"name":{"type":"string"},"notificationEmail":{"type":["string","null"],"description":"Primary notification recipients, one or more comma-separated emails."},"notificationCcEmails":{"type":"array","items":{"type":"string","format":"email"},"description":"Optional CC recipients for hook notifications."},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Optional allowed origins. Leave empty to accept any origin."}},"required":["siteId","name"],"additionalProperties":false},"ProvisionSiteIntake":{"type":"object","description":"Do not blindly add every standard field. Choose fields from the form purpose, site context, and lead-quality needs. Minimum common fields are name and phone; usually add email or project details when useful. Ask one concise question when full address vs city/ZIP is not obvious. Add address/city/state/ZIP, service dropdowns, checkboxes, radios, dates, or file uploads only when the workflow benefits from them or the user asks. For residential/commercial forms, use property_type radios and show company_name above name only for Commercial. Whenever you build or reorder a form, send _formbox_field_order as a JSON array matching the visible business-field order so emails and dashboard details mirror the website. For website forms, preserve first-touch attribution through navigation and send page URL, landing/referrer, user agent, UTMs, and click IDs as metadata or _formbox_* reserved fields only, never as visible payload fields. FormBox preserves submitted business fields exactly; agents should normalize and validate common fields in the website form or same-origin server/function before posting to FormBox. If collected, address is one line with address street words capitalized, city/state/ZIP stay separate, state exactly two uppercase letters, ZIP digits-only five characters, and phone 10 US digits with dashes like 801-555-1234.","properties":{"domain":{"type":"string"},"forms":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"notificationEmail":{"type":["string","null"],"description":"Primary notification recipients, one or more comma-separated emails."},"notificationCcEmails":{"type":"array","items":{"type":"string","format":"email"}},"allowedOrigins":{"type":"array","items":{"type":"string"}}},"required":["name"]}}},"required":["domain","forms"],"additionalProperties":false},"EmailSettingsUpdate":{"type":"object","properties":{"globalBccEmails":{"type":"string","description":"Global BCC copy recipients, one per line or comma-separated."},"includeGlobalBccEmails":{"type":"boolean","description":"Send separate Global BCC copy emails."},"includeMetadataForGlobalBcc":{"type":"boolean","description":"Include lead-source metadata on Global BCC copy emails."},"includeReferenceInSubject":{"type":"boolean","description":"Add the per-organization submission reference suffix to the email subject."},"nextReferenceNumber":{"type":"integer","minimum":1,"default":1001,"description":"Set the next reference number for new submissions. Defaults to 1001 and cannot be lower than existing submission refs."},"templateFormat":{"type":"string","enum":["plain_text","table"]},"subjectTemplate":{"type":"string","description":"Subject template. Supports {{siteName}}, {{hookName}}, {{submitterName}}, {{submittedAt}}, {{siteDomain}}, {{siteRequestName}}, {{submissionReference}}, and {{referenceSuffix}}."},"senderDisplayTemplate":{"type":"string","description":"Visible From display-name template. The real sending address remains the verified notify address."}},"required":[],"additionalProperties":false}}},"paths":{"/api/v1/sites":{"get":{"summary":"List sites","security":[{"FormBoxApiKey":[]}],"responses":{"200":{"description":"Site list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}},"post":{"summary":"Create a site from a domain","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCreate"}}}},"responses":{"201":{"description":"Created site"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/sites/{siteId}":{"get":{"summary":"Get one site","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Site"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"patch":{"summary":"Update a site","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteUpdate"}}}},"responses":{"200":{"description":"Updated site"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"delete":{"summary":"Archive a site","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Archived site"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}}},"/api/v1/hooks":{"get":{"summary":"List form hooks","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"siteId","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Hook list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}},"post":{"summary":"Create a form hook linked to a site","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookCreate"}}}},"responses":{"201":{"description":"Created form hook"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/hooks/{hookId}":{"get":{"summary":"Get one hook","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"hookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Hook"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"patch":{"summary":"Update a hook","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"hookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookUpdate"}}}},"responses":{"200":{"description":"Updated hook"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"delete":{"summary":"Archive a hook","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"hookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Archived hook"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}}},"/api/v1/hooks/{hookId}/rotate-secret":{"post":{"summary":"Rotate a hook intake secret","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"hookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Rotated secret"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}}},"/api/v1/inbox":{"get":{"summary":"List recent inbox items","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"siteId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"hookId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"query","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Inbox list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/settings/email":{"get":{"summary":"Get organization email settings","security":[{"FormBoxApiKey":[]}],"responses":{"200":{"description":"Email settings"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}},"put":{"summary":"Update organization email settings","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSettingsUpdate"}}}},"responses":{"200":{"description":"Updated email settings"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/inbox/{inboxItemId}":{"get":{"summary":"Get one inbox item","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"inboxItemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Inbox item"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Inbox item not found"}}}},"/api/v1/inbox/{inboxItemId}/files":{"get":{"summary":"List files attached to one inbox item","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"inboxItemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Inbox file list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Inbox item not found"}}}},"/api/v1/inbox/{inboxItemId}/files/{fileId}/download":{"get":{"summary":"Create a short-lived signed download URL for one inbox item file","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"inboxItemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Signed download URL"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Inbox item or file not found"},"503":{"description":"Storage is not configured"}}}},"/api/v1/inbox/{inboxItemId}/deliveries":{"get":{"summary":"List delivery attempts for one inbox item","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"inboxItemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Inbox delivery list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Inbox item not found"}}}},"/api/v1/inbox/{inboxItemId}/deliveries/{deliveryId}/retry":{"post":{"summary":"Retry a failed or pending delivery","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"inboxItemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Delivery retry queued or executed"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Inbox item or delivery not found"},"409":{"description":"Delivery already sent"}}}},"/api/v1/settings/api-keys":{"get":{"summary":"List API keys","security":[{"FormBoxApiKey":[]}],"responses":{"200":{"description":"API key list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}},"post":{"summary":"Create API key","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"201":{"description":"Created API key"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/settings/api-keys/{apiKeyId}":{"patch":{"summary":"Revoke or reinstate API key","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"apiKeyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated API key"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"delete":{"summary":"Delete API key","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"apiKeyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted API key"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}}},"/api/v1/settings/users":{"get":{"summary":"List users","security":[{"FormBoxApiKey":[]}],"responses":{"200":{"description":"User list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}},"post":{"summary":"Create user","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}}},"responses":{"201":{"description":"Created user"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/settings/users/{memberId}":{"patch":{"summary":"Update user role","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"memberId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Updated user"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}},"delete":{"summary":"Remove user","security":[{"FormBoxApiKey":[]}],"parameters":[{"name":"memberId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed user"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."},"404":{"description":"Not found"}}}},"/api/v1/ops/deliveries":{"get":{"summary":"List pending, failed, and stuck deliveries","security":[{"FormBoxApiKey":[]}],"responses":{"200":{"description":"Delivery ops list"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}},"/api/v1/provision-site-intake":{"post":{"summary":"Create client, site, and one or more form hooks in one workflow","security":[{"FormBoxApiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionSiteIntake"}}}},"responses":{"201":{"description":"Provisioned intake assets and snippets"},"400":{"description":"Invalid input"},"401":{"description":"Missing, invalid, revoked, or underscoped API key."},"403":{"description":"Missing, invalid, revoked, or underscoped API key."}}}}}}