Pro - a Free form rejects a multipart submission with attachments.
multipart/form-data POST to the same /submit endpoint you already use —
no separate upload endpoint, no JavaScript required.
Adding a file input
Plain HTML (no JS)
Addenctype="multipart/form-data" to the form and a file input:
React / Vue / Astro / any JS
Build aFormData and post it - don’t set Content-Type yourself; the browser adds the
correct multipart boundary:
Limits
A file over the per-file limit, or a submission with too many files, is rejected outright —
nothing is silently dropped or truncated:
What happens to an uploaded file
- The file uploads to storage (Cloudflare R2) and is held privately while it’s scanned. Nothing is released before scanning completes - this is fail-closed: if scanning can’t confirm a file is clean, it is not made available.
- If the file passes, it becomes downloadable from your dashboard - open the submission and download the file. Downloads are owner-scoped: only the account that owns the form can fetch it, over a short-lived authenticated link. Files are never publicly reachable by URL.
- If the file fails scanning (or is an unsafe/unrecognized type), it’s blocked and never delivered to you.
Free vs. Pro
Free forms do not accept file uploads. Submitting a multipart request with attachments against a Free-plan form is rejected with:Zero-config
No dashboard toggle to flip - any Pro-plan form acceptsmultipart/form-data submissions
with file fields as soon as you add a <input type="file"> (or append files to a
FormData) in your form.