File Upload Chunked upload flow, web upload (URL import), status polling, and upload management.

Base URL: https://api.fast.io/current/ Auth: Bearer {jwt_token} Format: multipart/form-data (file data) · application/x-www-form-urlencoded (non-file)

Overview

Fast.io supports four upload flows:

  1. 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.
  2. Large files (≥ 4 MB) — Chunked upload. Create a session, upload chunks (up to 3 in parallel), trigger assembly, poll until stored.
  3. Stream upload — Upload a file of unknown size in a single request. Create a session with stream=true, then POST the raw file body to the stream endpoint.
  4. 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

ConstraintValue
Single-call upload max size4 MB (4,194,304 bytes)
Chunk sizePlan-dependent (query /upload/limits/ for exact values)
Last chunkMay be smaller than the plan chunk size
Max parallel chunk uploads per session3
Max undersized chunks per session1 (the final chunk only)
Chunk ordering1-based (first chunk is order=1)
Supported hash algorithmsmd5, sha1, sha256, sha384
relative_path max length8192 characters
relative_pathOmit entirely if empty — do NOT send as empty string
creator format1–150 chars, alphanumeric and hyphens only (/^[a-zA-Z0-9\-]+$/)
Max file sizePlan-dependent (up to 40 GB)
Max concurrent sessionsPlan-dependent (150 for Free, 7500 for Pro/Business)
Long-poll max wait590 seconds

Upload Status Values

StatusMeaningAction
readySession created, awaiting chunksUpload chunks
uploadingChunks being receivedContinue uploading
assembleAssembly queuedKeep polling
assemblingAssembly in progressKeep polling
completeAssembly done, awaiting storage importKeep polling (or use addfile if not auto-adding)
storeStorage import queuedKeep polling
storingBeing imported to storageKeep polling
storedFully complete — file assembled and in storageDone. new_file_id available.
assembly_failedAssembly failedHandle error
store_failedStorage import failedHandle 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

POST /current/upload/

Create upload session and send file data in a single request.

Content-Type: multipart/form-data

Parameters

ParameterTypeRequiredDescription
namestringYesFile name including extension (1–255 chars). Names longer than 100 chars are auto-truncated server-side, preserving the extension; conflict resolution switches to RENAME when truncation occurs.
sizeintegerYesFile size in bytes (must match actual file)
chunkfileYesThe file binary data (multipart field)
actionstringNo"create" for new file, "update" for file replacement
instance_idstringRequired if action=createWorkspace or share profile ID (19-digit numeric)
file_idstringRequired if action=updateOpaqueId of the existing file to replace
folder_idstringNoTarget folder OpaqueId or "root" for storage root
hashstringNoHash of the full file. Must be provided with hash_algo.
hash_algostringNoHash algorithm: "md5", "sha1", "sha256", or "sha384"
relative_pathstringNoFor folder uploads, relative path for auto folder creation (max 8192 chars). Omit entirely if not applicable.
orgstringNoOrganization ID for billing limit resolution (only used when no action is specified)
creatorstringNoClient 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

FieldTypeDescription
resultstring"yes" on success
response.idstringUpload session OpaqueId
response.creatorstringEchoed back only if creator was provided in the request
response.new_file_idstringOpaqueId 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 CodeHTTP StatusMessage
1605 (Invalid Input)400"The size was not supplied."
1605 (Invalid Input)400"The file name is not valid."
1605 (Invalid Input)400"Invalid share or workspace instance ID."
1658 (Not Acceptable)406"This file type is not allowed for upload on your plan."
1685 (Feature Limit)403"The file size exceeds single call upload, use chunks."
1685 (Feature Limit)403"You have created too many upload sessions..."
1685 (Feature Limit)403"The size is too large for the account plan."
1685 (Feature Limit)403"The total size of all active upload sessions exceeds the limit."
1605 (Invalid Input)400"The hash algorithm provided is not valid."
1605 (Invalid Input)400"The hash provided is not valid."
1605 (Invalid Input)400"The hash algorithm was provided but not the hash."
1658 (Not Acceptable)406"We were unable to create the upload session..."

Workflow: Large File Upload (Chunked)

Step 1: Create upload session

POST /current/upload/

Create a new upload session for a large file.

