# Disk — Personal Cloud Storage for AI Agents Base URL: https://disk.zaynjarvis.com API: https://disk.zaynjarvis.com/api/v1 MCP: https://disk.zaynjarvis.com/mcp ## Authentication All API requests require: Authorization: Bearer $DISK_KEY - Root key (env.ROOT_KEY): full admin access, can create/revoke keys, see full audit - Admin keys (role=admin): root-equivalent, but revocable — an agent given an admin key can manage keys and see all audit/shares - User keys (dk_<32 base62>): scoped by prefix + permission (ro or rw), and an optional per-file upload cap (maxUploadBytes) - Virtual root: a scoped key sees its prefix AS the root — you send and receive scope-relative paths and never include the prefix. A key scoped to agents/x/ that writes "notes/a.txt" stores agents/x/notes/a.txt; it lists "/" and sees "notes/". You cannot escape your scope. - 401 = bad token, 403 = read-only / non-admin, 413 = file over maxUploadBytes ## Quick Reference | Operation | Method | Endpoint | |-----------|--------|----------| | Verify key | GET | /api/v1/auth/verify | | List folder | GET | /api/v1/files?prefix= | | Search | GET | /api/v1/files?search= | | Stat object | GET | /api/v1/files/stat?path= | | Download | GET | /api/v1/files/blob?path= | | Preview (inline) | GET | /api/v1/files/blob?path=&inline=1 | | Upload (≤90MiB) | PUT | /api/v1/files/blob?path= | | Create folder | POST | /api/v1/files/mkdir | | Delete | POST | /api/v1/files/delete | | Move | POST | /api/v1/files/move | | Multipart create | POST | /api/v1/files/multipart/create | | Multipart part | PUT | /api/v1/files/multipart/part?path=&uploadId=&partNumber= | | Multipart complete | POST | /api/v1/files/multipart/complete | | Multipart abort | POST | /api/v1/files/multipart/abort | | Create share | POST | /api/v1/shares | | List shares | GET | /api/v1/shares | | Revoke share | DELETE | /api/v1/shares/:id | | List keys (admin) | GET | /api/v1/keys | | Create key (admin) | POST | /api/v1/keys | | Revoke key (admin) | DELETE | /api/v1/keys/:id | | Audit log | GET | /api/v1/audit | | Usage stats | GET | /api/v1/usage | ## curl Examples ### Verify your key curl -s https://disk.zaynjarvis.com/api/v1/auth/verify \ -H "Authorization: Bearer $DISK_KEY" ### List root folder curl -s https://disk.zaynjarvis.com/api/v1/files \ -H "Authorization: Bearer $DISK_KEY" ### List a subfolder curl -s "https://disk.zaynjarvis.com/api/v1/files?prefix=projects/alpha/" \ -H "Authorization: Bearer $DISK_KEY" ### Search files recursively curl -s "https://disk.zaynjarvis.com/api/v1/files?search=report&prefix=docs/" \ -H "Authorization: Bearer $DISK_KEY" ### Stat a file curl -s "https://disk.zaynjarvis.com/api/v1/files/stat?path=docs/readme.md" \ -H "Authorization: Bearer $DISK_KEY" ### Download a file curl -s "https://disk.zaynjarvis.com/api/v1/files/blob?path=docs/report.pdf" \ -H "Authorization: Bearer $DISK_KEY" -o report.pdf ### Preview inline (image/video/text) curl -s "https://disk.zaynjarvis.com/api/v1/files/blob?path=photos/sunset.jpg&inline=1" \ -H "Authorization: Bearer $DISK_KEY" ### Download a byte range curl -s "https://disk.zaynjarvis.com/api/v1/files/blob?path=bigfile.bin" \ -H "Authorization: Bearer $DISK_KEY" -H "Range: bytes=0-1023" ### Upload a small file curl -X PUT "https://disk.zaynjarvis.com/api/v1/files/blob?path=uploads/notes.txt" \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: text/plain" \ --data-binary @notes.txt ### Create a folder curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/mkdir \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"projects/new-app"}' ### Delete files/folders curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/delete \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"paths":["old-notes.txt","archive/"]}' ### Move a file curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/move \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"from":"drafts/doc.md","to":"published/doc.md"}' ### Move a folder (subtree) curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/move \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"from":"work/","to":"archive/work/"}' ### Multipart: create upload curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/multipart/create \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"big-archive.zip","contentType":"application/zip"}' ### Multipart: upload a part curl -X PUT "https://disk.zaynjarvis.com/api/v1/files/multipart/part?path=big-archive.zip&uploadId=UPLOAD_ID&partNumber=1" \ -H "Authorization: Bearer $DISK_KEY" \ --data-binary @part1.bin ### Multipart: complete curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/multipart/complete \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"big-archive.zip","uploadId":"UPLOAD_ID","parts":[{"partNumber":1,"etag":"ETAG1"}]}' ### Multipart: abort curl -s -X POST https://disk.zaynjarvis.com/api/v1/files/multipart/abort \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"big-archive.zip","uploadId":"UPLOAD_ID"}' ### Create a share link curl -s -X POST https://disk.zaynjarvis.com/api/v1/shares \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"path":"docs/brochure.pdf","ttlSeconds":86400}' ### List shares curl -s https://disk.zaynjarvis.com/api/v1/shares \ -H "Authorization: Bearer $DISK_KEY" ### Revoke a share curl -s -X DELETE https://disk.zaynjarvis.com/api/v1/shares/s_abc123 \ -H "Authorization: Bearer $DISK_KEY" ### Create an API key (admin only) # Scoped user key with a 10 MiB per-file upload cap: curl -s -X POST https://disk.zaynjarvis.com/api/v1/keys \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"my-agent","prefix":"agents/","permission":"rw","expiresDays":30,"maxUploadBytes":10485760}' # Admin key (root-equivalent, revocable) — lets an agent act as administrator: curl -s -X POST https://disk.zaynjarvis.com/api/v1/keys \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"admin-agent","role":"admin"}' ### List keys (admin only) curl -s https://disk.zaynjarvis.com/api/v1/keys \ -H "Authorization: Bearer $DISK_KEY" ### Revoke a key (admin only) — soft; key stops working, row kept curl -s -X DELETE https://disk.zaynjarvis.com/api/v1/keys/k_abc123 \ -H "Authorization: Bearer $DISK_KEY" ### Permanently delete a revoked key (admin only) — frees the name for reuse curl -s -X DELETE "https://disk.zaynjarvis.com/api/v1/keys/k_abc123?hard=1" \ -H "Authorization: Bearer $DISK_KEY" ### View audit log (root sees all; keys see own) curl -s "https://disk.zaynjarvis.com/api/v1/audit?action=file.download&limit=50" \ -H "Authorization: Bearer $DISK_KEY" ### Audit log as CSV curl -s "https://disk.zaynjarvis.com/api/v1/audit?format=csv" \ -H "Authorization: Bearer $DISK_KEY" -o audit.csv ### Get usage stats curl -s https://disk.zaynjarvis.com/api/v1/usage \ -H "Authorization: Bearer $DISK_KEY" ## MCP Server Endpoint: https://disk.zaynjarvis.com/mcp Protocol: MCP streamable HTTP (JSON-RPC 2.0, single POST, no SSE) Auth: Authorization: Bearer $DISK_KEY (same as REST) Tools: disk_list, disk_stat, disk_read, disk_write, disk_delete, disk_move, disk_share, and (admin keys only) disk_key_create, disk_key_list, disk_key_revoke (pass hard:true to permanently delete a revoked key). An agent holding an admin key can manage API keys entirely over MCP. File tools take scope-relative paths. Example MCP tools/list: curl -s -X POST https://disk.zaynjarvis.com/mcp \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' Example MCP tools/call: curl -s -X POST https://disk.zaynjarvis.com/mcp \ -H "Authorization: Bearer $DISK_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"disk_list","arguments":{"prefix":"docs/"}}}' ## Notes - Paths have NO leading slash: "docs/file.txt" not "/docs/file.txt" - Folders are zero-byte objects ending with "/": "projects/" is a folder marker - Timestamps are unix milliseconds everywhere - Bulk delete accepts 1-200 paths; folder paths (ending "/") delete the entire subtree - Multipart: parts must be >= 5 MiB (except last), max 10000 parts - Error shape: {"error":{"code":"snake_case","message":"human description"}}