VirtualDrive Cloud docs
Object storage for developers and AI agents. Add file storage to any app in minutes.
Quickstart
Create a project in the dashboard, generate an API key, then install the SDK:
npm install @virtualdrive/cloudimport { VirtualDrive } from "@virtualdrive/cloud";
const vd = new VirtualDrive(process.env.VD_API_KEY);
const file = await vd.files.upload({ name: "hello.txt", data: "hi!" });
console.log(file.url);Authentication
Every request authenticates with a project API key sent as a Bearer token. Keys are scoped to a single project and a set of permissions (files:read, files:write, files:delete). Keys are shown once at creation — store them as a secret.
Authorization: Bearer vdk_live_xxxxxxxxxxxxxxxxUpload a file
Upload bytes directly, or request a presigned URL for large/browser-direct uploads.
curl https://api.virtualdrive.cloud/v1/files \
-H "Authorization: Bearer $VD_API_KEY" \
-F "name=report.pdf" \
-F "file=@report.pdf"Download & signed URLs
Every file can be served via a short-lived signed URL. Nothing is public by default.
const { url } = await vd.files.signedUrl(fileId, { expiresIn: 3600 });List & delete
const { files } = await vd.files.list({ prefix: "invoices/" });
await vd.files.delete(fileId);Framework examples
A few common integrations. All use the JS SDK; keep your key server-side.
Next.js — route handler
// app/api/upload/route.ts
import { VirtualDrive } from "@virtualdrive/cloud";
const vd = new VirtualDrive(process.env.VD_API_KEY!);
export async function POST(req: Request) {
const form = await req.formData();
const file = form.get("file") as File;
const stored = await vd.files.upload({
name: file.name,
data: await file.arrayBuffer(),
contentType: file.type,
});
return Response.json({ url: stored.url });
}Express
import express from "express";
import { VirtualDrive } from "@virtualdrive/cloud";
const vd = new VirtualDrive(process.env.VD_API_KEY);
app.post("/upload", async (req, res) => {
const file = await vd.files.upload({ name: req.body.name, data: req.body.data });
res.json({ url: file.url });
});Swift (iOS / macOS)
import VirtualDrive
let vd = VirtualDrive(apiKey: ProcessInfo.processInfo.environment["VD_API_KEY"]!)
let file = try await vd.files.upload(name: "photo.jpg", data: imageData, contentType: "image/jpeg")
print(file.url)Swift Package: add this repo's sdk-swift via Swift Package Manager (iOS 15+ / macOS 12+). Keep the key server-side for shipped apps; use a short-lived key or proxy for clients.
Browser
Never put your API key in the browser. Upload through your server (examples above), or have the server return a signed URL for the client to use.
MCP server
Connect any AI agent to your storage over the Model Context Protocol. Point your MCP client at the hosted endpoint with a project key, or run the local shim:
npx @virtualdrive/mcp --key $VD_API_KEY
# Tools exposed: list_files, read_file, write_file, delete_fileLLM-readable API summary: /developers/llms.txt
Webhooks
Register an endpoint in the dashboard to receive events: file.uploaded, file.deleted. Each delivery is a POST with an HMAC-SHA256 signature so you can verify it came from us.
// Headers on every delivery:
// X-VD-Event: file.uploaded
// X-VD-Signature: sha256=<hex>
// Verify (Node):
import crypto from "crypto";
const sig = "sha256=" + crypto.createHmac("sha256", WHSEC).update(rawBody).digest("hex");
if (sig !== req.headers["x-vd-signature"]) throw new Error("bad signature");
// Body: { "event": "file.uploaded", "created": "...",
// "data": { "id": "...", "name": "...", "size": 1234 } }Errors & limits
Standard HTTP status codes. 401 invalid key · 403 scope/quota · 413 file too large · 429 rate limited · 503 service paused. Usage is metered per project (stored bytes + requests); a generous free tier is included at launch.
VirtualDrive Cloud is in early access.
APIs may change before GA. Join the waitlist to get your keys first.