Content-Type: application/x-www-form-urlencoded

Parameters

ParameterTypeRequiredDescription
namestringYesFile name including extension (1–255 chars). Names longer than 100 chars are auto-truncated server-side, preserving the extension; conflict resolution switches to RENAME when truncation occurs.
sizeintegerYesTotal file size in bytes
actionstringYes"create" for new file, "update" for file replacement
instance_idstringRequired if action=createWorkspace or share profile ID (19-digit numeric) for auto-add to storage after assembly
file_idstringRequired if action=updateOpaqueId of existing file to replace
folder_idstringNoTarget folder OpaqueId or "root" for storage root
hashstringNoSHA-256 hex hash of the full file for integrity verification. Must be provided with hash_algo.
hash_algostringNoHash algorithm: "md5", "sha1", "sha256", or "sha384"
relative_pathstringNoFor folder uploads, relative path for auto folder creation (max 8192 chars). Omit entirely if not applicable.
orgstringNoOrganization ID for billing limit resolution (only used when no action is specified)
creatorstringNoClient 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

POST /current/upload/{upload_id}/chunk/?order={n}&size={bytes}

Upload a single chunk of file data.

Content-Type: multipart/form-data

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe upload session ID from Step 1

Query parameters

ParameterTypeRequiredDescription
orderintegerYes1-based chunk number (first chunk = 1). Must not exceed plan's chunk limit.
sizeintegerYesSize of this chunk in bytes. Must match the actual uploaded file size.
hashstringNoHash of this chunk. Must be provided with hash_algo.
hash_algostringNoHash algorithm: "md5", "sha1", "sha256", or "sha384"

Request body (multipart/form-data)

FieldTypeRequiredDescription
chunkfileYesBinary 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 CodeHTTP StatusMessage
1605 (Invalid Input)400"The session id provided is not valid."
1658 (Not Acceptable)406"The session id provided is not in a valid state to accept a chunk."
1605 (Invalid Input)400"No order supplied"
1605 (Invalid Input)400"The order provided for this chunk is not valid..."
1605 (Invalid Input)400"The size was not supplied."
1685 (Feature Limit)403"The size is too large for the account plan."
1685 (Feature Limit)403"The size is too small for the account plan."
1685 (Feature Limit)403"You have exceeded the maximum number of chunks..."
1685 (Feature Limit)403"The combined chunk size exceeds the size for this session."
1605 (Invalid Input)400"The upload chunk failed or was the wrong size..."
1605 (Invalid Input)400"The chunk failed to hash properly..."
1654 (Internal Error)500"The chunk failed to be stored..."

Step 3: Trigger assembly

POST /current/upload/{upload_id}/complete/

Trigger asynchronous assembly of all uploaded chunks.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe upload session ID

Query parameters (optional)

ParameterTypeRequiredDescription
hashstringNoFinal file hash for validation. Can be provided/updated at completion time. Must be provided with hash_algo.
hash_algostringNoHash 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 CodeHTTP StatusMessage
1683 (Resource Missing)404"The id provided is not found..."
1658 (Not Acceptable)406"The session id provided is not in a valid state to assemble."
1658 (Not Acceptable)406"No chunks have been uploaded to this session."
1658 (Not Acceptable)406"The chunks provided do not match the size of the file."
1685 (Feature Limit)403"You have created too many upload sessions..."
1678 (Enqueue Failed)500"Your request was valid but could not be processed."

Step 4: Poll for completion

GET /current/upload/{upload_id}/details/?wait=60

Get upload session status with optional long-poll.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe upload session ID

Query parameters

ParameterTypeRequiredDefaultDescription
waitintegerNoLong-poll wait time in seconds (1 to 590). Server holds the connection and returns immediately when the status changes.

The server detects status changes efficiently during long-poll. 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

FieldTypeDescription
response.session.idstringUpload session OpaqueId
response.session.namestringFilename
response.session.sizeintegerDeclared file size in bytes
response.session.statusstringCurrent status (see status table above)
response.session.hashstringFile hash (if provided)
response.session.hash_algostringHash algorithm (if provided)
response.session.createdstringSession creation timestamp
response.session.updatedstringLast update timestamp
response.session.chunksobjectMap of chunk order (string key) to chunk size (integer value)
response.session.new_file_idstringOpaqueId 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

