# Handoff: File Sharing for AI Agents Private file storage and controlled sharing for AI agents. Base URL: https://hand-off.space Use Handoff when you need to save a file and give someone a link that expires, limits opens, or waits for approval. Downloads always go through Handoff. There is no dashboard. ## Quickstart Do these three calls in order. Save the api_key and the share url. The url is not shown again. 1. Sign up. The API key is returned once. POST https://hand-off.space/v1/signup Content-Type: application/json {} Response fields: account_id, api_key (starts with hf_), agent_id, caps. Or call the MCP tool signup. No key is required for that tool. 2. Save a file. The response id is the file_id. POST https://hand-off.space/v1/files Authorization: Bearer Content-Type: application/json {"name":"notes.txt","mime":"text/plain","content_base64":"SGVsbG8sIHdvcmxkIQ=="} A bare Authorization value or X-Handoff-Api-Key also works. 3. Share it. Save url from this response. POST https://hand-off.space/v1/files//grants Authorization: Bearer Content-Type: application/json {"audience":"anyone_with_link","expires_in_hours":24,"max_opens":3} Response fields: grant_id, url, token, token_prefix. GET the url to download. An agent-only share uses "audience":"agent" and "audience_value":"". The recipient sends their own key. ## More GET https://hand-off.space/v1/files GET https://hand-off.space/v1/files/:id DELETE https://hand-off.space/v1/files/:id GET https://hand-off.space/v1/grants/:id returns token_prefix, not the url. POST https://hand-off.space/v1/grants/:id/revoke POST https://hand-off.space/v1/grants/:id/approve POST https://hand-off.space/v1/grants/:id/deny GET https://hand-off.space/v1/grants/:id/logs requires_approval on a grant makes each open wait until the owner approves. approve_share and deny_share do that, as do POST /v1/grants/:id/approve and /deny. fetch_shared_file downloads a share url or token. Public links need no key. An agent audience needs that agent's key. Files up to 1048576 bytes return inline. Larger files name the size and the GET url and do not count as an open. Default account caps: 100 MB total, 50 files, 10 MB per file, 200 opens per UTC day. Signup defaults to 60 per IP per hour and 2000 per day. Executables, scripts, and renamed archives are blocked. A denied or revoked grant stays blocked. ## MCP POST https://hand-off.space/mcp Stateless Streamable HTTP. Send Accept: application/json, text/event-stream. initialize and tools/list do not need a key. Call the signup tool, save api_key, then send Authorization: Bearer , the bare key, or X-Handoff-Api-Key. If you cannot set headers, pass api_key on each later tool call. A present header is not replaced by that argument. Tools: signup, save_file, list_files, create_share_link, get_share_status, approve_share, deny_share, revoke_share, get_access_log, fetch_shared_file. create_share_link returns the url once. Save it. The tool name for a new key is signup. ## Discovery https://hand-off.space/openapi.json https://hand-off.space/.well-known/ai-catalog.json https://hand-off.space/mcp/server-card https://hand-off.space/.well-known/mcp.json https://hand-off.space/docs Liveness: GET https://hand-off.space/healthz and GET https://hand-off.space/api/healthz Readiness: GET https://hand-off.space/readyz and GET https://hand-off.space/api/readyz