Documentation
File Uploads
File uploads use a session-based flow: create a session, upload files to it, then submit your form with the session token. Uploads are linked to the submission automatically.
How it works
- Enable file uploads in your form's settings and configure allowed types and limits
-
Create an upload session by POSTing to
/f/YOUR_FORM_ID/sessions - Upload files to the session one at a time
-
Submit your form with the
_sessionfield to link uploads to the submission
1. Create a session
Sessions are valid for 1 hour. You must create one before uploading any files.
POST /f/YOUR_FORM_ID/sessions
// Response (201)
{
"session_id": "base64-encoded-token"
}
2. Upload files
Upload each file as multipart form data. Include the session token from the previous step.
POST /f/YOUR_FORM_ID/upload
Content-Type: multipart/form-data
Fields:
session_id: "token-from-step-1"
file: (binary)
// Response (201)
{
"id": "file-uuid",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"size": 12345,
"url": "/uploads/...?token=..."
}
3. Submit with session
Include the
_session
field alongside your normal form fields. Uploaded files are automatically attached to the submission.
POST /f/YOUR_FORM_ID
Content-Type: application/json
{
"name": "Jane",
"email": "[email protected]",
"_session": "token-from-step-1"
}
The
_session
field is a reserved field — it's extracted automatically and won't appear in your submission data.
JavaScript example
// 1. Create session
const sess = await fetch("/f/YOUR_FORM_ID/sessions", { method: "POST" });
const { session_id } = await sess.json();
// 2. Upload a file
const form = new FormData();
form.append("session_id", session_id);
form.append("file", fileInput.files[0]);
await fetch("/f/YOUR_FORM_ID/upload", { method: "POST", body: form });
// 3. Submit with session
await fetch("/f/YOUR_FORM_ID", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Jane",
email: "[email protected]",
_session: session_id,
}),
});
Defaults & limits
| Setting | Default |
|---|---|
| Max file size | 20 MB |
| Max files per submission | 5 (up to 20) |
| Allowed types | JPEG, PNG, GIF, PDF |
| Session lifetime | 1 hour |
| File URL validity | 90 days |
All settings are configurable per form. Allowed types also support WebP, WebM, and Office formats (DOCX, XLSX, PPTX). Files are validated against their content using magic bytes — renaming a file won't bypass type checks.
File URLs are token-signed but anyone with the URL can access the file. Do not use file uploads to collect sensitive documents such as government IDs, medical records, or financial statements.
Error responses
| Status | Meaning |
|---|---|
| 403 | Uploads disabled, form disabled, or domain not allowed |
| 422 | Invalid/expired session, file too large, type not allowed, or too many files |
| 429 | Rate limited or storage limit reached |