> ## Documentation Index
> Fetch the complete documentation index at: https://cactal.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Forms

> Native website forms: post to /_cactal/forms/{name} from any page, every submission is stored in the Forms tab and emailed to each form's recipients, spam is filtered invisibly, and the API exposes submissions and recipients.

Every Cactal website can receive form submissions without any backend setup. A page posts to the site's own endpoint, Cactal stores the submission, emails the recipients, and shows it in the **Forms** tab of the studio.

## How a form works

A form is ordinary HTML whose action is a literal path on the same origin:

```html theme={null}
<form method="post" action="/_cactal/forms/contact">
  <label>Name <input name="name" autocomplete="name" required /></label>
  <label>Email <input name="email" type="email" autocomplete="email" required /></label>
  <label>Message <textarea name="message" required></textarea></label>
  <button type="submit">Send</button>
</form>
```

* `{name}` is the form name: lowercase letters, digits, and hyphens (`contact`, `quote-request`). The build scans the source for `/_cactal/forms/{name}` literals; a name that is not in the deployed source is rejected with `unknown_form`, so write the path as a literal string rather than computing it. A site can have up to 20 forms.
* The endpoint accepts `application/x-www-form-urlencoded`, `multipart/form-data` (file parts are rejected), and `application/json`. Repeated field names become arrays.
* `_redirect` is the only reserved field: a same-site path to redirect to after a successful browser submission.
* The first email field (`type="email"` or a field named like `email`) becomes the submitter address and the reply-to of the notification; the first `name`, `full_name`, or `first_name` field becomes the submitter name.
* Limits: 50 fields, 10 KB per value, 64 KB per submission.

### Responses

The endpoint answers according to how it was called:

| Caller | Success | Failure |
| - | - | - |
| Browser navigation (a plain form post) | `303` to `_redirect`, or back to the page with `?submitted={name}` | `303` back to the page with `?form-error={code}` |
| `fetch` with `Accept: application/json` | `200 { "ok": true, "id": "..." }` | `4xx { "ok": false, "error": { "code", "message", "fields"? } }` |

Error codes: `validation` (400, with per-field `fields`), `unknown_form` (404), `payload_too_large` (413), `rate_limited` (429, with `Retry-After`), `limit_reached` (403, the Free plan monthly allowance is used up), `suspended` (451), `unavailable` (503).

Submissions from the draft preview host are accepted and stored as test submissions (`source: "draft"`); they never count toward limits and appear under the **Test** filter.

To also send submissions to a CRM or another service, add a `form` [server function](https://cactal.ai/docs/concepts/server-functions.md). It runs after spam screening for every accepted submission and never changes what the visitor sees.

## Notifications

Every accepted submission is emailed from `Your site via Cactal <forms@cactalforms.com>` with the submitter as reply-to, so replying from any mail client reaches the visitor. Each form has its own list of recipients:

* A new form starts by notifying the organization owners. Removing every recipient stops the emails; submissions still land in the **Forms** tab, and `POST /v1/websiteSourceCode/head/check` returns a note for each such form unless the website has a `form` server function.
* An address that belongs to an organization member or website editor receives submissions immediately.
* Any other address must click a confirmation link first (valid for 7 days). Every email carries a link the recipient can use to stop future submissions.
* An address that bounces permanently or complains is marked failing and stops receiving mail; owners are notified. A temporary bounce, such as a full mailbox, does not stop it.
* After 10 immediate emails in an hour, further submissions to the site are batched into one hourly digest per recipient, so a busy form or a bot that slips past the filters never floods an inbox. The Forms tab always shows every submission as it arrives.

## Spam

Spam filtering is invisible to visitors: there is no CAPTCHA. Rate limits, a page-load signal, duplicate detection, and link density run on every submission. Every Cactal page sets the page-load signal in the visitor's browser, so a published submission without it was sent by a script, not from the website, and goes straight to the **Spam** folder; submissions from framed pages and the draft preview, where browsers block the signal, are exempt. A classifier moves the remaining spam to **Spam**, with a second model reviewing the submissions it is unsure about. A submission is emailed only after the classifier has screened it: if screening is briefly unavailable, the submission still appears in the Forms tab right away and its email waits for the next hourly retry, and one that still cannot be screened is announced in the hourly digest without its content. Spam never triggers an email, stays for 30 days, and can be restored with **Not spam**, which sends the missed notification.

## Plans

Free websites accept 50 published submissions per month, with warnings to owners at 80 percent and at the limit; further submissions receive `limit_reached` until the month resets. Pro websites are unlimited. See [Plans and limits](https://cactal.ai/docs/platform/plans-and-limits.md).

## API

* `GET /v1/websites/{websiteId}/forms` lists forms with counts, on-site status, recipients, and monthly usage. A form is listed as soon as the draft or published build contains it, so recipients can be set before the first submission.
* `GET /v1/websites/{websiteId}/forms/submissions` pages submissions newest first; filter with `form`, `status` (`inbox` or `spam`), and `source` (`published` or `draft`).
* `PATCH` and `DELETE /v1/websites/{websiteId}/forms/submissions/{submissionId}` mark spam or not spam, and delete.
* `POST /v1/websites/{websiteId}/forms/{formName}/recipients` and `DELETE .../recipients/{recipientId}` change who a form emails; `POST /v1/websites/{websiteId}/forms/recipients/{recipientId}/resend` reissues a confirmation.

Reading and triaging submissions needs the `websiteForms.view` capability (content editors and above); recipients need `websiteForms.manage` (full editors and above). Submission data is personal information: never render it on the public website.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.