Insane Forms

File uploads

Send files through the endpoint, or upload large ones directly.

There are two ways to attach files to a Submission. A plain form sends them in the request, up to 4.5 MB in total. For larger files, upload each one directly to storage first and then name it in a JSON Submission.

Every file is stored privately in your Workspace's Region and is only ever shown through short-lived signed links.

Through the endpoint

Add enctype="multipart/form-data" and a file input:

Limits per Submission:

  • 4.5 MB for the whole request, files included.
  • 10 files.
  • Each file within your Plan's per-file cap (25 MB on the beta Plan, which only matters for direct uploads, since the request limit is lower).

Past the request limit or the file count the answer is 413 payload_too_large. A single file over the Plan's cap gets 413 file_too_large. A file input left empty sends no file and isn't an error.

If you test against a server with no file storage configured, a request that carries files answers 501 uploads_unavailable. A request without files still works.

Direct uploads

Use these for files over the 4.5 MB request limit. The request for upload URLs takes the same Submit Key, Allowed Origins and rate-limit checks as a submit. It doesn't run Turnstile: the Submission that names the files does.

1. Ask for upload URLs

Send up to 10 files. Each needs a name, a type (its content type) and its size in bytes.

The answer has one upload per file:

A file over the Plan's per-file cap gets 413 file_too_large here, and a request that would fill the Workspace's storage gets 429 plan_limit_reached. A body that isn't {"files": [...]} in that shape gets 400 invalid_body.

2. Upload each file

PUT the file to its url with the headers you were given. The URL only accepts the content type it was issued for, and it expires after an hour.

3. Send the Submission

Send JSON and put {"$upload": "<uploadId>"} where the file goes. Use an array for several files in one field. The reference has to be the field's whole value: one nested inside another object isn't read.

An upload that has expired, belongs to another Form or never received its file gets 400 invalid_upload. Uploads that never join a Submission are deleted after they expire.

Storage

Files count towards your Plan's storage (1 GB on the beta Plan). When it's full, the endpoint answers 429 plan_limit_reached. Files of Spam Submissions aren't stored, and files are deleted with their Submission.

On this page