File Upload Chunked upload flow, web upload (URL import), status polling, and upload management.
Overview
Fast.io supports three upload flows:
- Small files (< 4 MB) — Single-request upload. Send the file as a multipart chunk in the session creation request. Optionally auto-add to storage in the same call.
- Large files (≥ 4 MB) — Chunked upload. Create a session, upload chunks (up to 3 in parallel), trigger assembly, poll until stored.
- Web upload (URL import) — Import files from any HTTP/HTTPS URL. The server downloads and uploads the file asynchronously.
Both direct upload flows produce an upload session with a unique id (OpaqueId). Once the upload reaches stored status, the file is ready to use.
Upload Constraints
| Constraint | Value |
|---|---|
| Single-call upload max size | 4 MB (4,194,304 bytes) |
| Chunk size | Plan-dependent (query /upload/limits/ for exact values) |
| Last chunk | May be smaller than the plan chunk size |
| Max parallel chunk uploads per session | 3 |
| Max undersized chunks per session | 1 (the final chunk only) |
| Chunk ordering | 1-based (first chunk is order=1) |
| Supported hash algorithms | md5, sha1, sha256, sha384 |
relative_path max length | 8192 characters |
relative_path | Omit entirely if empty — do NOT send as empty string |
creator format | 1–150 chars, alphanumeric and hyphens only (/^[a-zA-Z0-9\-]+$/) |
| Max file size | Plan-dependent (up to 40 GB) |
| Max concurrent sessions | Plan-dependent (150 for Free, 7500 for Pro/Business) |
| Long-poll max wait | 590 seconds |
Upload Status Values
| Status | Meaning | Action |
|---|---|---|
ready | Session created, awaiting chunks | Upload chunks |
uploading | Chunks being received | Continue uploading |
assemble | Assembly queued | Keep polling |
assembling | Assembly in progress | Keep polling |
complete | Assembly done, awaiting storage import | Keep polling (or use addfile if not auto-adding) |
store | Storage import queued | Keep polling |
storing | Being imported to storage | Keep polling |
stored | Fully complete — file assembled and in storage | Done. new_file_id available. |
assembly_failed | Assembly failed | Handle error |
store_failed | Storage import failed | Handle error |
Terminal states: stored, assembly_failed, store_failed. Stop polling when you reach one of these.
Workflow: Small File Upload (< 4 MB)
A single request creates the session and uploads the file. Optionally auto-adds to storage.
Step 1: Upload in one request
Create upload session and send file data in a single request.
Content-Type: multipart/form-data
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | File name including extension (1–255 chars) |
| size | integer | Yes | File size in bytes (must match actual file) |
| chunk | file | Yes | The file binary data (multipart field) |
| action | string | No | "create" for new file, "update" for file replacement |
| instance_id | string | Required if action=create | Workspace or share profile ID (20-digit numeric) |
| file_id | string | Required if action=update | OpaqueId of the existing file to replace |
| folder_id | string | No | Target folder OpaqueId or "root" for storage root |
| hash | string | No | Hash of the full file. Must be provided with hash_algo. |
| hash_algo | string | No | Hash algorithm: "md5", "sha1", "sha256", or "sha384" |
| relative_path | string | No | For folder uploads, relative path for auto folder creation (max 8192 chars). Omit entirely if not applicable. |
| org | string | No | Organization ID for billing limit resolution (only used when no action is specified) |
| creator | string | No | Client identifier string (1–150 chars, alphanumeric and hyphens only) |
Example (small file with auto-add to workspace)
curl -X POST "https://api.fast.io/current/upload/" \
-H "Authorization: Bearer {jwt_token}" \
-F "name=notes.txt" \
-F "size=1024" \
-F "action=create" \
-F "instance_id=12345678901234567890" \
-F "folder_id=root" \
-F "chunk=@notes.txt"
Response (201 Created)
{
"result": "yes",
"response": {
"id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"creator": "my-web-client",
"new_file_id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4"
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| result | string | "yes" on success |
| response.id | string | Upload session OpaqueId |
| response.creator | string | Echoed back only if creator was provided in the request |
| response.new_file_id | string | OpaqueId of the created storage node. Only present for single-call uploads with an upload target (instance_id). |
When instance_id and folder_id are provided, the file is automatically added to storage. No separate polling or addfile step is needed.
Response (without instance_id, 201 Created)
{
"result": "yes",
"response": {
"id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123"
},
"current_api_version": "1.0"
}
Without a target, only the upload session id is returned. Use addfile to place the file in storage after the upload completes.
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | "The size was not supplied." |
APP_ERROR_INPUT_INVALID | 400 | "The file name is not valid." |
APP_ERROR_INPUT_INVALID | 400 | "Invalid share or workspace instance ID." |
APP_NOT_ACCEPTABLE | 406 | "This file type is not allowed for upload on your plan." |
APP_FEATURE_LIMIT | 403 | "The file size exceeds single call upload, use chunks." |
APP_FEATURE_LIMIT | 403 | "You have created too many upload sessions..." |
APP_FEATURE_LIMIT | 403 | "The size is too large for the account plan." |
APP_FEATURE_LIMIT | 403 | "The total size of all active upload sessions exceeds the limit." |
APP_ERROR_INPUT_INVALID | 400 | "The hash algorithm provided is not valid." |
APP_ERROR_INPUT_INVALID | 400 | "The hash provided is not valid." |
APP_ERROR_INPUT_INVALID | 400 | "The hash algorithm was provided but not the hash." |
APP_NOT_ACCEPTED | 406 | "We were unable to create the upload session..." |
Workflow: Large File Upload (Chunked)
Step 1: Create upload session
Create a new upload session for a large file.
Content-Type: application/x-www-form-urlencoded
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | File name including extension (1–255 chars) |
| size | integer | Yes | Total file size in bytes |
| action | string | Yes | "create" for new file, "update" for file replacement |
| instance_id | string | Required if action=create | Workspace or share profile ID (20-digit numeric) for auto-add to storage after assembly |
| file_id | string | Required if action=update | OpaqueId of existing file to replace |
| folder_id | string | No | Target folder OpaqueId or "root" for storage root |
| hash | string | No | SHA-256 hex hash of the full file for integrity verification. Must be provided with hash_algo. |
| hash_algo | string | No | Hash algorithm: "md5", "sha1", "sha256", or "sha384" |
| relative_path | string | No | For folder uploads, relative path for auto folder creation (max 8192 chars). Omit entirely if not applicable. |
| org | string | No | Organization ID for billing limit resolution (only used when no action is specified) |
| creator | string | No | Client identifier string (1–150 chars, alphanumeric and hyphens only) |
Example
curl -X POST "https://api.fast.io/current/upload/" \
-H "Authorization: Bearer {jwt_token}" \
-d "name=annual-report.pdf" \
-d "size=52428800" \
-d "action=create" \
-d "instance_id=12345678901234567890" \
-d "hash_algo=sha256" \
-d "hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
Response (201 Created)
{
"result": "yes",
"response": {
"id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123"
},
"current_api_version": "1.0"
}
Step 2: Upload chunks
Upload a single chunk of file data.
Content-Type: multipart/form-data
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {upload_id} | string | Yes | The upload session ID from Step 1 |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| order | integer | Yes | 1-based chunk number (first chunk = 1). Must not exceed plan's chunk limit. |
| size | integer | Yes | Size of this chunk in bytes. Must match the actual uploaded file size. |
| hash | string | No | Hash of this chunk. Must be provided with hash_algo. |
| hash_algo | string | No | Hash algorithm: "md5", "sha1", "sha256", or "sha384" |
Request body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
| chunk | file | Yes | Binary chunk data |
Upload up to 3 chunks in parallel. The last chunk may be smaller. Only 1 undersized chunk is allowed per session.
When all chunks have been uploaded (total bytes equal the declared file size), auto-finalization triggers automatically. You can still call the complete endpoint explicitly.
Example
curl -X POST "https://api.fast.io/current/upload/u1abc-defgh-ijklm-nopqr-stuvw-xyz123/chunk/?order=1&size=5242880&hash_algo=sha256&hash=abc123def456..." \
-H "Authorization: Bearer {jwt_token}" \
-F "chunk=@chunk_001.bin"
Response (202 Accepted)
{
"result": "yes",
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | "The session id provided is not valid." |
APP_NOT_ACCEPTABLE | 406 | "The session id provided is not in a valid state to accept a chunk." |
APP_ERROR_INPUT_INVALID | 400 | "No order supplied" |
APP_ERROR_INPUT_INVALID | 400 | "The order provided for this chunk is not valid..." |
APP_ERROR_INPUT_INVALID | 400 | "The size was not supplied." |
APP_FEATURE_LIMIT | 403 | "The size is too large for the account plan." |
APP_FEATURE_LIMIT | 403 | "The size is too small for the account plan." |
APP_FEATURE_LIMIT | 403 | "You have exceeded the maximum number of chunks..." |
APP_FEATURE_LIMIT | 403 | "The combined chunk size exceeds the size for this session." |
APP_ERROR_INPUT_INVALID | 400 | "The upload chunk failed or was the wrong size..." |
APP_ERROR_INPUT_INVALID | 400 | "The chunk failed to hash properly..." |
APP_INTERNAL_ERROR | 500 | "The chunk failed to be stored..." |
Step 3: Trigger assembly
Trigger asynchronous assembly of all uploaded chunks.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {upload_id} | string | Yes | The upload session ID |
Query parameters (optional)
| Parameter | Type | Required | Description |
|---|---|---|---|
| hash | string | No | Final file hash for validation. Can be provided/updated at completion time. Must be provided with hash_algo. |
| hash_algo | string | No | Hash algorithm: "md5", "sha1", "sha256", or "sha384" |
No body parameters required. If the session is already in a completed or processing state (complete, assemble, assembling, store, storing, stored), the endpoint returns 200 OK immediately without error.
Example
curl -X POST "https://api.fast.io/current/upload/u1abc-defgh-ijklm-nopqr-stuvw-xyz123/complete/" \
-H "Authorization: Bearer {jwt_token}"
Response (202 Accepted)
{
"result": "yes",
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_MISSING | 404 | "The id provided is not found..." |
APP_NOT_ACCEPTABLE | 406 | "The session id provided is not in a valid state to assemble." |
APP_NOT_ACCEPTABLE | 406 | "No chunks have been uploaded to this session." |
APP_NOT_ACCEPTABLE | 406 | "The chunks provided do not match the size of the file." |
APP_FEATURE_LIMIT | 403 | "You have created too many upload sessions..." |
APP_ENQUEUE_FAILED | 500 | "Your request was valid but could not be processed." |
Step 4: Poll for completion
Get upload session status with optional long-poll.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {upload_id} | string | Yes | The upload session ID |
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| wait | integer | No | — | Long-poll wait time in seconds (1 to 590). Server holds the connection and returns immediately when the status changes. |
The server uses Pub/Sub to detect status changes during long-poll. If Pub/Sub is unavailable, it falls back to polling every 0.5 seconds. Maximum wait is 590 seconds.
Example
curl -X GET "https://api.fast.io/current/upload/u1abc-defgh-ijklm-nopqr-stuvw-xyz123/details/?wait=60" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"session": {
"id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"name": "annual-report.pdf",
"size": 52428800,
"status": "stored",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"hash_algo": "sha256",
"created": "2025-01-20 10:30:00",
"updated": "2025-01-20 10:35:00",
"chunks": {
"1": 5242880,
"2": 5242880,
"3": 5242880,
"4": 5242880,
"5": 5242880
}
}
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.session.id | string | Upload session OpaqueId |
| response.session.name | string | Filename |
| response.session.size | integer | Declared file size in bytes |
| response.session.status | string | Current status (see status table above) |
| response.session.hash | string | File hash (if provided) |
| response.session.hash_algo | string | Hash algorithm (if provided) |
| response.session.created | string | Session creation timestamp |
| response.session.updated | string | Last update timestamp |
| response.session.chunks | object | Map of chunk order (string key) to chunk size (integer value) |
| response.session.new_file_id | string | OpaqueId of created storage node (only when stored with a target) |
Exit condition: Stop polling when status is stored, assembly_failed, or store_failed.
Step 5 (if no instance_id): Add file to storage manually
Add a completed upload to workspace storage.
Or for shares:
Add a completed upload to share storage.
Path parameters
{workspace_id}or{share_id}— Profile ID (20-digit numeric string){folder_id}— OpaqueId of the target folder, or"root"for the storage root
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| from | string (JSON) | Yes | Source specification as JSON-encoded string |
from format
from={"type":"upload","upload":{"id":"{upload_id}"}}
Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/root/addfile/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'from={"type":"upload","upload":{"id":"u1abc-defgh-ijklm-nopqr-stuvw-xyz123"}}'
Step 6 (optional): Clean up session
Delete an upload session and clean up temporary files.
Complete Chunked Upload Example
1. Create session (25 MB file, 5 chunks)
curl -X POST "https://api.fast.io/current/upload/" \
-H "Authorization: Bearer {jwt_token}" \
-d "name=presentation.pptx" \
-d "size=26214400" \
-d "action=create" \
-d "instance_id=12345678901234567890" \
-d "folder_id=root"
Response:
{"result": "yes", "response": {"id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123"}, "current_api_version": "1.0"}
2. Upload 5 chunks (3 in parallel, then 2 more)
# Chunks 1-3 in parallel
curl -X POST "https://api.fast.io/current/upload/u1abc-.../chunk/?order=1&size=5242880" \
-H "Authorization: Bearer {jwt_token}" -F "chunk=@chunk1.bin" &
curl -X POST "https://api.fast.io/current/upload/u1abc-.../chunk/?order=2&size=5242880" \
-H "Authorization: Bearer {jwt_token}" -F "chunk=@chunk2.bin" &
curl -X POST "https://api.fast.io/current/upload/u1abc-.../chunk/?order=3&size=5242880" \
-H "Authorization: Bearer {jwt_token}" -F "chunk=@chunk3.bin" &
wait
# Chunks 4-5
curl -X POST ".../chunk/?order=4&size=5242880" \
-H "Authorization: Bearer {jwt_token}" -F "chunk=@chunk4.bin" &
curl -X POST ".../chunk/?order=5&size=5242880" \
-H "Authorization: Bearer {jwt_token}" -F "chunk=@chunk5.bin" &
wait
3. Trigger assembly
curl -X POST "https://api.fast.io/current/upload/u1abc-.../complete/" \
-H "Authorization: Bearer {jwt_token}"
4. Poll until stored
curl -X GET "https://api.fast.io/current/upload/u1abc-.../details/?wait=60" \
-H "Authorization: Bearer {jwt_token}"
Response: {"result": "yes", "response": {"session": {"status": "assembling", ...}}} — keep polling
curl -X GET "https://api.fast.io/current/upload/u1abc-.../details/?wait=60" \
-H "Authorization: Bearer {jwt_token}"
Response: {"result": "yes", "response": {"session": {"status": "stored", "new_file_id": "f3jm5-...", ...}}} — done
5. Clean up session
curl -X DELETE "https://api.fast.io/current/upload/u1abc-defgh-ijklm-nopqr-stuvw-xyz123" \
-H "Authorization: Bearer {jwt_token}"
Resume a Disconnected Upload
If an upload is interrupted (network failure, client crash), resume it without re-uploading completed chunks.
Steps
-
Get session status:
curl -X GET "https://api.fast.io/current/upload/{upload_id}/details/" \ -H "Authorization: Bearer {jwt_token}" - Read the
chunksmap in the response. Keys are chunk numbers already uploaded, values are byte sizes. - Upload only missing chunks. Compare the
chunksmap against the expected chunk list. Upload any chunks not present. -
Trigger assembly:
curl -X POST "https://api.fast.io/current/upload/{upload_id}/complete/" \ -H "Authorization: Bearer {jwt_token}" - Poll for completion as normal.
File Update (New Version)
To upload a new version of an existing file:
- Create session with
action=update,instance_id, andfile_id(OpaqueId of the file to replace). - Upload chunks and complete as normal. The existing file receives a new version.
curl -X POST "https://api.fast.io/current/upload/" \
-H "Authorization: Bearer {jwt_token}" \
-d "name=report-v2.pdf" \
-d "size=1024" \
-d "action=update" \
-d "instance_id=12345678901234567890" \
-d "file_id=f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4" \
-F "chunk=@report-v2.pdf"
Web Upload (URL Import)
Import files from any HTTP/HTTPS URL. Supports OAuth-protected URLs (Google Drive, OneDrive, Dropbox, Box, iCloud). The server downloads the file in the background and streams it through the standard upload pipeline.
Create web upload job
Create a new web upload job to import a file from a URL.
Content-Type: application/json
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| source_url | string | Yes | URL to download the file from. Only HTTP/HTTPS supported. Max 2048 characters. |
| file_name | string | Yes | Filename to save as (1–255 chars) |
| profile_id | string | Yes | Target workspace or share profile ID (20-digit numeric) |
| profile_type | string | Yes | "workspace" or "share" |
| folder_id | string | No | Target folder OpaqueId or "root" for storage root |
| relative_path | string | No | Relative path for automatic folder creation (1–8192 chars) |
| options | integer | No | Bitfield options (default: 0). See options table. |
| creator | string | No | Client identifier string (1–150 chars, alphanumeric and hyphens only) |
Options bitfield
| Bit | Value | Description |
|---|---|---|
| 0 | 0x1 | Overwrite if a file with the same name exists at the destination |
| 1 | 0x2 | Skip virus scanning (admin only) |
| 2 | 0x4 | Attempt to preserve source file metadata |
Example
curl -X POST "https://api.fast.io/current/web_upload/" \
-H "Authorization: Bearer {jwt_token}" \
-H "Content-Type: application/json" \
-d '{
"source_url": "https://example.com/files/document.pdf",
"file_name": "document.pdf",
"profile_id": "12345678901234567890",
"profile_type": "workspace",
"folder_id": "root"
}'
Response (201 Created)
{
"result": "yes",
"response": {
"web_upload": {
"id": "aBcDeFgHiJkLmNoPqRsT123456",
"user_id": "12345678901234567890",
"profile_id": "12345678901234567890",
"profile_type": 1,
"source_url": "https://example.com/files/document.pdf",
"file_name": "document.pdf",
"folder_id": null,
"relative_path": null,
"status": 2,
"bytes_downloaded": 0,
"expected_size": null,
"upload_session_id": null,
"async_job_id": null,
"error_message": null,
"options": 0,
"properties": null,
"created": "2025-01-26 15:00:00",
"updated": "2025-01-26 15:00:00"
}
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.web_upload.id | string | Web upload job OpaqueId |
| response.web_upload.user_id | string | ID of the user who created the job |
| response.web_upload.profile_id | string | Target workspace or share ID |
| response.web_upload.profile_type | integer | 1 = workspace, 2 = share |
| response.web_upload.source_url | string | The source URL |
| response.web_upload.file_name | string | Destination filename |
| response.web_upload.folder_id | string/null | Target folder OpaqueId |
| response.web_upload.relative_path | string/null | Relative path for folder creation |
| response.web_upload.status | integer | Status code (initially 2 = QUEUED) |
| response.web_upload.bytes_downloaded | integer | Bytes downloaded so far (0 initially) |
| response.web_upload.expected_size | integer/null | Expected file size (from HEAD request, if known) |
| response.web_upload.upload_session_id | string/null | Linked upload session ID (populated during uploading phase) |
| response.web_upload.error_message | string/null | Error details if failed |
| response.web_upload.options | integer | Options bitfield |
| response.web_upload.created | string | Creation timestamp |
| response.web_upload.updated | string | Last update timestamp |
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | "Invalid URL. Only HTTP and HTTPS URLs are supported." |
APP_ERROR_INPUT_INVALID | 400 | "Invalid profile_type. Must be \"workspace\" or \"share\"." |
APP_DENIED | 403 | "You do not have permission to upload to this workspace." |
APP_DENIED | 403 | "You do not have permission to upload to this share." |
APP_NOT_ACCEPTABLE | 406 | "You have too many active web uploads..." |
APP_INTERNAL_ERROR | 500 | "Failed to create web upload job." |
OAuth for protected URLs
For Google Drive, OneDrive, and other OAuth-protected files, include the access token as a query parameter in the source URL:
https://www.googleapis.com/drive/v3/files/{fileId}?alt=media&access_token={oauth_token}
The server extracts the token from the URL, removes it from the query string, and sends it as an Authorization: Bearer header on all HTTP requests. Tokens are never logged or returned in API responses.
List web upload jobs
List all web upload jobs for the current user.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| limit | integer | No | 50 | Maximum number of results (1–100) |
| offset | integer | No | 0 | Pagination offset |
| status | string | No | — | Filter by status: "pending", "queued", "downloading", "uploading", "complete", "failed", "canceled" |
Example
curl -X GET "https://api.fast.io/current/web_upload/?status=downloading&limit=20" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"web_uploads": [
{
"id": "aBcDeFgHiJkLmNoPqRsT123456",
"user_id": "12345678901234567890",
"profile_id": "12345678901234567890",
"profile_type": "workspace",
"source_url": "https://example.com/files/document.pdf",
"file_name": "document.pdf",
"folder_id": null,
"relative_path": null,
"status": "downloading",
"status_description": "Downloading file from URL",
"bytes_downloaded": 5242880,
"expected_size": 52428800,
"progress_percent": 10,
"upload_session_id": null,
"error_message": null,
"created": "2025-01-26 15:00:00",
"updated": "2025-01-26 15:01:00"
}
],
"total": 1,
"limit": 20,
"offset": 0
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.web_uploads | array | Array of web upload job objects |
| response.web_uploads[].id | string | Web upload job OpaqueId |
| response.web_uploads[].profile_type | string | "workspace" or "share" |
| response.web_uploads[].status | string | Status string (e.g., "downloading", "complete") |
| response.web_uploads[].status_description | string | Human-readable status description |
| response.web_uploads[].bytes_downloaded | integer | Bytes downloaded so far |
| response.web_uploads[].expected_size | integer/null | Expected file size (null if unknown) |
| response.web_uploads[].progress_percent | integer | Download progress percentage (0–100) |
| response.web_uploads[].upload_session_id | string/null | Linked upload session ID |
| response.web_uploads[].error_message | string/null | Error details if failed |
| response.total | integer | Total count of matching records |
| response.limit | integer | Applied limit |
| response.offset | integer | Applied offset |
Get web upload job details
Get details for a specific web upload job.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {upload_id} | string | Yes | The web upload job OpaqueId |
Example
curl -X GET "https://api.fast.io/current/web_upload/aBcDeFgHiJkLmNoPqRsT123456/details/" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"web_upload": {
"id": "aBcDeFgHiJkLmNoPqRsT123456",
"user_id": "12345678901234567890",
"profile_id": "12345678901234567890",
"profile_type": 1,
"source_url": "https://example.com/files/document.pdf",
"file_name": "document.pdf",
"status": 5,
"bytes_downloaded": 52428800,
"expected_size": 52428800,
"upload_session_id": "xYzAbCdEfGhIjKlMnOpQ123456",
"error_message": null,
"options": 0,
"created": "2025-01-26 15:00:00",
"updated": "2025-01-26 15:02:00"
}
},
"current_api_version": "1.0"
}
Note: The details endpoint returns raw status integers (not the string names used in the list endpoint).
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | "Web upload job not found." |
APP_DENIED | 403 | "You do not have permission to view this web upload job." |
Cancel web upload job
Cancel an active web upload job.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The web upload job OpaqueId to cancel |
Example
curl -X DELETE "https://api.fast.io/current/web_upload/?id=aBcDeFgHiJkLmNoPqRsT123456" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"canceled": true,
"id": "aBcDeFgHiJkLmNoPqRsT123456"
},
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | "Web upload job not found." |
APP_DENIED | 403 | "You do not have permission to cancel this web upload job." |
APP_NOT_ACCEPTABLE | 406 | "This web upload job cannot be canceled because it is already in a terminal state." |
APP_INTERNAL_ERROR | 500 | "Failed to cancel web upload job." |
Web Upload Status Values
| Status | Value | Description | Terminal |
|---|---|---|---|
pending | 1 | Job created, waiting for async job pickup | No |
queued | 2 | Async job has been queued for processing | No |
downloading | 3 | Actively downloading from the source URL | No |
uploading | 4 | Feeding downloaded chunks to upload system | No |
complete | 5 | Upload successfully completed | Yes |
failed | 6 | Download or upload failed | Yes |
canceled | 7 | User canceled the web upload | Yes |
Web Upload Limits
| Limit | Value |
|---|---|
| Max active per user | 50 (non-terminal jobs) |
| Max file size | Up to 40 GB (subject to plan limits) |
| Max retries | 3 (automatic on transient failures) |
| Retry delay | 60 seconds between attempts |
Upload Management Endpoints
List all upload sessions
Returns all upload sessions for the current user in any state.
Example
curl -X GET "https://api.fast.io/current/upload/details/" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"results": 2,
"sessions": [
{
"id": "aBcDeFgHiJkLmNoPqRsT123456",
"name": "document.pdf",
"size": 52428800,
"status": "uploading",
"hash": "e3b0c44298fc1c14...",
"hash_algo": "sha256",
"created": "2025-01-20 10:30:00",
"updated": "2025-01-20 10:35:00"
}
]
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.results | integer | Total number of sessions (only present when > 1) |
| response.sessions | array | Array of upload session objects |
Delete/cancel an upload session
Cancel and delete an active upload session.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {upload_id} | string | Yes | The upload session ID to delete (appended to URL path) |
Cleans up temporary chunk files and releases session quota. If the session has an associated web upload job, that job is automatically canceled.
Sessions can be deleted in states: ready, uploading, assembly_failed, store_failed, complete. Sessions in assembling, storing, or stored states cannot be deleted.
Example
curl -X DELETE "https://api.fast.io/current/upload/aBcDeFgHiJkLmNoPqRsT123456" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | "The id provided is not found or is not associated with your account." |
APP_NOT_ACCEPTABLE | 406 | "The session id provided is not in a valid state to delete." |
APP_INTERNAL_ERROR | 500 | "We were unable to delete the requested upload session." |
Get upload limits
Returns upload limits based on the user's billing plan and target context.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| action | string | No | — | "create" or "update" to get limits in context of a target |
| org | string | No | — | Organization ID for limit resolution (used when no action specified) |
| instance_id | string | Required if action=create | — | Target workspace or share ID |
| folder_id | string | No | — | Target folder OpaqueId or "root" |
| file_id | string | Required if action=update | — | File ID for update context |
Example
# General limits (with org context)
curl -X GET "https://api.fast.io/current/upload/limits/?org=12345678901234567890" \
-H "Authorization: Bearer {jwt_token}"
# Limits for creating a file in a workspace
curl -X GET "https://api.fast.io/current/upload/limits/?action=create&instance_id=12345678901234567890" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"limits": {
"chunk_size": 104857600,
"size": 42949672960,
"chunks": 500,
"sessions": 7500,
"sessions_size_max": 214748364800
}
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.limits.chunk_size | integer | Maximum size of a single chunk in bytes |
| response.limits.size | integer | Maximum total file size in bytes |
| response.limits.chunks | integer | Maximum number of chunks per upload session |
| response.limits.sessions | integer | Maximum concurrent active upload sessions |
| response.limits.sessions_size_max | integer | Maximum aggregate size of all active sessions in bytes |
Get restricted file extensions
Returns restricted and archive file extensions. Authentication is optional.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| plan | string | No | User's plan or "free" | Override the billing plan to check restrictions for |
Example
curl -X GET "https://api.fast.io/current/upload/limits/extensions/"
# With specific plan
curl -X GET "https://api.fast.io/current/upload/limits/extensions/?plan=pro"
Response (200 OK)
{
"result": "yes",
"response": {
"restricted_extensions": [".exe", ".apk", ".jar", ".php"],
"archive_extensions": [".7z", ".zip", ".rar", ".tar.gz", ".bz2"],
"enforcement_enabled": true,
"plan": "free",
"cache_ttl": 86400
},
"current_api_version": "1.0"
}
Response fields
| Field | Type | Description |
|---|---|---|
| response.restricted_extensions | string[] | Extensions blocked for the plan |
| response.archive_extensions | string[] | Archive extensions (only populated if the plan restricts archives) |
| response.enforcement_enabled | boolean | Whether extension restriction enforcement is currently active |
| response.plan | string | The plan used for this response |
| response.cache_ttl | integer | Suggested client-side cache TTL in seconds (86400 = 24 hours) |
Clients should call this once on startup and cache the results for 24 hours.
List supported hash algorithms
Returns the list of supported hash algorithms for upload integrity verification.
Example
curl -X GET "https://api.fast.io/current/upload/algos/" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"response": {
"algos": ["md5", "sha1", "sha256", "sha384"]
},
"current_api_version": "1.0"
}
Get chunk information
Returns information about uploaded chunks for a session.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| order | integer | No | Specific chunk number to retrieve. If omitted, returns all chunks. |
Example (all chunks)
curl -X GET "https://api.fast.io/current/upload/aBcDeFgHiJkLmNoPqRsT123456/chunk/" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK, all chunks)
{
"result": "yes",
"response": {
"chunks": {
"1": 5242880,
"2": 5242880,
"3": 2097152
}
},
"current_api_version": "1.0"
}
Response (200 OK, single chunk with ?order=1)
{
"result": "yes",
"response": {
"chunk": {
"1": 5242880
}
},
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | "The supplied chunk not valid or found." |
Delete a chunk
Delete a specific chunk from an upload session. Session must be in uploading state.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| order | integer | Yes | The chunk number to delete |
Example
curl -X DELETE "https://api.fast.io/current/upload/aBcDeFgHiJkLmNoPqRsT123456/chunk/?order=3" \
-H "Authorization: Bearer {jwt_token}"
Response (200 OK)
{
"result": "yes",
"current_api_version": "1.0"
}
Error responses
| Error Code | HTTP Status | Message |
|---|---|---|
APP_NOT_ACCEPTABLE | 406 | "The session id provided is not in a valid state to delete a chunk." |
APP_INTERNAL_ERROR | 500 | "We were unable to delete the requested upload session chunk." |
Quick Reference
Small file (one request, auto-add)
POST /current/upload/
multipart: name, size, chunk, action=create, instance_id, folder_id
-> 201: {id, new_file_id}
Large file (chunked)
POST /current/upload/ # Create session
form: name, size, action=create, instance_id, folder_id
-> 201: {id}
POST /current/upload/{id}/chunk/?order=N&size=N # Upload chunks (up to 3 parallel)
multipart: chunk
-> 202
POST /current/upload/{id}/complete/ # Trigger assembly
-> 202
GET /current/upload/{id}/details/?wait=60 # Poll until stored
-> 200: {session: {status, new_file_id}}
DELETE /current/upload/{id} # Clean up session
-> 200
Manual add to storage (if no instance_id)
POST /current/workspace/{id}/storage/{folder}/addfile/
form: from={"type":"upload","upload":{"id":"{upload_id}"}}
-> 200
Web upload (URL import)
POST /current/web_upload/ # Create job
json: source_url, file_name, profile_id, profile_type
-> 201: {web_upload}
GET /current/web_upload/ # List jobs
query: limit, offset, status
-> 200: {web_uploads, total}
GET /current/web_upload/{id}/details/ # Get job details
-> 200: {web_upload}
DELETE /current/web_upload/?id={id} # Cancel job
-> 200: {canceled, id}
Upload management
GET /current/upload/details/ # List all sessions
GET /current/upload/limits/ # Get plan limits
GET /current/upload/limits/extensions/ # Get restricted extensions
GET /current/upload/algos/ # List hash algorithms
GET /current/upload/{id}/chunk/ # Get chunk info
DELETE /current/upload/{id}/chunk/?order=N # Delete a chunk
Best Practices
- Check limits first: Query
/upload/limits/and/upload/limits/extensions/before starting uploads. - Use hash validation: Always provide chunk and file hashes to detect corruption early.
- Implement retry logic: Failed chunk uploads can be retried by re-uploading the same
order. - Track chunks locally: Maintain a local record of successfully uploaded chunks for resumability.
- Long-poll for completion: Use the
waitparameter on the details endpoint instead of frequent polling. - Clean up failures: DELETE failed sessions to free session quota.
- Cache extension restrictions: Call
/upload/limits/extensions/once and cache for 24 hours. - Use auto-finalization: When all chunks total the declared file size, assembly triggers automatically. Explicit
/complete/is optional but recommended for reliability. - Omit
relative_pathwhen unused: Do NOT send it as an empty string.