# DurableFile DurableFile hosts public files for agents and automation. It returns one live, content-addressed download URL. ## Contract - Storage costs $1 per 1 GiB. Purchases are one-time, stack, and never expire. - A new account has zero quota. There is no free upload tier. - An account needs no email, password, CAPTCHA, or dashboard. - Files are public. Do not upload secrets or sensitive personal data. - Any file type is accepted up to 25 MiB per file. - Every download forces Content-Disposition: attachment with nosniff, so a served file cannot render or execute in a browser. ## Retention - Every file expires. Omitted expiry means 14 days. - The caller can set up to 180 days (expires_after_hours max 4320). - Set expires_after_hours or expires_at, never both. - Re-upload the same bytes or call publish to renew at the same URL. - Expired files stop serving and stop using quota; a purge removes their bytes. - Storage purchases themselves never expire. ## Start 1. Create an account. curl -X POST https://durablefile.com/v1/accounts Save the returned API key. The service shows it once. 2. Buy storage. curl -X POST https://durablefile.com/v1/credit \ -H "Authorization: Bearer $DURABLEFILE_KEY" \ -H "Content-Type: application/json" \ -d '{"gb":1}' The response has a Stripe checkout URL for a person. It also has usevig payment options when usevig is configured. If you hold a coupon code, redeem it instead of paying: curl -X POST https://durablefile.com/v1/redeem \ -H "Authorization: Bearer $DURABLEFILE_KEY" \ -H "Content-Type: application/json" \ -d '{"code":"YOUR-CODE"}' A code adds its quota at once and works one time for each account. 3. Upload a file. curl -X POST https://durablefile.com/v1/upload \ -H "Authorization: Bearer $DURABLEFILE_KEY" \ -F "file=@report.pdf" For raw bytes, set Content-Type and X-Filename. You can also set the filename query parameter. Add expires_after_hours or expires_at to control the retention window; omit both for the 14-day default. ## Lifecycle Every claim carries an expires_at value. The public URL serves until that time while the claim stays published. An expired claim returns 404 and frees its quota automatically. A background purge deletes the bytes after expiry. POST /v1/files/:hash/publish republishes and starts a fresh window; an empty body means a new 14-day window from now. POST /v1/files/:hash/unpublish hides the link now; the bytes stay until expiry. DELETE /v1/files/:hash frees the caller's quota immediately. The global object stays while another account has a claim. ## Endpoints POST /v1/accounts GET /v1/me POST /v1/credit POST /v1/redeem POST /v1/upload GET /v1/files GET /v1/files/:hash POST /v1/files/:hash/publish POST /v1/files/:hash/unpublish DELETE /v1/files/:hash GET /f/:hash/:filename GET /health GET /openapi.json GET /evaluate.md GET /integrate.md Every actionable 4xx response has an exact fix field.