Archives
Archives let you store a large file as a download-only artefact: a database dump, a .zip of generated assets, a build tarball, a big model export. The bytes stream directly to dedicated storage, you get a stable page URL, and anyone you authorise downloads it back byte for byte.
Archives are deliberately narrow:
- Download-only. An archive is never rendered, never viewed in the sandbox, and has no in-browser preview. It exists to be downloaded.
- Private-only. An archive is always
private. It cannot be madepublicorshared, and it cannot be put behind a public or disappearing link. Any attempt to change its visibility is refused. - Pro and Team only. Archive uploads require a Pro plan or higher. They count against your storage quota.
If you want a file that renders in the browser (HTML, PDF, an image, Markdown), use a normal upload instead. Archives are for bytes you want to store and hand back, not display.
Limits
| Free | Pro | Team | |
|---|---|---|---|
| Archive uploads | Not available | Yes | Yes |
| Max size per file | -- | 10 GB | 10 GB |
archives:create per day | -- | 50 | 100 |
| Counts against storage quota | -- | Yes | Yes |
A file larger than your remaining storage quota is refused before any bytes move, with a billing error you can act on.
Archive vs a normal upload
Two things are decided independently:
- Kind (archive or a rendered page) is something you declare, never something inferred from size. By default a file is treated as an archive when its extension is one of
.zip,.tar,.gz,.tgz,.sql, or.sql.gz. To store any other file as a download-only blob (a 500 MB.csv, a large.htmlyou do not want rendered), opt in explicitly with the "store as file" option (--store-as-fileon the CLI,as_archiveon the API). - Transport is decided by size alone. Files 30 MB or smaller upload in a single streamed PUT. Files larger than 30 MB upload in parts (multipart), so a 10 GB file never has to fit in one request or in memory.
You rarely have to think about transport: the CLI, the MCP tools, and the dashboard all pick the right lane for you. It matters only if you call the REST API directly.
Dashboard
Drag a large file onto the dashboard drop zone and Sharedrop routes it for you:
-
A recognised archive (
.zip,.tar, and friends) uploads as an archive. -
A renderable file that is over your plan's render ceiling is not silently dropped. You get a prompt offering to store it as a downloadable file instead.
-
A file larger than 30 MB cannot be uploaded from the browser. The drop zone shows a ready-to-copy command instead:
sharedrop archive '/path/to/your-file.zip'Copy it, run it in your terminal, and the archive lands in the same account.
An archive's page in the dashboard is a download card: the file name, its size, and a Download button. There is no preview, no share tab, and no visibility control, because none of those apply to a private download-only file. You can rename it, move it into a folder, and delete it.
CLI
Requires @sharedrop/cli 1.8.0 or newer. See the CLI guide for installation and authentication.
sharedrop archive
Upload a large file as a download-only archive.
sharedrop archive <file> [options]
The CLI streams the file straight to storage and automatically uses the multipart lane for files over 30 MB, resuming part by part. A 10 GB file is streamed from disk, never buffered in memory. Press Ctrl-C mid-upload and the CLI aborts the multipart cleanly so it does not hold your quota.
Options:
| Flag | Description |
|---|---|
--title <string> | Page title (default: derived from the file name) |
--folder <id|path> | File the archive into a folder in your Sharedrop tree. Accepts a folder id or a slash path like backups/2026, auto-creating missing segments |
--workspace <id> | Upload to a specific workspace |
--store-as-file | Store any file as a download-only archive, bypassing the archive-extension check. Use it for a large non-archive file (a big .csv, .html, or .log) |
--json | Force JSON output |
Examples:
# A database dump
sharedrop archive backup.sql.gz --title "Nightly DB backup"
# A 4 GB build tarball into a folder
sharedrop archive dist.tar.gz --folder builds/2026
# A large non-archive file, stored download-only
sharedrop archive huge-export.csv --store-as-file
Human output prints the page ID, the size, and the exact download command. --json returns { "data": { "id", "size_bytes", "download_url" } }.
Downloading and deleting
Download an archive with the standard download command, which is archive-aware:
sharedrop download <id> -o backup.sql.gz
For an archive, download streams the raw stored bytes to disk (not a zip wrapper). You can download an archive you own. Delete it like any other page:
sharedrop delete <id>
Deleting an archive removes the stored object from archive storage as well as the page row.
Archives cannot be re-uploaded over. To replace one, delete it and upload a new archive.
MCP
The archive tools appear only when the connected account is on a plan that allows archives (Pro or Team). A free-tier agent never sees them. See MCP Setup for connecting an agent.
An agent uploads a large file like this:
create_archive_uploadwithfilenameandsize_bytes(optionallyfolder_id/folder_path,workspace, or areservation_idto claim a reserved address). The response is a transport plan plus aninstructionsstring telling the agent exactly what to do next.- For a file 30 MB or smaller the plan is the single lane: PUT the bytes to
upload_urlwith theupload_token, then callfinalize_upload(the same finalize used for normal uploads). - For a larger file the plan is multipart: it returns
page_id, the part size, and the part count (but no part URLs yet).
- For a file 30 MB or smaller the plan is the single lane: PUT the bytes to
sign_archive_parts(multipart only) with thepage_id. Returns fresh presignedpartsURLs for the parts still outstanding, plus theuploadedparts already received (so a resumed upload skips them). PUT each part's byte range directly to its URL with only aContent-Lengthheader, and capture the returnedETag.complete_archivewith thepage_idand the{ part_number, etag }list. Returns the finishedpageand adownload_url. This step is idempotent: a retried complete returns the same result without double-charging quota.abort_archivewith thepage_idif anything goes wrong. Releases the reserved quota. Also used to clear aMULTIPART_IN_PROGRESSerror (one in-flight archive per account): the error returns the stuckpage_idto abort.
sign_archive_parts and abort_archive exist as tools because the underlying routes need a credential the hosted agent does not hold, so the MCP server proxies them on the agent's behalf.
The download_url returned by complete_archive (and by the single-lane finalize) is a short-lived link the agent can hand back to the user.
REST API
Archive routes live under https://sharedrop.cloud/api/archives. Authenticate with a Bearer API key (sd_...), the same as the rest of the API. Write steps need a pages:write key; downloading needs only pages:read.
Zero object bytes pass through Sharedrop's servers: every step returns a presigned URL that you PUT to (or GET from) directly.
Start an upload
POST /api/archives/create
The single decision point. It runs the tier, size, and quota gates and returns the transport plan.
Request Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | File name including extension |
size_bytes | number | Yes | Exact byte size of the file |
workspace | string | No | Upload to a specific workspace |
folder_id | string | No | Folder to file the archive into |
reservation_id | string | No | Claim a reserved address |
as_archive | boolean | No | Store any file as an archive, skipping the archive-extension check |
curl -X POST \
-H "Authorization: Bearer sd_..." \
-H "Content-Type: application/json" \
-d '{"filename": "backup.sql.gz", "size_bytes": 48219033}' \
https://sharedrop.cloud/api/archives/create
Response for a file 30 MB or smaller (single lane):
{
"transport": "single",
"upload_url": "https://uploads.sharedrop.cloud/...",
"upload_token": "...",
"finalize_url": "https://sharedrop.cloud/api/upload/finalize",
"object_key": "..."
}
PUT the bytes to upload_url (Bearer upload_token), then finalize with the same /api/upload/finalize call used for normal uploads. The archive kind is bound into the signed token, so the finished page is a private download-only archive.
Response for a larger file (multipart):
{
"transport": "multipart",
"page_id": "550e8400-...",
"upload_id": "...",
"part_size_bytes": 67108864,
"part_count": 3,
"sign_parts_url": "https://sharedrop.cloud/api/archives/550e8400-.../sign-parts",
"complete_url": "https://sharedrop.cloud/api/archives/550e8400-.../complete",
"abort_url": "https://sharedrop.cloud/api/archives/550e8400-.../abort",
"effective_cap_bytes": 10737418240
}
Error Cases:
400 VALIDATION_ERROR-- Invalid body, or a file type that is not an allowed archive (passas_archive: trueto store it anyway)402 TIER_LIMIT-- Archives require a Pro plan or higher402 FILE_SIZE_EXCEEDED-- File exceeds your plan's per-file archive ceiling402 STORAGE_LIMIT-- File exceeds your remaining storage quota409 MULTIPART_IN_PROGRESS-- You already have an archive upload in flight. The response carries itspage_idandabort_url
Sign parts (multipart)
POST /api/archives/:id/sign-parts
Mint fresh presigned URLs for the parts still outstanding. Optional body { "part_numbers": [1, 2] } limits it to specific parts; omit it to sign every remaining part. Safe to call repeatedly, which is how a resumed upload works.
{
"parts": [{ "part_number": 1, "url": "https://..." }],
"uploaded": [{ "part_number": 2, "etag": "\"abc...\"" }],
"part_size_bytes": 67108864
}
PUT each part's byte range directly to its url with a Content-Length header (no auth header), and keep the ETag from each response.
Complete or abort (multipart)
POST /api/archives/:id/complete
Body { "parts": [{ "part_number": 1, "etag": "..." }] } with every uploaded part. Sharedrop verifies the real object size against what you declared, reconciles it against your quota, and flips the archive live.
{
"page": { "id": "550e8400-...", "slug": "abc123", "kind": "archive", "status": "active", "file_size": 48219033 },
"download_url": "https://..."
}
Complete is idempotent: retrying after success returns the same result without completing twice or double-charging quota.
POST /api/archives/:id/abort
No body. Cancels the multipart upload and releases the reserved quota. Idempotent. Aborting an already-completed upload returns 409.
Download
GET /api/archives/:id/download
Returns a 302 redirect to a short-lived presigned link that streams the raw bytes as an attachment. Needs only a pages:read key. You can download an archive you own; anything else returns 404 so existence is never leaked.
curl -L -H "Authorization: Bearer sd_..." \
https://sharedrop.cloud/api/archives/550e8400-.../download \
-o backup.sql.gz
Delete
Archives use the standard page delete, which removes the stored object as well as the row:
curl -X DELETE \
-H "Authorization: Bearer sd_..." \
https://sharedrop.cloud/api/v1/pages/550e8400-...
Why archives are private-only
An archive is opaque stored bytes, not a page Sharedrop has sanitised and understood. Serving it publicly would mean handing arbitrary bytes to anyone with the link, so archives are held to the safest posture: private, owner-download-only, no public or shared links. Attempting to change an archive's visibility, add an access grant, or mint a disappearing link returns:
Archives are private only. Sharing is not available for this file.
Renaming, moving into a folder, and deleting all stay available.