Fileexchange is transfer infrastructure for teams that ship datasets, masters and builds across networks they do not control. Chunked, resumable, encrypted before it leaves the machine — and driven entirely by an API you can read in one sitting.
Hotel Wi-Fi, a mobile hotspot, a corporate proxy that resets long connections. The failure modes are boring and well understood — so we designed around them instead of asking people to try again.
Every transfer is chunked and content-addressed. A dropped connection resumes at the last verified block, not at zero — on any network, on any device.
Objects are encrypted client-side before the first byte leaves the machine. Keys never reach our infrastructure, and neither does plaintext.
Uploads land on the nearest of 31 edge locations and replicate over private backbone, so a transfer between two continents does not cross the public internet twice.
Links expire by time, by download count, or on first open. Expired objects are erased within the retention window, not merely hidden.
The dashboard is a client of the same public API you get. Anything you can click, you can script — including bulk issuance and revocation.
Every issue, open, download and revoke is written to an append-only log with the requesting key, address family and user agent.
No SDK required. The reference client is 300 lines of Go and the protocol is plain HTTP with checksums.
Post the manifest — filenames, sizes and checksums. You get an upload session and a set of presigned block endpoints.
Upload blocks in any order, in parallel, from as many workers as you like. Re-uploading an identical block is a no-op.
Sealing the session returns a share URL with the policy you set: lifetime, download ceiling, password, allowed networks.
# 1 — open a session with the manifest
curl -sS https://api.fileexchange.site/v2/transfers \
-H "Authorization: Bearer $FX_KEY" \
-H "Content-Type: application/json" \
-d '{"files":[{"name":"build.tar.zst","size":4831838208,"sha256":"9f4c…"}],
"policy":{"expires_in":86400,"max_downloads":3}}'
# 2 — push blocks, any order, any number of workers
curl -sS --upload-file block-0007.bin "$UPLOAD_URL&block=7"
# 3 — seal and get the share link
curl -sS -X POST https://api.fileexchange.site/v2/transfers/$ID/seal \
-H "Authorization: Bearer $FX_KEY"import { Fileexchange } from "@fileexchange/client";
const fx = new Fileexchange({ key: process.env.FX_KEY });
const t = await fx.transfers.create({
files: ["./build.tar.zst", "./manifest.json"],
policy: { expiresIn: "24h", maxDownloads: 3 },
// resumes from the last verified block automatically
onProgress: (p) => process.stdout.write(`\r${p.percent}%`),
});
console.log(t.shareUrl); // https://fileexchange.site/t/9f4c1afrom fileexchange import Client
fx = Client(key=os.environ["FX_KEY"])
with fx.transfer(expires_in="24h", max_downloads=3) as t:
t.add("build.tar.zst") # streamed, never buffered
t.add("manifest.json")
# blocks are content-addressed: identical blocks upload once
print(t.share_url)Encryption happens in the client, before the first byte is sent. We store ciphertext, block hashes and sizes. That is the whole picture on our side.
Derived per transfer, never transmitted, never recoverable by us.
Identical blocks upload once — across files and across transfers.
Time, download count, password and network range, set per link.
Throughput, retries and block state exposed on the same API.
No card, no sales call. The free tier is the same infrastructure with a smaller ceiling.
See the plans