Skip to content
SiteOS

Documentation

Forms

Connect your website forms to a shared inbox with versioned definitions, contacts, notifications, Mailchimp forwarding and spam controls.

Last updated

SiteOS Forms receives data from forms you build in your website. Your site owns the fields, validation and design; SiteOS stores accepted submissions and gives your team an inbox, contacts and notifications.

Connect a form

Define the fields and validation in your website, publish the form definition to the selected project environment and send submissions from a server route. The API key belongs to that environment and must stay on the server, never in a browser bundle. A static site needs a serverless function or another server endpoint for this step.

In SiteOS, Settings → Website connection walks through the same steps: install the SDK, add the API key, publish your forms and verify a submission. Create and revoke API keys there; a new key is shown once as a ready SITEOS_FORMS_API_KEY= line. Set up with AI copies a prompt for Codex or Claude that does every step in your repository. Settings also links to publishing, Mailchimp, contact fields, spam protection and notifications, each with its current state.

Use your Zod schemas

On a Node.js 22.12+ server with Zod 4 schemas, install @siteoshq/forms and keep your existing schemas, form library and build. Register each form with createForm in a server-only siteos.forms.ts that exports the forms as its default array; the fields object describes how answers appear in the inbox, while validation stays in Zod. Browser components import only the shared schemas.

Check and publish the forms with CLI 2.45.0 or later before deploying the updated website:

siteos forms definition check --source siteos.forms.ts --json
siteos forms deploy --source siteos.forms.ts --json

Your server validates answers with the same schema and sends the parsed output with the API key, stored as SITEOS_FORMS_API_KEY. Publication uses a separate key, SITEOS_FORMS_DEPLOYMENT_KEY, which belongs only to the person or trusted CI that publishes forms, never to the website runtime. An administrator issues it with siteos forms deployment-key issue --environment <slug> --install, which writes it to your ignored .env without printing it. Other validators and server languages can use the Forms HTTP API instead of the package.

Versions and verification

Each published definition is saved as a version. Your release can publish all managed forms together, and each submission names the version it was built for, so a deployed page keeps using its own field rules. The agent can inspect an existing form and adapt it to SiteOS instead of creating a second form.

Definition publication and a successful website build are only part of setup. Complete a clearly identified test submission and verify that it reaches the expected form and environment. Website connection can wait for a new submission to a selected form version and link to it; it never sends a test itself.

SiteOS confirms a submission once it is stored durably. It then appears in the inbox and triggers notifications; if the application is temporarily unavailable, that step is delayed rather than lost.

Work with submissions

Overview shows whether forms are receiving, unread counts, the latest submissions and your forms. Inbox lists submissions across all forms in the environment, with Archived, Spam and All folders and filters for form, text, dates and test responses. A submission opens in a side sheet; opening it marks it read for the whole team, and you can mark it unread again.

Select submissions on the current page to mark them read or unread, archive them, move them to spam or classify them as tests, with Undo. Test submissions stay out of normal unread counts. Export CSV downloads every submission matching the current filters, up to 5,000 rows; a larger export asks you to narrow the filters instead of truncating the file.

Contacts and spam protection

Contacts brings together senders identified from a form's email field. When a form has several email fields, choose the one that identifies the sender. Contact history links related submissions, and contacts can be exported as CSV or XLSX. An email address in a form submission is not permission to send marketing messages.

Spam & block sender blocks that exact address for future submissions and moves its existing submissions in this environment to Spam. Moving a submission to Spam on its own does not block the sender. Under Contacts → Blocked, owners and administrators can also turn on Block disposable emails to reject new submissions from known temporary-email domains. It is off by default because some temporary addresses are legitimate.

Notifications

Open a form's Notifications to send new submissions to a Slack channel or Telegram chat connected in Integrations. Choose up to ten answer fields to include; password and secret fields are excluded. Owners and administrators manage these settings. Notifications cover new submissions only; earlier submissions are not sent.

Forward contacts to Mailchimp

Connect Mailchimp once for the organization in Services (see Integrations), then open a form's Integrations tab. Owners and administrators manage it. Every submission is saved in Forms first; then the contact goes to the audience you choose.

Turn on Forward new submissions, choose the Audience and select the email field under Fields. Required Mailchimp fields are always listed; Map a field adds an optional one. Only mapped answers are sent, and empty answers keep existing Mailchimp values. Tags are added to every contact from the form. Save with Save integration.

Under Subscription, choose how new contacts join the audience:

  • Contact only: added without email marketing consent. This is the default.
  • Confirm by email: Mailchimp sends a double opt-in email when the selected consent checkbox is ticked.
  • Subscribe with checkbox: subscribed only when the consent checkbox is ticked.
  • Subscribe on submission: new contacts subscribe when the form is submitted, with no separate checkbox or confirmation email. Choose it only when subscribing is the form's purpose.

Existing contacts keep their status, including previous opt-outs. Forwarding covers new submissions only; earlier submissions are not sent. Marking a submission as spam or a test, archiving the form or disconnecting Mailchimp stops pending deliveries.

Recent deliveries lists each outcome with its reason. Retry delivery sends a failed delivery again for up to seven days. In the Inbox, a submission that did not reach Mailchimp shows Not sent to Mailchimp; its details give the reason, and Review and retry opens the form's Integrations tab. All forms shows where each form sends its submissions in Sends to.

Archive or delete a form

Archive a form to stop new submissions while keeping its versions and submissions, and restore it when needed. Permanent deletion removes the definition, versions and submissions after you confirm the exact form key; that key cannot be reused. Contacts and sender blocks remain. A form missing from your website's list of managed forms is never deleted automatically.

Keep the website and definition aligned

When fields change, update validation and publish the definition again before relying on the new shape. Use Projects and environments to test changes without adding development responses to the production inbox.

$siteos Connect the existing contact form in this repository to SiteOS Forms.
Preserve its design, validate the fields, and verify a labeled test submission.

Through MCP, your agent can read forms, submissions, contacts and protection settings, plus a form's Mailchimp forwarding settings and recent deliveries with siteos_forms_get_integration and siteos_forms_list_deliveries; submissions can contain personal data. Publication, credentials, status changes and forwarding changes use the CLI; siteos forms integrations shows, saves, disables and retries forwarding for an owner or administrator. See AI & MCP for plugin installation, sign-in and project setup.

Use an Analytics event to measure a successful submission. A submit-button click alone does not prove that the message was accepted. To check the form journey on a schedule without creating real submissions, use a Pulse browser check that mocks delivery.