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 made public or shared, 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

FreeProTeam
Archive uploadsNot availableYesYes
Max size per fileNot available10 GB10 GB
archives:create per dayNot available50100
Counts against storage quotaNot availableYesYes

A file is refused before any bytes move when live storage plus recoverable trash plus other uploads still in progress plus the declared archive bytes would exceed the cap. The STORAGE_LIMIT billing response includes combined current usage, the trash-only amount, pricing, and an upgrade URL. Storage add-on space counts toward the cap only while the subscription is paid (see Trash and storage accounting).

If your plan lapses

Archives follow the same clock as images and video. When the plan that pays for an archive drops to Free (cancelled, or unpaid after a failed payment), the archive stays downloadable for 14 days. From day 14 it is locked: every download route, including the CLI, the API, MCP and a custom domain, answers not found, and the dashboard shows it as locked. After 28 days it is permanently deleted. Restoring the plan before then brings it straight back. A workspace archive follows the workspace's Team plan, not the plan of the person who uploaded it.

Deleting an archive moves it to charged trash for 7 days. Other items, including folders and non-archive pages, stay in trash for 30 days. The archive object is removed only when it expires or Empty trash permanently purges it.

Archive vs a normal upload

Two things are decided independently:

  1. 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 .html you do not want rendered), opt in explicitly with the "store as file" option (--store-as-file on the CLI, as_archive on the API).
  2. 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:

FlagDescription
--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-fileStore 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)
--jsonForce 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. Move it to recoverable trash like any other page:

sharedrop delete <id>

The archive remains charged while it is recoverable. Permanently clear the authenticated caller's trash only when that deletion is intended:

sharedrop trash empty

The command is irreversible and releases the retained bytes after the guarded row deletion. Archives expire automatically after 7 days. Other items expire after 30 days.

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 Connector (MCP) for connecting an agent.

An agent uploads a large file like this:

  1. create_archive_upload with filename and size_bytes (optionally folder_id / folder_path, workspace, or a reservation_id to claim a reserved address). The response is a transport plan plus an instructions string 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_url with the upload_token, then call finalize_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).
  2. sign_archive_parts (multipart only) with the page_id. Returns fresh presigned parts URLs for the parts still outstanding, plus the uploaded parts already received (so a resumed upload skips them). PUT each part's byte range directly to its URL with only a Content-Length header, and capture the returned ETag.
  3. complete_archive with the page_id and the { part_number, etag } list. Returns the finished page and a download_url. This step is idempotent: a retried complete returns the same result without double-charging quota.
  4. abort_archive with the page_id if anything goes wrong. Releases the reserved quota. Also used to clear a MULTIPART_IN_PROGRESS error (one in-flight archive per account): the error returns the stuck page_id to 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.

Use delete_page to move a finished archive into charged trash. Use the empty_trash tool only with clear intent to permanently remove the trash (pass workspace for a workspace's trash). Archives stay recoverable for 7 days; other items stay recoverable for 30 days.

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):

FieldTypeRequiredDescription
filenamestringYesFile name including extension
size_bytesnumberYesExact byte size of the file
workspacestringNoUpload to a specific workspace
folder_idstringNoFolder to file the archive into
reservation_idstringNoClaim a reserved address
as_archivebooleanNoStore 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 (pass as_archive: true to store it anyway)
  • 402 TIER_LIMIT: Archives require a Pro plan or higher
  • 402 FILE_SIZE_EXCEEDED: File exceeds your plan's per-file archive ceiling
  • 402 STORAGE_LIMIT: File exceeds your remaining storage quota
  • 409 MULTIPART_IN_PROGRESS: You already have an archive upload in flight. The response carries its page_id and abort_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. An archive whose paying plan lapsed more than 14 days ago also returns 404, for the owner too, until the plan is restored (see If your plan lapses).

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 moves the archive row and retained object to charged trash:

curl -X DELETE \
  -H "Authorization: Bearer sd_..." \
  https://sharedrop.cloud/api/v1/pages/550e8400-...

To permanently remove the authenticated caller's trash:

curl -X DELETE \
  -H "Authorization: Bearer sd_..." \
  https://sharedrop.cloud/api/trash

That DELETE /api/trash response contains success, purged, and freedBytes. It is irreversible. Archives otherwise expire from trash after 7 days; other items expire after 30 days.

Workspace storage meters and new-write gates charge all trash in the workspace. In a workspace's trash (?workspace_id=), an owner removes every item, a member only the items they created plus the trashed folders.

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.