Forms Config API
Public endpoint (embedded forms)
| Method | Path | Description |
|---|---|---|
GET | /forms/config | Returns form schema for a site and form ID (domain-validated) |
OPTIONS | /forms/config | CORS preflight |
Used by the embedded form SDK to load form schema from the database. Request domain must be authorized for the site.
Dashboard API (authenticated)
Sites, forms, and integrations are managed via the analytics API (same Authorization: Bearer <key> as the dashboard). Use the Forms config page in the dashboard, or call these directly:
| Method | Path | Description |
|---|---|---|
GET | /analytics/sites | List all sites |
POST | /analytics/sites | Create site (body: { name?, site_key }) |
GET | /analytics/sites/:id | Get site with domains and forms |
PATCH | /analytics/sites/:id | Update site name (body: { name }) |
POST | /analytics/sites/:id/domains | Add domain (body: { domain }) |
DELETE | /analytics/sites/:id/domains/:domainId | Remove domain |
GET | /analytics/forms | List forms (optional ?site_id=) |
POST | /analytics/forms | Create form (body: { site_id, form_id, name?, form_json }) |
GET | /analytics/forms/:formId | Get form |
PATCH | /analytics/forms/:formId | Update form (body: { name?, form_json? }) |
DELETE | /analytics/forms/:formId | Delete form |
GET | /analytics/integrations | List integrations (API keys masked) |
POST | /analytics/integrations | Create integration (body: { name? }); returns api_key once |
DELETE | /analytics/integrations/:id | Revoke API key |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
siteKey | Yes | Site key (e.g. pk_live_xxx) |
formId | Yes | Form ID (e.g. enquiry_form) |
Domain Validation
The server reads Origin or Referer and extracts the hostname. The hostname must exist in SiteDomains for the site identified by siteKey. If not, the response is 403 Forbidden.
Debugging 403 (server logs)
On denial, the worker logs domain_validation_denied (level warn) with:
| Field | Meaning |
|---|---|
reason | missing_origin_referer — no usable Origin/Referer; site_not_found — invalid siteKey; hostname_not_in_site_domains — host not in SiteDomains; database_error — D1 error; empty_site_key — should not occur for this route |
request_hostname | Hostname derived from Origin/Referer when present |
route | /forms/config |
Use Cloudflare Workers logs or wrangler tail to inspect. The JSON error body stays generic for clients.
Response
200 OK
{
"formId": "enquiry_form",
"form": {
"fields": [
{ "name": "ContactName", "type": "text", "label": "Name" },
{ "name": "ContactPhone", "type": "tel", "label": "Phone" }
]
}
}400 Bad Request — Missing siteKey or formId
403 Forbidden — Domain not authorized for this site
404 Not Found — Site or form not found
500 — Database error