Upload Flow
Tusky uses a presigned URL flow for file uploads. This keeps file bytes off the API server and uploads directly to object storage.
Overview
Section titled “Overview”-
Request upload — Call the API to get a presigned URL and file ID.
-
Upload bytes — PUT the file bytes directly to the presigned URL.
-
Confirm — Tell the API the upload is complete. Status moves to
hot.
Using the SDK (recommended)
Section titled “Using the SDK (recommended)”The SDK wraps all three steps into a single call:
import { TuskyClient } from '@tuskydp/sdk';import { readFile } from 'fs/promises';
const tusky = new TuskyClient({ apiKey: 'tdp_your_key' });
const data = await readFile('./report.pdf');const file = await tusky.files.upload({ name: 'report.pdf', mimeType: 'application/pdf', vaultId: 'vault-uuid', data,});
console.log(file.status); // "hot"import requests
API = "https://api.opentusk.ai"headers = {"Authorization": "Bearer tdp_your_key"}
# Step 1: Request presigned URLupload = requests.post(f"{API}/api/files/upload", headers=headers, json={ "name": "report.pdf", "mimeType": "application/pdf", "sizeBytes": 204800, "vaultId": "vault-uuid",}).json()
# Step 2: PUT byteswith open("report.pdf", "rb") as f: requests.put(upload["uploadUrl"], data=f.read(), headers={ "Content-Type": "application/pdf", })
# Step 3: Confirmfile = requests.post( f"{API}/api/files/{upload['fileId']}/confirm", headers=headers,).json()
print(file["status"]) # "hot"Manual 3-step upload
Section titled “Manual 3-step upload”If you’re not using the SDK, here’s each step in detail.
Step 1: Request upload
Section titled “Step 1: Request upload”POST /api/files/upload{ "name": "report.pdf", "mimeType": "application/pdf", "sizeBytes": 204800, "vaultId": "vault-uuid"}Response:
{ "fileId": "file-uuid", "uploadUrl": "https://spaces.example.com/...?X-Amz-Signature=..."}Step 2: Upload bytes
Section titled “Step 2: Upload bytes”PUT the raw file bytes to the uploadUrl. Set the Content-Type header to match the MIME type:
curl -X PUT "https://spaces.example.com/...?X-Amz-Signature=..." \ -H "Content-Type: application/pdf" \ --data-binary @report.pdfStep 3: Confirm upload
Section titled “Step 3: Confirm upload”POST /api/files/{fileId}/confirmThe API verifies the file exists in storage and updates the status to hot. A background job is queued to sync the file to Walrus.
What happens after upload
Section titled “What happens after upload”- File status is
hot— available for immediate download from the hot cache - The Walrus sync worker picks up the job and publishes to the Walrus network
- Status changes to
syncedonce confirmed on Walrus - Eventually, the hot eviction worker removes the hot cache copy (status →
cold)
Track these transitions with webhooks or SDK polling.
Encrypted uploads (private vaults)
Section titled “Encrypted uploads (private vaults)”For private vaults, the client must encrypt the file before uploading. See the encryption guide for details. The upload flow is the same — you just upload encrypted bytes and include the encryption metadata (wrappedKey, encryptionIv, plaintextSizeBytes, plaintextChecksumSha256) in the request.