POST /current/workspace/{workspace_id}/storage/{folder_id}/addfile/

Add a completed upload to workspace storage.

Or for shares:

POST /current/share/{share_id}/storage/{folder_id}/addfile/

Add a completed upload to share storage.

Path parameters

Body parameters

ParameterTypeRequiredDescription
fromstring (JSON)YesSource 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 /current/upload/{upload_id}

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

  1. Get session status:
    curl -X GET "https://api.fast.io/current/upload/{upload_id}/details/" \
      -H "Authorization: Bearer {jwt_token}"
  2. Read the chunks map in the response. Keys are chunk numbers already uploaded, values are byte sizes.
  3. Upload only missing chunks. Compare the chunks map against the expected chunk list. Upload any chunks not present.
  4. Trigger assembly:
    curl -X POST "https://api.fast.io/current/upload/{upload_id}/complete/" \
      -H "Authorization: Bearer {jwt_token}"
  5. Poll for completion as normal.

File Update (New Version)

To upload a new version of an existing file:

  1. Create session with action=update, instance_id, and file_id (OpaqueId of the file to replace).
  2. 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"

Stream Upload (Unknown File Size)

For clients that don't know the exact file size upfront (piped output, generated content, compressed streams). The client declares a maximum size ceiling, streams the file in a single request, and the system records actual bytes.

Step 1: Create stream session

POST /current/upload/

Create a stream-mode upload session.

Parameters

ParameterTypeRequiredDescription
namestringYesFilename including extension
streamstringYesMust be "true"
max_sizeintegerNoMaximum file size in bytes (defaults to plan limit)
actionstringNo"create" or "update" (same as standard upload)
instance_idstringConditionalTarget workspace/share ID (required if action=create)
file_idstringConditionalFile to update (required if action=update)
hashstringNoExpected whole-file hash
hash_algostringNoHash algorithm: "md5", "sha1", "sha256", or "sha384"
creatorstringNoClient identifier

Example

curl -X POST "https://api.fast.io/current/upload/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "name=output.tar.gz" \
  -d "stream=true" \
  -d "max_size=52428800" \
  -d "action=create" \
  -d "instance_id=12345678901234567890"

Response (201 Created)

{
  "result": "yes",
  "response": {
    "id": "u1abc-defgh-ijklm-nopqr-stuvw-xyz123"
  },
  "current_api_version": "1.0"
}

Step 2: Stream file body

POST /current/upload/{upload_id}/stream/

Upload the entire file as a raw binary stream.

Send the raw file bytes as the request body with Content-Type: application/octet-stream. No size or order parameters needed.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe upload session ID from Step 1

Query parameters (optional)

ParameterTypeRequiredDescription
hashstringNoWhole-file hash for validation. Must be provided with hash_algo.
hash_algostringNoHash algorithm: "md5", "sha1", "sha256", or "sha384"

Example

curl -X POST "https://api.fast.io/current/upload/u1abc-defgh-ijklm-nopqr-stuvw-xyz123/stream/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @myfile.tar.gz

Response (201 Created)

{
  "result": "yes",
  "current_api_version": "1.0"
}

The session auto-finalizes after the stream completes. The session's size field is updated to reflect the actual bytes received.

Error responses

Error CodeHTTP StatusMessage
1658 (Not Acceptable)406"This session is not configured for streaming uploads."
1658 (Not Acceptable)406"A stream has already been uploaded for this session."
1605 (Invalid Input)400"The upload stream was empty or interrupted."
1685 (Feature Limit)403"The uploaded bytes exceed the session's maximum size."
1658 (Not Acceptable)406"The session is not in a valid state to accept a stream."

Notes

Batch Upload (Many Small Files)

Submit 1–200 small files in a single request. Returns a per-file result array, so partial success is legible and does not abort the batch. Use this when you have many small files destined for the same workspace or share — one rate-limit cost instead of one per file. For files over 4 MB, keep using the standard chunked POST /current/upload/ flow.

Batch Limits

LimitValue
Files per batch1–200
Max per-file size4 MB (4,194,304 bytes)
Max request body100 MB (applied post-base64-decode on the JSON path)
Supported hash algorithmsmd5, sha1, sha256, sha384
Status record TTL1 hour from POST

