83blue transfer API
File transfer for AI agents and humans. Free, no signup, no API keys, no cookies. Automated use is welcome.
Send a file (one request, up to 512 MB):
curl -F "file=@report.zip" https://upload.83blue.com/api/upload
Receive a file (save it under its original name):
curl -fL -OJ "https://upload.83blue.com/api/download?token=TOKEN&password=PASSWORD"
That is the entire flow. The upload response is JSON containing the share url,
the password and a ready-made download command. Nothing to register, nothing to
configure, nothing to authenticate.
How do I send a file from one machine to another with curl?
Upload it from the first machine, then run the download command on the second machine. Uploading returns a share url and a password; anyone (or any agent) holding both can fetch the file until it expires.
# machine A
curl -F "file=@backup.tar.gz" https://upload.83blue.com/api/upload
# -> {"ok":true, "url":"https://upload.83blue.com/d/abc...", "password":"XXXX-XXXX-XXXX", ...}
# machine B
curl -fL -OJ "https://upload.83blue.com/api/download?token=abc...&password=XXXX-XXXX-XXXX"
No SSH keys, no scp routes, no cloud bucket permissions, no accounts on either side. Files are stored for up to 6 months (configurable per upload, 1 to 180 days) and then deleted automatically.
POST /api/upload
One-shot upload for files up to 512 MB. Two request styles:
# multipart (form field "file")
curl -F "file=@data.csv" https://upload.83blue.com/api/upload
# raw body (PUT or POST), file name in the query string
curl -T data.csv "https://upload.83blue.com/api/upload?name=data.csv"
| Parameter | Where | Meaning |
|---|---|---|
file | multipart field | The file (alternative: raw request body) |
name | query | File name for raw-body uploads (or X-Filename header) |
password | query or form | Optional custom password, 8-64 characters; a strong one is generated when omitted |
expires_days | query or form | 1 to 180, default 180 |
Response (JSON):
{
"ok": true,
"token": "1f0c9a41c58a7b2d90aa",
"url": "https://upload.83blue.com/d/1f0c9a41c58a7b2d90aa",
"filename": "data.csv",
"size": 18874368,
"size_human": "18 MB",
"expires_at": "2027-02-04T14:00:00+00:00",
"downloads": 0,
"password": "Ab3k-Xy7q-Mn2p",
"download": {
"api": "https://upload.83blue.com/api/download?token=1f0c9a41c58a7b2d90aa&password=Ab3k-Xy7q-Mn2p",
"curl": "curl -fL -OJ \"...\""
},
"handoff": "Give the receiving agent or person the url and the password. ..."
}
GET /api/download
Streams the file. Supports HTTP Range, so interrupted downloads resume and download managers can fetch in segments.
curl -fL -OJ "https://upload.83blue.com/api/download?token=TOKEN&password=PASSWORD"
| Parameter | Meaning |
|---|---|
token | The 20-character transfer id, or the full share url (both accepted) |
password | The transfer password |
Errors are JSON: 404 unknown or expired, 403 wrong password.
The share page form at /d/TOKEN and the direct link
/dl/TOKEN?p=PASSWORD work too.
Capability and handoff urls
Every upload response also contains two special urls that carry their whole secret, so no separate password is needed:
| Url | What it does |
|---|---|
capability_url/f/TOKEN/KEY |
GET downloads the raw file (HTTP Range supported). DELETE removes the transfer immediately. |
handoff_url/h/TOKEN/KEY |
GET returns a markdown briefing any model understands: what the
transfer is, its manifest, the HANDOFF.md content for bundles, sha256,
and the exact download commands. Send Accept: application/json for the
same thing as structured data. This is the one url to paste into any chat with any
model. |
# fetch
curl -fL -OJ "https://upload.83blue.com/f/TOKEN/KEY"
# clean up when done
curl -X DELETE "https://upload.83blue.com/f/TOKEN/KEY"
The handoff convention: when bundling several files for another agent, put
a HANDOFF.md (or INSTRUCTIONS.md / README.md) at the
zip root with the briefing. The handoff url and the MCP receive_file tool
surface it first, so the receiving agent knows what it has before downloading anything.
GET /api/info
Metadata without downloading: file name, size, sha256 (recorded for files up to 1 GB), expiry and download count.
curl "https://upload.83blue.com/api/info?token=TOKEN&password=PASSWORD"
Try it end to end in four commands
The service is trivially testable: upload a small file, check its sha256, fetch it back, delete it.
printf 'hello agent' > probe.txt
CAP=$(curl -sS -F "file=@probe.txt" "https://upload.83blue.com/api/upload?expires_days=1" | jq -r .capability_url)
curl -sS "$CAP" | sha256sum # compare with .sha256 from the upload response
curl -sS -X DELETE "$CAP" # {"ok":true,"deleted":true,...}
How do I upload files larger than 512 MB?
With the chunked, resumable protocol, up to 1 TB per file. Create a transfer, then append chunks (up to 256 MB each) until the declared size is reached. If the connection drops, ask for the current offset and continue from there; re-creating with the same fingerprint from the same IP resumes the same transfer.
POST /api/createwith JSON{"name", "size", "fingerprint"}(fingerprint: any 64-char hex string that identifies the file, e.g.sha256(name|size)). Optional:password,expires_days. Returns{token, offset, password}. Re-creating with the same fingerprint and size from the same IP resumes the unfinished transfer, and every create call issues a fresh password: always use the most recent one.POST /api/chunk?token=TOKEN&offset=OFFSETwith raw bytes in the body. Returns the new offset; replies409with the real offset on a mismatch, and{"complete": true, "link": ...}when the file is done.GET /api/status?token=TOKENat any time for the current offset.
#!/bin/bash
# resumable upload of a big file
FILE="big.iso"
SIZE=$(stat -c%s "$FILE")
FP=$(printf '%s' "$FILE|$SIZE" | sha256sum | cut -c1-64)
RES=$(curl -fsS -X POST https://upload.83blue.com/api/create \
-H 'Content-Type: application/json' \
-d "{\"name\":\"$FILE\",\"size\":$SIZE,\"fingerprint\":\"$FP\"}")
TOKEN=$(echo "$RES" | jq -r .token)
PASS=$(echo "$RES" | jq -r .password)
OFFSET=$(echo "$RES" | jq -r .offset)
CHUNK_MB=64
while [ "$OFFSET" -lt "$SIZE" ]; do
RES=$(dd if="$FILE" bs=1M skip=$((OFFSET / 1048576)) count=$CHUNK_MB 2>/dev/null \
| curl -fsS -X POST --data-binary @- \
"https://upload.83blue.com/api/chunk?token=$TOKEN&offset=$OFFSET")
OFFSET=$(echo "$RES" | jq -r .offset)
done
echo "url: https://upload.83blue.com/d/$TOKEN password: $PASS"
Uploads and downloads both resume, which matters for agents on flaky connections and for very large artefacts (model weights, datasets, disk images).
MCP server
A remote MCP server (Model Context Protocol, Streamable HTTP transport, no authentication) runs at:
https://upload.83blue.com/mcp
Four tools:
| Tool | What it does |
|---|---|
share_text | Upload text (instructions, code, JSON, a prompt for another model) as a downloadable file; returns handoff + capability urls plus a share url and password |
share_file | Upload one or more files in one call; several files are zipped into a single bundle server-side, so one url carries the whole handoff |
share_conversation | Package a markdown transcript (context, instructions, task state) as HANDOFF.md plus any files into one bundle; returns the handoff url to paste into any chat with any model |
receive_file | Fetch a transfer by capability url (or share url + password); returns metadata with sha256, lists zip contents, reads the root HANDOFF.md first, inlines small text files, and hands back a curl command for anything bigger |
(The original names send_text, send_files and receive
still work as aliases.)
Claude Code
claude mcp add --transport http transfer https://upload.83blue.com/mcp
claude.ai (web and desktop)
Settings > Connectors > Add custom connector > paste
https://upload.83blue.com/mcp. No OAuth fields needed. Available on all plans.
Cursor
// ~/.cursor/mcp.json (global) or .cursor/mcp.json (project)
{ "mcpServers": { "transfer": { "url": "https://upload.83blue.com/mcp" } } }
VS Code (Copilot agent mode)
// .vscode/mcp.json
{ "servers": { "transfer": { "type": "http", "url": "https://upload.83blue.com/mcp" } } }
ChatGPT (developer mode)
Settings > Apps & Connectors > Developer mode > create a connector with the url
https://upload.83blue.com/mcp and authentication set to No authentication
(paid plans only).
A2A (Agent2Agent protocol)
For agents speaking Google's A2A protocol, the agent card is published at the standard
well-known location and a JSON-RPC endpoint (protocol 0.3.0, non-streaming) answers
message/send synchronously:
Agent card: https://upload.83blue.com/.well-known/agent-card.json
Endpoint: https://upload.83blue.com/a2a
- Share: send file parts (
FileWithBytes); multiple files are zipped into one bundle. Add a data part{"transcript": "..."}to placeHANDOFF.mdat the root, and optionalexpires_days/password. The reply is a message with a text summary, aFileWithUripart (the capability url) and a data part with all urls. - Fetch: send a data part
{"url": "...", "password": "..."}(or aFileWithUripointing at this service); the reply carries the metadata and the capability url. This service is also a natural host for the uri in any A2AFileWithUripart, which the A2A specification deliberately leaves to external infrastructure.
How do two AI agents hand files to each other?
The sending agent uploads everything the next agent needs (instructions, code, data) and
passes on two strings: the url and the password. That message is small enough to travel
through any channel: a chat reply, a ticket, an e-mail, another model's context window,
or an A2A message (this service is a natural host for the uri in an A2A
FileWithUri part, which the A2A specification deliberately leaves to
external infrastructure).
A handoff message that works well as a prompt for the receiving agent:
I have uploaded a bundle for you on 83blue transfer.
url: https://upload.83blue.com/d/TOKEN
password: XXXX-XXXX-XXXX
Fetch it with:
curl -fL -OJ "https://upload.83blue.com/api/download?token=TOKEN&password=XXXX-XXXX-XXXX"
Unzip it and read INSTRUCTIONS.md first: it explains what each file is
and what you need to do.
Agents connected over MCP skip the shell entirely: the sender calls
share_file or share_conversation, the receiver calls
receive_file, and the bundle contents plus the root briefing are surfaced
automatically so the receiving agent knows what it has.
Limits and fair use
| Thing | Limit |
|---|---|
| Max file size | 1 TB (chunked); 512 MB in a single request; 100 MB per MCP call |
| Retention | 1 to 180 days; default 180 (6 months) for web and HTTP API uploads, 30 days for MCP tool calls |
| Simultaneous uploads | 3 site-wide. When all slots are busy the reply is HTTP 429 with a
Retry-After header and a JSON error: wait a few seconds and retry |
| Download speed | 1 Mbit/s per connection after the first 512 KB, at most 3 download connections per IP: this service optimises for handoffs, not bulk speed |
| Accounts / API keys | None, ever |
| Price | Free |
| Automated use | Welcome. Scripts, cron jobs, CI pipelines and AI agents are the intended audience |
Fair use means: no illegal content, no malware distribution, no using the service as permanent primary storage or a CDN. Abusive transfers are removed.
Security and privacy
- All transfers travel over HTTPS.
- Every transfer gets an unguessable 80-bit link token plus a separate auto-generated password (roughly 70 bits), stored only as a bcrypt hash.
- Files are deleted automatically at expiry; expired links return 404.
- No tracking, no advertising, no analytics scripts, no cookies.
- Anyone holding the url and the password can download the file until it expires; treat the pair like the secret it is.
Free file transfer for AI agents and humans. No signup, no keys, no nonsense.