Skip to main content
Each project gets isolated object storage. Keys are tenant-relative — you see uploads/report.pdf, never a shared global namespace — and one project can never address another’s objects. Bytes move through short-lived signed URLs, so large uploads and downloads never proxy through the API.

CLI

The signed-URL flow (API / MCP)

Uploading is two steps — create the signed upload, then PUT the bytes:
byteLength must match the upload exactly, and the URL expires quickly — mint it right before sending. Downloads mirror the shape: POST .../storage/downloads with {"key": "..."} returns { url, expiresAt }. Over MCP, use the method and path returned by search:
Full contracts in the Storage API.

From a deployed server

@korve-dev/sdk uses the injected runtime capability to mint the same short-lived upload and download grants without an organization key:
The platform fixes project and environment server-side. A named bucket must already be visible to that project, and its object keys receive a private project/environment prefix. Runtime code cannot list or delete objects. Grants expire after ten minutes; treat the bearer and signed URL as secrets and never persist or log them.

Deleting objects

Deletes are idempotent. Over the raw API the key travels as a single URL-encoded path segment (/ becomes %2F):
The CLI handles encoding; MCP code should URL-encode the key path segment.

Roles and billing

Listing and downloading need member; creating uploads requires active billing; deleting requires admin. Storage meters storage.objects per GB-month. Direct signed-download bytes are not yet exposed as a separate customer usage line. Read the current public amounts and available meters from billing.get; see budgets and usage.