Create batch (multipart)

POST /current/upload/batch/

Submit a batch of up to 200 small files via multipart/form-data.

Content-Type: multipart/form-data

Batch-level fields

FieldTypeRequiredDescription
instance_idstringYesTarget workspace or share profile ID (19-digit numeric). Every file in the batch lands in this target.
creatorstringNoOptional echo-back correlation tag (1–150 chars, alphanumeric and hyphens only).
manifeststring (JSON)YesJSON-encoded array of per-file manifest entries (see below).
file_{index}fileYes (one per manifest entry)Binary file body. The suffix matches the index in the manifest entry.

Manifest entry schema

FieldTypeRequiredDescription
indexintegerYes0-based position. Indices must be contiguous from 0 to N−1 with no duplicates.
filenamestringYesFile name (1–255 chars). Names longer than 100 chars are auto-truncated server-side, preserving the extension; conflict resolution switches to RENAME when truncation occurs.
hash_algostringNo"md5", "sha1", "sha256", or "sha384" for optional integrity validation.
hashstringNoHex digest of the uploaded bytes.

Hash validation is opt-in per entry: supply both hash_algo and hash, or neither. A mismatch errors only that entry; the batch still returns 200.

Example

curl -X POST "https://api.fast.io/current/upload/batch/" \
  -H "Authorization: Bearer {jwt_token}" \
  -F "instance_id=12345678901234567890" \
  -F "creator=my-importer" \
  -F 'manifest=[{"index":0,"filename":"doc-001.txt"},{"index":1,"filename":"doc-002.txt"}]' \
  -F "file_0=@doc-001.txt" \
  -F "file_1=@doc-002.txt"

Create batch (JSON)

POST /current/upload/batch/

Fallback body shape for clients that cannot compose multipart.

Content-Type: application/json

Base64 inflation adds ~33% to the wire size and forces the server to hold decoded bytes in memory while parsing; prefer multipart (which streams directly to disk) for non-trivial payloads.

Body schema

{
  "instance_id": "12345678901234567890",
  "creator": "my-importer",
  "files": [
    {"filename": "doc-001.txt", "content_b64": "SGVsbG8sIHdvcmxkIQ=="},
    {"filename": "doc-002.txt", "content_b64": "U2Vjb25kIGZpbGU="}
  ]
}

Each files entry accepts the same optional hash_algo and hash fields as the multipart manifest. The array position is the entry's logical index.

Example

curl -X POST "https://api.fast.io/current/upload/batch/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "instance_id": "12345678901234567890",
    "creator": "my-importer",
    "files": [
      {"filename": "doc-001.txt", "content_b64": "SGVsbG8sIHdvcmxkIQ=="},
      {"filename": "doc-002.txt", "content_b64": "U2Vjb25kIGZpbGU="}
    ]
  }'

Response (200 OK)

Always 200 OK on a well-formed batch. Inspect count_errored to detect per-file failures.

{
  "result": "yes",
  "response": {
    "batch_id": "{batch_id}",
    "count_total": 2,
    "count_succeeded": 1,
    "count_errored": 1,
    "creator": "my-importer",
    "results": [
      {
        "index": 0,
        "filename": "doc-001.txt",
        "status": "ok",
        "upload_id": "{upload_id}",
        "node_id": "{node_id}"
      },
      {
        "index": 1,
        "filename": "doc-002.txt",
        "status": "error",
        "error_code": 1605,
        "error_message": "hash_algo and hash must both be provided for a manifest entry."
      }
    ]
  },
  "current_api_version": "1.0"
}

Response fields

FieldTypeDescription
response.batch_idstringOpaque batch identifier for the GET status lookup (valid for 1 hour).
response.count_totalintegerFiles submitted.
response.count_succeededintegerFiles with status: "ok".
response.count_erroredintegerFiles with status: "error".
response.creatorstringEchoed back only if creator was supplied.
response.results[].indexintegerMatches the submitted manifest index (or array position for the JSON path).
response.results[].filenamestringSubmitted filename.
response.results[].statusstring"ok" or "error".
response.results[].upload_idstringPresent on ok. Upload session OpaqueId.
response.results[].node_idstringPresent on ok when storage placement succeeded.
response.results[].error_codeintegerPresent on error. Same numeric codes used by POST /current/upload/.
response.results[].error_messagestringPresent on error. Human-readable description.

