Tools

Forms

Contact forms and custom forms with schema-on-write. No form builder needed — just submit data and the schema builds itself.


Two types of forms#

Contact Form

Pre-built with email, name, and message fields. Renders as a widget on your page.

Custom Forms

Accept any JSON payload. Schema auto-infers from submissions. Each form gets a unique key.

Contact form widget#

The built-in contact form renders as a Shadow DOM widget with email, name, and message fields.

<!-- Renders a contact form with email, name, message --><div data-os-widget="form" data-os-form="contact"></div>
Property Type Description
heading stringWidget heading text (default: "Get in touch")
description stringSubtitle below the heading
buttonText stringSubmit button label (default: "Send")
successMessage stringMessage shown after submission (default: "Thanks for reaching out!")
fields string[]Visible fields: "email", "name?", "message?"

Custom forms#

Custom forms use a schema-on-write approach: you don’t define fields upfront. The schema is inferred from the first submission and extended with each new one.

Form keys#

Every custom form gets a unique key (e.g., frm_abc123). Use this key for API submissions and SDK calls.

Public form endpoint#

Submit to any form using its form key. No authentication required. Accepts JSON, form-urlencoded, or multipart data.

curl
# JSONcurl -X POST https://api.operatorstack.dev/v1/f/frm_abc123 \  -H "Content-Type: application/json" \  -d '{"email": "user@example.com", "company": "Acme Inc"}' # Form-urlencodedcurl -X POST https://api.operatorstack.dev/v1/f/frm_abc123 \  -d "email=user@example.com&company=Acme+Inc"

Reserved fields#

Fields prefixed with an underscore are metadata — they’re processed but not stored in the submission data.

Property Type Description
_redirect stringURL to redirect to after submission (returns 303)
_subject stringEmail notification subject line
_formName stringDisplay name for the form in notifications

SDK usage#

app.js
// Submit to a custom formawait window.OperatorStack.submitForm('frm_abc123', {  email: 'user@example.com',  company: 'Acme Inc',  budget: '$10k-50k'}) // Send a contact messageawait window.OperatorStack.sendContactMessage({  email: 'user@example.com',  name: 'Jane Doe',  message: 'I have a question about pricing.'})

Plain HTML form#

You can submit to custom forms using a standard HTML form — no JavaScript needed. Add a _redirect hidden field to redirect after submission.

form.html
<form action="https://api.operatorstack.dev/v1/f/frm_abc123" method="POST">  <input type="email" name="email" placeholder="Email" required />  <input type="text" name="company" placeholder="Company" />  <textarea name="feedback" placeholder="Your feedback"></textarea>  <input type="hidden" name="_redirect" value="https://yoursite.com/thanks" />  <button type="submit">Submit</button></form>

API endpoints#

POST/v1/f/{form_key}Public
Submit data to a custom form. Accepts JSON, form-urlencoded, or multipart. No auth required.
POST/v1/projects/{projectKey}/contactPublic
Submit a contact form message.

Submission management#

Every submission has a status that helps you triage incoming data:

  • New — fresh submission, not yet reviewed
  • Read — you’ve seen it
  • Archived — processed and filed away

Filter submissions by status in the dashboard. Status changes are logged to the audit trail.

CSV export#

Export submissions to CSV from the dashboard. Columns are auto-generated from the form schema with a submitted_at timestamp. Exports include UTF-8 BOM for Excel compatibility and are capped at 10,000 rows.

Dashboard features#

  • Auto-generated table columns from submission schema
  • Form configuration panel with heading, description, and button text
  • Submission count and recent activity
  • Status management (new, read, archived) with filtering
  • CSV export of submissions
  • Setup tab with copyable code snippets for 4 integration patterns: HTML form, JavaScript SDK, HTTP API, and AI prompt