Tutorial · Upload API for agents

Upload a file from an AI agent in 60 seconds

Authentication is a Bearer token. Payment is 5¢ via x402 (or debited from account credits). Retries are idempotent. The whole surface is OpenAPI 3.1 and MCP-discoverable.

1. Get an API key

One POST. Returns a key like fs_… tied to the email you provide. The same key handles auth, ownership, and your agent-credits ledger.

curl
curl -X POST https://foldr.space/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@example.com"}'

Or browse to /developers/signup for a UI version.

2. Upload a file

Multipart POST to /api/v1/files. Every upload is permanent. Response carries the public URL, share token, and direct download URL.

curl
curl -X POST https://foldr.space/api/v1/files \
  -H "Authorization: Bearer fs_xxx" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "file=@report.pdf" \
  -F "folder_slug=research"
typescript
import { FoldrSpaceClient } from 'foldrspace'

const client = new FoldrSpaceClient({ apiKey: process.env.FOLDR_API_KEY })

const file = await client.uploadFile(blob, {
  filename: 'report.pdf',
  folderSlug: 'research',
})
console.log(file.publicUrl)
python
from foldrspace import FoldrSpaceClient

client = FoldrSpaceClient(api_key=os.environ["FOLDR_API_KEY"])

f = client.upload_file("./report.pdf", folder_slug="research")
print(f.public_url)

3. Handle the 402

If your key isn't Pro+ and your credits balance is empty, the upload returns 402 Payment Required with an x402 envelope. Sign one entry from accepts[] using your Base wallet, then retry the same call with the signed payload in X-PAYMENT.

response · 402
{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "base",
    "maxAmountRequired": "50000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x0fF790fBBF1D26E533cCaf9c9C01EBE728509f74",
    "resource": "https://foldr.space/api/v1/files",
    "description": "5¢ per upload",
    "maxTimeoutSeconds": 60
  }]
}

Sign with your Base wallet, base64-encode the signed payload, retry:

curl · retry
curl -X POST https://foldr.space/api/v1/files \
  -H "Authorization: Bearer fs_xxx" \
  -H "Idempotency-Key: <same key as before>" \
  -H "X-PAYMENT: <base64 of signed payment payload>" \
  -F "file=@report.pdf"

Same Idempotency-Key means the original request slot is reused - no double-charge, even if you retry a third time.

4. Retries are safe

Always send Idempotency-Key on writes. Same key + same body replays the original response with Idempotent-Replayed: true. Same key + different body returns 422. In-flight duplicate returns 409 with Retry-After.

response · replay
HTTP/1.1 201 Created
Idempotent-Replayed: true

{ "success": true, "file": { ... } }   // original response, no second charge

5. Move, share, list

Once the file exists, you can move it, mint a capability token (time-bounded share), list everything you've uploaded, or batch-delete.

typescript
// Mint a 1-hour, 5-use share link
const cap = await client.mintCapability(file.id, {
  expiresIn: 3600,
  maxUses: 5,
})
console.log(cap.downloadUrl)

// List everything in a folder
const files = await client.listFiles({ folderSlug: 'research' })

// Move into a different folder
await client.moveFile(file.id, 'archive')

6. MCP, if you prefer

All of the above is exposed as MCP tools at /api/mcp (streamable-http transport). Connect from Claude Desktop, Cursor, or any MCP client and call upload_file, list_files, etc. directly. Same 5¢ per upload - MCP debits the credits ledger; x402 is HTTP-only.

Ship something

Get an API key, plug it into your agent, point its wallet at our 402 endpoint, and start uploading. Or skip x402 and pre-fund credits via Stripe.