Whole-batch error responses

These are returned in the standard error envelope (no results[]).

Error CodeHTTP StatusCause
1605 (Invalid Input)400Unsupported Content-Type (must be multipart/form-data or application/json).
1605 (Invalid Input)400instance_id missing, not numeric, or not a valid workspace/share ID.
1605 (Invalid Input)400manifest not valid JSON, empty, or entries malformed.
1605 (Invalid Input)400Manifest index values not contiguous from 0, or contain duplicates.
1605 (Invalid Input)400Manifest filename fails validation.
1605 (Invalid Input)400JSON body missing files array or files empty.
1605 (Invalid Input)400creator fails length or character-set validation.
1685 (Feature Limit)403Batch contains more than 200 files.
1685 (Feature Limit)403Request body exceeds 100 MB (pre-parse Content-Length, or post-decode total for JSON).
1685 (Feature Limit)403Account plan does not allow files at the 4 MB per-file bound.
1680 (Access Denied)403Caller not authorized to upload to the target.

Per-file error causes

Recorded in results[] with status: "error"; the batch returns 200 OK.

Fetch batch status

GET /current/upload/batch/{batch_id}/

Re-fetch the stored result record for a prior batch.

Authentication is not required for this endpoint — the opaque batch_id is the only credential. Treat batch_id as bearer-equivalent; transport over HTTPS and do not log alongside identifiers.

Path parameters

ParameterTypeRequiredDescription
{batch_id}stringYesThe opaque batch identifier returned by a previous POST.

Example

curl -X GET "https://api.fast.io/current/upload/batch/{batch_id}/"

Response (200 OK)

{
  "result": "yes",
  "response": {
    "batch_id": "{batch_id}",
    "creator": "my-importer",
    "count_total": 2,
    "count_succeeded": 1,
    "count_errored": 1,
    "results": [
      { "index": 0, "filename": "doc-001.txt", "status": "ok", "upload_id": "{upload_id}", "node_id": "{node_id}" },
      { "index": 1, "filename": "doc-002.txt", "status": "error", "error_code": 1605, "error_message": "hash_algo and hash must both be provided for a manifest entry." }
    ],
    "created_ts": 1745000000
  },
  "current_api_version": "1.0"
}

Error responses

Error CodeHTTP StatusCause
1605 (Invalid Input)400batch_id missing or not a valid opaque identifier.
1609 (Not Found)404No record found, or the 1-hour TTL elapsed. 404 is returned for both cases; callers cannot distinguish "never existed" from "expired".

Notes

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

POST /current/web_upload/

Create a new web upload job to import a file from a URL.

Content-Type: application/json

Parameters

ParameterTypeRequiredDescription
source_urlstringYesURL to download the file from. Only HTTP/HTTPS supported. Max 2048 characters.
file_namestringYesFilename to save as (1–255 chars). Names longer than 100 chars are auto-truncated server-side, preserving the extension; RENAME conflict resolution prevents distinct sources from overwriting each other when they collapse to the same truncated prefix.
profile_idstringYesTarget workspace or share profile ID (19-digit numeric)
profile_typestringYes"workspace" or "share"
folder_idstringNoTarget folder OpaqueId or "root" for storage root
relative_pathstringNoRelative path for automatic folder creation (1–8192 chars)
optionsintegerNoBitfield options (default: 0). See options table.
creatorstringNoClient identifier string (1–150 chars, alphanumeric and hyphens only)

Options bitfield

BitValueDescription
00x1Overwrite if a file with the same name exists at the destination
10x2Skip virus scanning (admin only)
20x4Attempt 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": "workspace",
      "source_url": "https://example.com/files/document.pdf",
      "file_name": "document.pdf",
      "folder_id": null,
      "relative_path": null,
      "status": "queued",
      "status_description": "Queued for processing",
      "bytes_downloaded": 0,
      "expected_size": null,
      "upload_session_id": null,
      "async_job_id": null,
      "creator": "12345678901234567890",
      "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

