Share files with private download links that expire on their own
Published 2026-10-21
Most small teams send files to people outside the company every week: a contract draft, a report for a customer, a price sheet for one partner, a set of photos or exports. The usual options are an email attachment that bounces when it is too large, or a shared folder link that keeps working long after anyone needs it. ChatGPT or Claude can help you write the note that goes with the file. It cannot hold the file somewhere online, give it a private address, or close that address next month.
What a chat cannot do alone
A chat has no public storage you control and no server that answers when someone clicks a link. Files you upload to a chat stay inside that chat. It also cannot keep a record of who opened what, and it has no way to act on a date, so nothing revokes access when a deal ends or a customer leaves. People end up pasting folder links from a drive account and hoping they remember to change the sharing later.
What your assistant builds with Sails
Sails is a coding agent you connect over MCP, with cloud deployment built in. Your assistant writes the code and Sails runs it in the cloud. For this job it builds four pieces.
A file store for the shared files. You hand your assistant a file, and it saves it under a private folder that is never listed publicly.
A table of links. Each row has a long random token, the file it points to, who it is for, an expiry date, an optional download limit, and a count of downloads so far.
A small download endpoint on your own domain. When someone opens the link, it looks up the token, checks the date and the limit, records the download with a timestamp, and returns the file. An expired or unknown token gets a plain page that says the link is no longer active.
A scheduled job written as ordinary shell code with no model in the loop. Each morning it marks links past their date as closed, deletes files no active link still uses, and emails you from your mailbox a short list of what expired and which links were never opened.
Why it works
Every link is its own row, so you can give two people different end dates for the same file, or close one without touching the other. The download log answers the question of whether someone actually got the file without asking them. Cleanup runs on a schedule rather than on your memory, so old links do not pile up. Because the files and the table live in Sails, your assistant can make a new link or extend an old one in any later chat.
Hand it off
Copy this into your assistant:
Add Sails from https://sails.app/start. Build me private file sharing on my domain. Store files I give you in a private folder. Keep a table of links with a random token, the file, who it is for, an expiry date, an optional download limit, and a download count. Serve a download endpoint that checks the token, date, and limit, logs each download, and shows a plain message for expired links. Write a daily scheduled job in plain shell code with no model involved that closes expired links, removes unused files, and emails me what expired and which links were never opened. Show me how to create, extend, and revoke a link. Ask me anything you need before you start.