Sending a file is one of those problems that looks solved until you try to do it from a script. The web flow assumes a browser, the email flow assumes a human, and the API surface — when one exists at all — usually assumes you already have an account and a cookie.
ReTransfer started life as a clean WeTransfer-style send tool. Sometime around the fifth time we caught ourselves writing automation in a console, we realised the harder thing wasn’t the UI. It was making the same primitive equally cheap for a human, a CLI script, and an autonomous agent crawling the web.
Same API. Same auth. Same expiry semantics. No browser required.
Four surfaces, one contract
Discovery starts at /.well-known/agent.json: a JSON manifest pointing at the API base, an OpenAPI 3.1 spec, the rate limits, and the auth flow. An agent that lands on the homepage via search can read this without making a paid API call.
The OpenAPI document is the long-form contract — every endpoint, every shape, every error code, embedded in the binary so it never drifts from the live router. MCP-native hosts skip both and just spawn our stdio binary, which exposes four tools (retransfer_send_files, list/get/revoke) over JSON-RPC. Claude Desktop installs it in one click.
Where the agent identity story goes
Agents register a DID at agent:retransfer.one/u/<uuid> by publishing a public JWK manifest. We fetch it (with SSRF protection that re-checks the connected IP on every hop), validate the JWK, and stamp the key onto the user record. From then on, a sender can finalize a transfer addressed to that DID; we deliver a signed webhook to the agent’s inbox, the agent presents its bearer at the link, and the transfer flows. No email, no OTP, no human in the loop.
The signed webhook is the part we lost the most sleep over. Stripe-style HMAC over a canonical timestamp.delivery_id.body string. Asynq-backed retry with the 1m → 5m → 30m → 2h → 12h backoff schedule. A dead-letter transition that flips the recipient row to a terminal status so the sender’s dashboard sees a real outcome instead of "pending forever".
What’s next
Per-agent rate limits, receiver-side consent allowlists, and federation across deployments (so an agent on agent:example.com/u/... can be addressed from a ReTransfer hosted on retransfer.one). The plumbing is in place; the next few versions are about making the corners feel as deliberate as the centre.
