Skip to Content
ExamplesFile Upload

File Upload

Uploading a file to Formtorch takes two steps: the browser asks for an upload policy, POSTs the file straight to storage with it, then submits the form referencing the uploaded file by ID.

Uploads must be enabled for the form, and are available on Starter and Pro. See File Uploads for limits and accepted types.

Request an upload policy

upload.js
const file = document.querySelector("#attachment").files[0]; const intentRes = await fetch("https://formtorch.com/api/uploads/intent", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ formId: "YOUR_FORM_ID", files: [{ name: file.name, mimeType: file.type, size: file.size }], // turnstileToken: "...", // only if the form has captcha configured }), }); const { files } = await intentRes.json(); // [{ fileId, uploadUrl, fields }]

POST the file to storage

Send multipart/form-data built from the returned fields. This is a POST with a policy, not a raw PUT of the file body, and the file field must be appended last.

upload.js
const s3Form = new FormData(); for (const [key, value] of Object.entries(files[0].fields)) { s3Form.append(key, value); } s3Form.append("file", file); // must be appended last await fetch(files[0].uploadUrl, { method: "POST", body: s3Form });

Submit the form with _file_ids

_file_ids maps your form’s field names to the file IDs from step 1. A field can take a single ID or an array of them.

upload.js
const formData = new FormData(); formData.append("name", "John Doe"); formData.append("email", "john@example.com"); formData.append("_file_ids", JSON.stringify({ attachment: files[0].fileId })); await fetch("https://formtorch.com/f/YOUR_FORM_ID", { method: "POST", body: formData, });

Multiple files

Request a policy for every file in one intent call, upload each with its own policy, then pass an array of IDs for that field:

formData.append( "_file_ids", JSON.stringify({ attachments: files.map((f) => f.fileId) }) );

Field names in _file_ids must match your form’s field names, cannot start with _, and are capped at 100 characters.

Limits and types

LimitStarterPro
Max size per file25 MiB25 MiB
Max files per submission1010
Max total size per submission100 MiB100 MiB
Total storage1 GB5 GB

Accepted types are an allowlist: PDF, DOC, DOCX, XLS, XLSX, PNG, JPEG, WebP, GIF, text/plain, and CSV. The accept attribute on the input is a client-side hint only; Formtorch verifies the type against the file’s actual bytes when it attaches the file.

Retrieving files

Notification emails include a signed download link per file, webhook and Zapier payloads include a downloadUrl, and the REST API exposes GET /v1/submissions/:submissionId/files. See File Uploads for details.

Last updated on