FieldTypeDescription
response.web_upload.idstringWeb upload job OpaqueId
response.web_upload.user_idstringID of the user who created the job
response.web_upload.profile_idstringTarget workspace or share ID
response.web_upload.profile_typestring"workspace" or "share"
response.web_upload.source_urlstringThe source URL
response.web_upload.file_namestringDestination filename
response.web_upload.folder_idstring/nullTarget folder OpaqueId
response.web_upload.relative_pathstring/nullRelative path for folder creation
response.web_upload.statusstringStatus string (e.g., "queued", "downloading", "complete")
response.web_upload.bytes_downloadedintegerBytes downloaded so far (0 initially)
response.web_upload.expected_sizeinteger/nullExpected file size (from HEAD request, if known)
response.web_upload.upload_session_idstring/nullLinked upload session ID (populated during uploading phase)
response.web_upload.async_job_idstring/nullThe async job ID processing this upload
response.web_upload.status_descriptionstringHuman-readable status description
response.web_upload.creatorstringUser ID of the creator
response.web_upload.error_messagestring/nullError details if failed
response.web_upload.optionsintegerOptions bitfield
response.web_upload.createdstringCreation timestamp
response.web_upload.updatedstringLast update timestamp

Error responses

Error CodeHTTP StatusMessage
1605 (Invalid Input)400"Invalid URL. Only HTTP and HTTPS URLs are supported."
1605 (Invalid Input)400"Invalid profile_type. Must be \"workspace\" or \"share\"."
1680 (Access Denied)403"You do not have permission to upload to this workspace."
1680 (Access Denied)403"You do not have permission to upload to this share."
1658 (Not Acceptable)406"You have too many active web uploads..."
1654 (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

GET /current/web_upload/

List all web upload jobs for the current user.

Query parameters

ParameterTypeRequiredDefaultDescription
limitintegerNo50Maximum number of results (1–100)
offsetintegerNo0Pagination offset
statusstringNoFilter 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

FieldTypeDescription
response.web_uploadsarrayArray of web upload job objects
response.web_uploads[].idstringWeb upload job OpaqueId
response.web_uploads[].profile_typestring"workspace" or "share"
response.web_uploads[].statusstringStatus string (e.g., "downloading", "complete")
response.web_uploads[].status_descriptionstringHuman-readable status description
response.web_uploads[].bytes_downloadedintegerBytes downloaded so far
response.web_uploads[].expected_sizeinteger/nullExpected file size (null if unknown)
response.web_uploads[].progress_percentintegerDownload progress percentage (0–100)
response.web_uploads[].upload_session_idstring/nullLinked upload session ID
response.web_uploads[].error_messagestring/nullError details if failed
response.totalintegerTotal count of matching records
response.limitintegerApplied limit
response.offsetintegerApplied offset

Get web upload job details

GET /current/web_upload/{upload_id}/details/

Get details for a specific web upload job.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe 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": "workspace",
      "source_url": "https://example.com/files/document.pdf",
      "file_name": "document.pdf",
      "status": "complete",
      "status_description": "Upload successfully completed",
      "bytes_downloaded": 52428800,
      "expected_size": 52428800,
      "upload_session_id": "xYzAbCdEfGhIjKlMnOpQ123456",
      "async_job_id": "aBcDeFgHiJkLmNoPqRsT789012",
      "creator": "12345678901234567890",
      "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: Both the details and list endpoints return status as string values (e.g., "pending", "queued", "downloading", "uploading", "complete", "failed", "canceled").

Error responses

Error CodeHTTP StatusMessage
1609 (Not Found)404"Web upload job not found."
1680 (Access Denied)403"You do not have permission to view this web upload job."

Cancel web upload job

DELETE /current/web_upload/?id={web_upload_id}

Cancel an active web upload job.

Query parameters

ParameterTypeRequiredDescription
idstringYesThe 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 CodeHTTP StatusMessage
1609 (Not Found)404"Web upload job not found."
1680 (Access Denied)403"You do not have permission to cancel this web upload job."
1658 (Not Acceptable)406"This web upload job cannot be canceled because it is already in a terminal state."
1654 (Internal Error)500"Failed to cancel web upload job."

Web Upload Status Values

StatusValueDescriptionTerminal
pending1Job created, waiting for processingNo
queued2Job has been queued for processingNo
downloading3Actively downloading from the source URLNo
uploading4Feeding downloaded chunks to upload systemNo
complete5Upload successfully completedYes
failed6Download or upload failedYes
canceled7User canceled the web uploadYes

Web Upload Limits

LimitValue
Max active per user50 (non-terminal jobs)
Max file sizeUp to 40 GB (subject to plan limits)
Max retries3 (automatic on transient failures)
Retry delay60 seconds between attempts

Upload Management Endpoints

List all upload sessions

GET /current/upload/details/

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

FieldTypeDescription
response.resultsintegerTotal number of sessions (only present when > 1)
response.sessionsarrayArray of upload session objects

Delete/cancel an upload session

DELETE /current/upload/{upload_id}

Cancel and delete an active upload session.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe 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 assemble, assembling, store, 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 CodeHTTP StatusMessage
1605 (Invalid Input)400"The id provided is not found or is not associated with your account."
1658 (Not Acceptable)406"The session id provided is not in a valid state to delete."
1654 (Internal Error)500"We were unable to delete the requested upload session."

Get upload limits

GET /current/upload/limits/

Returns upload limits based on the user's billing plan and target context.

Query parameters

ParameterTypeRequiredDefaultDescription
actionstringNo"create" or "update" to get limits in context of a target
orgstringNoOrganization ID for limit resolution (used when no action specified)
instance_idstringRequired if action=createTarget workspace or share ID
folder_idstringNoTarget folder OpaqueId or "root"
file_idstringRequired if action=updateFile 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

FieldTypeDescription
response.limits.chunk_sizeintegerMaximum size of a single chunk in bytes
response.limits.sizeintegerMaximum total file size in bytes
response.limits.chunksintegerMaximum number of chunks per upload session
response.limits.sessionsintegerMaximum concurrent active upload sessions
response.limits.sessions_size_maxintegerMaximum aggregate size of all active sessions in bytes

Get restricted file extensions

GET /current/upload/limits/extensions/

Returns restricted and archive file extensions. Authentication is optional.

Query parameters

ParameterTypeRequiredDefaultDescription
planstringNoUser'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

FieldTypeDescription
response.restricted_extensionsstring[]Extensions blocked for the plan
response.archive_extensionsstring[]Archive extensions (only populated if the plan restricts archives)
response.enforcement_enabledbooleanWhether extension restriction enforcement is currently active
response.planstringThe plan used for this response
response.cache_ttlintegerSuggested 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

GET /current/upload/algos/

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

GET /current/upload/{upload_id}/chunk/

Returns information about uploaded chunks for a session.

Query parameters

ParameterTypeRequiredDescription
orderintegerNoSpecific 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"
}

