Developer documentation
Secure Send API
A REST API and an MCP server for delivering a file to a person as a one-time, encrypted, auto-deleting download link. Base URL https://fileseal.uk/v1.
Quickstart (REST)
- Create a FileSeal account and, in Settings → API keys, generate a key. The full secret is shown once; store it as
FILESEAL_API_KEY. - Encrypt your file client-side (see Encryption), base64-encode the result, and create the send:
curl -X POST https://fileseal.uk/v1/sends \
-H "Authorization: Bearer $FILESEAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"deliveryMode": "link",
"expiryHours": 48,
"files": [{
"filename": "contract.pdf",
"mimeType": "application/pdf",
"ciphertextBase64": "<[12-byte IV][AES-GCM ciphertext], base64>"
}]
}'The response gives you the claim link, expiry and seal id:
{
"success": true,
"id": "2c693e7c-...",
"claimUrl": "https://fileseal.uk/receive/2c693e7c-...",
"deliveryMode": "link",
"expiresAt": "2026-06-18T11:01:26.947Z",
"filesCount": 1,
"totalSize": 81234
}In link mode the response is the base URL only; append the key fragment yourself (claimUrl + "#k=" + keyFragment) and relay the full link, so FileSeal never receives the key. In email mode, passrecipientEmail and a per-fileencryptionKey and FileSeal emails the recipient.
Quickstart (MCP server)
The fileseal-send MCP server gives an AI agent a tool to deliver files securely, and does the client-side encryption for you. Register it in your MCP client config with FILESEAL_API_KEY and FILESEAL_API_BASE_URL set to https://fileseal.uk (the default from version 0.1.3; earlier versions call http://localhost:3000 without it):
{
"mcpServers": {
"fileseal-send": {
"command": "npx",
"args": ["-y", "@fileseal/send"],
"env": {
"FILESEAL_API_KEY": "${FILESEAL_API_KEY}",
"FILESEAL_API_BASE_URL": "https://fileseal.uk"
}
}
}
}It exposes three tools:
secure_send: encrypt one or more files and create a send; returns the share link (with#k=in link mode). Pass several files asfilePathsto send up to 10 under one link (from version 0.1.4), 3 MB in total, because the files travel inline in the request body. In email mode, passsenderNameso the email says who it is from.send_status: status and audit events for a send created with the same API key.revoke_send: revoke before download.
The server is published to npm as @fileseal/send (run via npx, no install); a hosted remote MCP option is on the roadmap.
Claude Code plugin
In Claude Code you can install the server as a plugin instead of editing your MCP config. The plugin stores your API key as a masked setting, outside your settings files, and adds a skill that tells Claude how to use the three tools: which delivery mode to choose, what FileSeal can read, and the limits.
/plugin marketplace add fileseal/mcp-send
/plugin install fileseal@filesealEnter your API key when asked. If you are not asked, or to change the key later, run /plugin configure fileseal@fileseal.
The plugin works in Claude Code only (the terminal, the IDE extensions and the desktop app’s Code tab). Claude chat does not run MCP servers that start on your computer, and Cowork cannot collect the API key the server needs. Its source is in the claude-plugin folder of github.com/fileseal/mcp-send.
Authentication
Every request needs Authorization: Bearer $FILESEAL_API_KEY. Keys are issued and revoked in the dashboard; a revoked key stops working immediately (401). Treat a key like a password: it can create sends and upload requests on your account, and it can read the client names and email addresses of the upload requests your account can see.
Endpoints
POST /v1/sends: create a send.
Body: deliveryMode (link default, or email), expiryHours (1–168, default 48), optional recipientEmail, senderName, senderEmail and message, and files (1–10), each with filename, mimeType, ciphertextBase64, and encryptionKey(required in email mode, forbidden in link mode). The file names, message and senderName are stored unencrypted in both modes, and anyone with the link can read them.
GET /v1/sends/:id: status and audit timeline.
Returns status (sealed / downloaded / revoked / expired), counts, and an events list (created, collected, revoked). Only sends created with the calling key are visible; any other id returns 404.
DELETE /v1/sends/:id: revoke before download.
Race-safe. Returns 200 once revoked, including when it was already revoked: the link stops working immediately and deletion of the encrypted files is attempted. Returns 409 if the send was collected, does not exist, or was created by another key (the API does not say which), and 404 for a malformed id.
Upload requests
Ask a client for documents from your own software and find out when they have arrived. The client uploads on FileSeal’s usual one-time page, and you collect in the FileSeal dashboard, as for any request. The API reports on requests; it never carries the documents, their file names or their keys.
curl -X POST https://fileseal.uk/v1/requests \
-H "Authorization: Bearer $FILESEAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"deliveryMode": "email",
"clientName": "Alex Client",
"clientEmail": "alex@example.com",
"description": "Your last three payslips",
"reference": "MATTER-42"
}'deliveryMode is required. With email, FileSeal keeps what it needs to open the files, so you can always collect them, and with a clientEmail it emails the client a working link and reminders. Without a client email it sends nothing and you send uploadUrl yourself. With link, you generate the key and give the client uploadUrl + "#k=" + keyFragment; FileSeal never receives it. Only that link carries the key: collect by pasting the full link into the dashboard, and if neither you nor your client keeps it, the documents cannot be opened.
POST /v1/requests: create an upload request.
Body: deliveryMode (email or link, required), optional clientName, clientEmail, description (up to 1000 characters, shown to the client), uploadHours (24 to 168, default 72), downloadHours (24 to 720, default 168, from the first upload) and reference (your own id, never shown to the client). Any other field, including a key, is refused. Returns uploadUrl, emailSent and dashboardUrl.
GET /v1/requests: list requests.
Every upload request your account can see in its dashboard, however it was made, newest first, with its status, client name and email, file count and size. Filter with status and reference; page with limit (up to 100) and page. With status=received the newest arrivals come first, which is what a poller wants.
GET /v1/requests/:id: one request.
The same fields, plus the description and when the files were first collected.
DELETE /v1/requests/:id: withdraw before the client uploads.
For requests your account made through the API. The link stops working straight away; withdrawing twice returns 200. Returns 409 once the client has uploaded or the request has expired. Withdraw dashboard requests in the dashboard.
Statuses: awaiting_upload, receiving (files are arriving), received (the request has stopped accepting files, usually within about 10 minutes of the first upload), collecting, collected, expired and cancelled. Poll for received before acting.
- A test request is a real request: it uses a trial seal and, with a client email, emails that address on your behalf. Test with your own address.
- A retry after a timeout can create a second request. Set
referenceand check the list for it before retrying. - FileSeal reminds the client before the deadline whenever there is a client email. If your own system chases clients, leave the email out and send the link yourself.
- The email names your team, or the company name in your Settings, since an API call has no signed-in person. Set a company name if you have no team.
- Requests made through the API appear in your dashboard with a “Via API” label and their reference, and teammates who can see all of the team’s requests see them too.
Encryption
Files are encrypted client-side before upload, as [12-byte random IV] + AES-GCM-256 ciphertext, then base64-encoded into ciphertextBase64. Use one fresh AES-256 key per send.
#k= fragment, so every file in a send must use the same key. A file encrypted with a different key cannot be decrypted and is lost once the one-time seal burns. The MCP server handles this for you.Limits
- File types: PDF, DOC, DOCX, TXT, JPG, PNG.
- Up to 10 files per send; up to 10 MB per file and 50 MB per send (enforced on the encrypted bytes). In Milestone 1 the whole request is sent inline, so it is bounded by the ~4.5 MB platform body limit until the scoped client-upload lands.
- The MCP server sends up to 10 files per call (from version 0.1.4), 3 MB in total, for the same inline-body reason.
- Expiry 1–168 hours (default 48). Rate limit: 100 sends per 24 hours per key and per account.
- Upload requests: the client can upload PDF, DOC, DOCX, JPG and PNG, up to 10 MB per file and 50 MB per request. 100 create calls per 24 hours per key and per account, and 60 reads a minute per key.
Errors
401: missing or invalid key.402: the account's free-trial allowance is used up (code: UPGRADE_REQUIRED). For upload requests,PAYMENT_PAST_DUEmeans a failed payment, andactionUrlsays where to fix either.403: recipient domain not allow-listed (when configured); for upload requests, a team member without permission to create requests (PERMISSION_DENIED).409: a send already collected, or an upload request that can no longer be withdrawn.400: invalid body, disallowed type or oversize file.429: rate limit exceeded (Retry-Afterheader).503: authentication backend unavailable.
FAQ
How do I let an AI agent send a file securely?
Add the fileseal-send MCP server and call its secure_send tool, or call POST /v1/sends directly. Either way the recipient gets a one-time, encrypted link that auto-deletes.
Is it zero-knowledge?
In the default link mode, yes: the key lives only in the link fragment and FileSeal stores ciphertext it cannot read. The opt-in email mode stores the key so FileSeal can email a working link.
What happens after download?
The link works once; the file is then deleted from FileSeal's servers and the collection is recorded on the audit trail.