VorcaroFiles
private downloads
New upload
Public API reference

API documentation

Programmatic access to VorcaroFiles. Two HTTP surfaces, plus a couple of browser-facing pages that are not part of the API.

Uploads
/flux/
Resumable upload protocol (tus.io v1). Use this to send files.
JSON API
/api/v1/
Metadata, listing, folder management. Always returns application/json.
Downloads
/d/{file_id}
Binary download. Browser-friendly HTML on GET; raw bytes on POST.
Auth model: the folder URL is its own credential — anyone with /v/{folder_id} can list/modify files in that folder. If a folder has an additional password, pass it in X-Folder-Password for JSON endpoints. Direct file downloads via /d/{file_id} are always open — the file ID alone is the credential.

Upload

Resumable, chunk-based uploads using the tus.io v1 protocol. Send the Tus-Resumable: 1.0.0 header on every request.

post/flux/create upload

Initialize a new upload. The server allocates a tus upload ID and (optionally) creates a new folder.

Required headers

nametypedescription
Tus-ResumablestringMust be 1.0.0
Upload-Lengthint64Total file size in bytes
Upload-MetadatacsvComma-separated key value-base64 pairs (see below)

Upload-Metadata fields

Each value is base64-encoded UTF-8. Example: filename ZmlsZS50eHQ=,encrypt dHJ1ZQ==

keytypedescription
filenamestringOriginal file name
content_typestringMIME type (e.g. image/png)
encryptbooltrue to encrypt the file server-side with password
passwordstringRequired when encrypt=true. Never stored.
ttl_hoursintLifetime in hours. 0 = never. Capped by retention settings unless folder is premium.
folder_idstringAttach to an existing folder. Omit to create a new one.
When uploading to a password-protected folder, the unlock cookie (mf_v_<folder_id>) must be present, or the upload is rejected with 403.

Response — 201 Created

Header Location contains the URL for subsequent PATCH/HEAD/DELETE requests.

Final response — after the last PATCH

JSON body and these headers:

header / json keydescription
X-File-Id / file_idPublic 40+ char file ID (used in /d/<id>)
X-Folder-Id / folder_idParent folder ID
X-Folder-New / folder_newtrue if a new folder was created
X-Download-Url / download_urlAbsolute or relative download URL
X-Folder-Url / folder_urlFolder admin URL — keep secret
expires_at / expires_isoUnix seconds + ISO-8601 UTC expiration

Example

# filename=file.txt, encrypt=true, password=hunter2, ttl_hours=168
curl -i -X POST "http://localhost:8080/flux/" \
    -H "Tus-Resumable: 1.0.0" \
    -H "Upload-Length: 1024" \
    -H "Upload-Metadata: filename ZmlsZS50eHQ=,encrypt dHJ1ZQ==,password aHVudGVyMg==,ttl_hours MTY4"
head/flux/{upload_id}get offset

Returns the current upload offset for resuming. Useful after a network drop.

Response — 200 OK

headerdescription
Upload-OffsetBytes already received by the server
Upload-LengthTotal expected size
patch/flux/{upload_id}send chunk

Sends a chunk of bytes starting at Upload-Offset. Body is raw binary.

Required headers

namevalue
Tus-Resumable1.0.0
Upload-OffsetByte offset where this chunk begins
Content-Typeapplication/offset+octet-stream

Returns 204 No Content. On the final chunk, returns 200 OK with the headers/body documented in POST /flux/.

delete/flux/{upload_id}terminate

Aborts an in-progress upload and discards every byte uploaded so far. Returns 204 No Content.

Folder API

Manage folder content programmatically. All responses are application/json.

No password set? Any holder of the folder ID can call these endpoints.
Password set? Send X-Folder-Password: <password> on every request. Wrong/missing password → 401.
get/api/v1/folders/{id}folder + file list

Returns folder metadata and the list of non-deleted files inside.

Response — 200 OK

{
  "id": "3kQ...",
  "created_day": 20596,
  "file_count": 2,
  "total_bytes": 2048,
  "premium": false,
  "password_set": true,
  "password_set_day": 20597,
  "files": [ /* array of file objects */ ]
}
delete/api/v1/folders/{id}delete folder

Permanently deletes the folder and every file inside. The on-disk blobs are removed.

{
  "deleted": true,
  "folder_id": "3kQ...",
  "files_deleted": 2
}
delete/api/v1/folders/{id}/files/{file_id}delete a file

Removes a single file from the folder. The file_id must belong to the given folder, otherwise 404.

post/api/v1/folders/{id}/files/{file_id}/regeneratenew download URL

Generates a new public file ID. The old /d/{old_file_id} URL stops working immediately.

The underlying encrypted blob is not moved or re-encrypted — only the URL token rotates.

Rate limit: 1 regeneration per hour per file. Returns 429 Too Many Requests otherwise.

Response — 200 OK

{
  "file_id": "newPublicId...",
  "old_file_id": "oldPublicId...",
  "download_url": "/d/newPublicId..."
}
post/api/v1/folders/{id}/passwordset / change / remove

Manages the folder password (Argon2id, irrecoverable). To change an existing password, you still send the current one in X-Folder-Password.

Request body

{ "new_password": "hunter2" }  // or "" to remove

Minimum 4 characters. Removing the password makes the folder publicly accessible again (still requires the folder ID).

File API

Lookup file metadata by its public ID. No password needed — the file ID itself is the credential.

get/api/v1/files/{id}metadata

Returns metadata only (no binary). Use POST /d/{id} to download the bytes.

Response — 200 OK

{
  "id": "V5pY...",
  "original_name": "file.txt",
  "content_type": "text/plain",
  "size_bytes": 1024,
  "encrypted": true,
  "cipher": "age-v1",
  "download_count": 0,
  "expires_at": 1779494400,
  "expires_iso": "2026-05-22T18:00:00Z",
  "created_day": 20596,
  "download_url": "/d/V5pY..."
}

Note: The parent folder_id is intentionally not exposed here. Anyone with the file ID can fetch metadata, but they should not learn which folder it belongs to.

Download

For programmatic downloads, use POST — it streams the raw bytes as Content-Disposition: attachment. The GET variant returns an HTML page meant for browsers (with a password prompt if the file is encrypted) and is not considered API.

post/d/{file_id}stream bytes

Request body (optional)

Form field password is required when the file is encrypted, ignored otherwise.

password=hunter2

Response

  • 200 OK — binary stream of the file
  • 401 Unauthorized — missing or wrong password
  • 404 Not Found — file expired, deleted, or unknown

Example

curl -X POST "http://localhost:8080/d/V5pY..." \
    -d "password=hunter2" \
    -o file.txt

Errors

All JSON endpoints return errors as {"error": "...", "code": "..."} with these status codes.

statusmeaning
400Invalid form data or malformed headers
401Wrong or missing password (file encryption or folder password)
403Folder is locked and the unlock cookie is missing
404Resource not found, expired, or already deleted
405HTTP method not allowed on this endpoint
413Upload exceeds upload.max_size_bytes (non-premium folders only)
421Misdirected request — host header doesn't match the configured domain
429Rate limited (e.g. link regeneration capped at 1/hour per file)
500Internal server error