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 file--10 GB10 GB
archives:create per day--50100
Counts against storage quota--YesYes

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:

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

  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.

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.

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.