Forms that ship in minutes.
Submissions that just work.
Build forms in the dashboard, share a public link, collect typed responses, and attach private files — Sawala Cloud handles validation, storage, and rate limits.
Drag, drop, ship.
No backend code.
Compose forms from a typed field library — text, number, date, select, multiselect, boolean, media, richtext, and more. Reorder with drag-and-drop. Save versions automatically. Share the public link the moment a form is published.
- ✓Typed fields with built-in validation (required, pattern, min/max, enum).
- ✓Per-field options for selects, file accept rules, and richtext toolbars.
- ✓Form-level settings: success message, redirect URL, max submissions per day.
form definition (stored as JSON)
{
"slug": "contact",
"name": "Contact form",
"fields": [
{ "name": "fullName", "type": "text", "required": true },
{ "name": "email", "type": "text", "required": true,
"validation": { "pattern": "^[^@]+@[^@]+$" } },
{ "name": "topic", "type": "select",
"options": { "enum": ["sales", "support", "other"] } },
{ "name": "message", "type": "richtext", "required": true },
{ "name": "attachment","type": "media",
"options": { "accept": ["pdf", "image"], "maxSize": 10485760 } }
],
"settings": {
"success": { "mode": "message", "message": "Thanks — we'll be in touch." }
}
}One endpoint.
Every channel.
Each form gets a public submission endpoint authenticated by an org API key, rate-limited per (key, formSlug), and validated against the same Zod schema the dashboard uses. Submissions land in a typed inbox the team can review, verify, or reject.
publishable keyBrowser-safe pk_live_… key copied from the dashboard’s API Keys page. Scope is verified against an allowedOrigins list.
typed inboxEach submission carries a status (received / verified / rejected), the form version it was filed against, IP, and user-agent.
POST /public/formulir/forms/contact/submit
x-api-key: pk_live_…
content-type: application/json
{ "fullName": "Ayu", "email": "ayu@example.com",
"topic": "sales", "message": "<p>Demo please.</p>" }
→ 202 Accepted
{ "id": "sub_01H…", "status": "received" }Attach files.
Keep them private.
File fields on public forms mint per-(form, submission) presigned upload tickets to a private Berkasna bucket. Submitters upload directly from the browser. Files are never exposed via a public URL — only the dashboard’s signed-download API can retrieve them.
- 1Submit the form. Sawala Cloud returns scoped upload tickets for each file field.
- 2Browser PUTs each file directly to private R2 — no proxy through your origin.
- 3Dashboard reviewers fetch attachments via signed-download URLs that expire.
scoped-ticket upload flow
# 1. Submit form, request upload slot for file fields
POST /public/formulir/forms/contact/submit
→ { id, status: "received",
uploadTickets: [
{ fieldName: "attachment",
uploadUrl: "https://upload.sawala.cloud/…",
expiresAt: "…" }
] }
# 2. Browser PUTs the file straight to private R2
PUT {uploadUrl} (binary body)
→ 200 OK
# 3. File is private — only signed-download API can retrieve itEdit safely.
Submissions stay anchored.
Every form save creates an immutable form_versions snapshot. Each submission is tied to the version it was filed against, so changing a form schema never silently invalidates old responses. The inbox surfaces version, status, IP, user-agent, and the full typed payload.
receivedNew submission, awaiting review by a team member.
verifiedReviewer confirmed the submission is valid. Triggers any configured downstream automations.
rejectedReviewer flagged the submission. Attached files become eligible for cleanup.
submissions inbox
sub_01HX…v3received2 minsub_01HW…v3verified1 hrsub_01HV…v2rejected1 dsub_01HU…v2verified1 dMore than just forms.
Everything you need to run real form workflows in production.
Multi-locale
Localize labels, placeholders, and validation messages per locale.
Edge-fast
Submission API runs on Cloudflare Workers — single-digit ms validation, no cold starts.
Rate limiting
Per-(key, formSlug) limits applied at the gateway block abusive bursts.
Embed on the roadmap
React component and <iframe> modes coming soon — drop a form into any site with a publishable key.
Submission analytics
Volume, completion rate, and rejection reasons surfaced in the dashboard.
OpenAPI docs
Built-in Scalar API reference at /dashboard/formulir/api-docs — always in sync with your deployed API.