To retrieve a specific chunk, you can also append the chunk number to the path:

GET /current/upload/{upload_id}/chunk/{order}

Returns information about a specific uploaded chunk by path parameter.

Path parameters

ParameterTypeRequiredDescription
{upload_id}stringYesThe upload session ID
{order}integerYesSpecific chunk number to retrieve

Example (single chunk by path)

curl -X GET "https://api.fast.io/current/upload/aBcDeFgHiJkLmNoPqRsT123456/chunk/1" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK, single chunk)

{
  "result": "yes",
  "response": {
    "chunk": {
      "1": 5242880
    }
  },
  "current_api_version": "1.0"
}

Error responses

Error CodeHTTP StatusMessage
1609 (Not Found)404"The supplied chunk not valid or found."

Delete a chunk

DELETE /current/upload/{upload_id}/chunk/?order={n}

Delete a specific chunk from an upload session. Session must be in uploading state.

Query parameters

ParameterTypeRequiredDescription
orderintegerYesThe 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 CodeHTTP StatusMessage
1658 (Not Acceptable)406"The session id provided is not in a valid state to delete a chunk."
1654 (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

Stream upload (unknown file size)

POST /current/upload/                              # Create stream session
  form: name, stream=true, max_size, action=create, instance_id
  -> 201: {id}

POST /current/upload/{id}/stream/                  # Stream file body
  body: raw binary (application/octet-stream)
  -> 201 (auto-finalizes)

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 all chunk info
GET  /current/upload/{id}/chunk/{order}            # Get single chunk info
DELETE /current/upload/{id}/chunk/?order=N          # Delete a chunk

Best Practices

↑ Back to top