How to share a file from the terminal with a one-time link
Upload a file with curl or the socket-help CLI, limit it to one download, and send the token separately. The contents are removed once that download happens.
When a one-time link is the right tool
Sometimes you need to move one file from a server or a colleague’s laptop to another machine: a log bundle, a test fixture, a build artifact. Setting up a bucket or a shared drive for that is overkill, and attaching it to a chat message leaves a copy in the chat history for good.
A one-time share is a temporary upload that accepts a single download. When that download happens, the stored contents are removed. If the link is opened by the wrong person first, the intended recipient gets an error instead of the file, which tells you something went wrong. Files can be up to 10 MiB.
Everything below works from a plain shell with curl, so it also works over SSH on a server where you cannot install anything. The socket-help CLI is a shorter alternative when it is available. Both talk to the same HTTP API, and both create private shares unless you ask for public ones.
Upload with curl
Send the raw bytes to /api/files as application/octet-stream and put the file name in the X-File-Name header. Set maxDownloads to 1 for a one-time share. Private is the default, and you can shorten the lifetime with ttlSeconds: without an account it can be from 60 seconds up to one hour.
The response includes the file ID, the downloadUrl, an accessToken for the recipient, a managementToken for you, the expiry time, and remainingDownloads. Store the response somewhere safe; the tokens are shown only once.
Use --data-binary rather than -d. The -d option is meant for form data and strips line breaks from files read with @, which silently corrupts text files and archives. If the upload is rejected with 503 and a Retry-After header, the service is busy with other transfers; wait the given number of seconds and try again.
curl --fail -X POST 'https://socket.help/api/files?visibility=private&maxDownloads=1&ttlSeconds=600' \
-H 'Content-Type: application/octet-stream' \
-H 'X-File-Name: logs.tar.gz' \
--data-binary @logs.tar.gzOr use the socket-help CLI
The CLI reads the file from standard input and prints the same JSON response. It is private by default, and accepts --max-downloads, --ttl-seconds, and --visibility. Set SOCKET_HELP_API_KEY if you want the share to belong to your workspace instead of being managed only by its token.
On the receiving side, the download command writes the original bytes to standard output, and reads the access token from SOCKET_HELP_ACCESS_TOKEN so it does not appear in your shell history as an argument. Errors are printed to standard error as JSON with a nonzero exit code, so scripts can tell a failed download from an empty file.
# Sender
socket-help upload logs.tar.gz --max-downloads 1 --ttl-seconds 600 < logs.tar.gz
# Recipient
export SOCKET_HELP_ACCESS_TOKEN='token sent separately'
socket-help download FILE_ID > logs.tar.gzSend the link and the token separately
A private share needs two things: the file ID or link, and the access token. Send them through different channels, for example the link in a ticket and the token in a direct message. Someone who sees only one of them cannot download the file.
Never put the token in the URL. A recipient using a browser opens the share page at /share/?id=FILE_ID and pastes the token there. A recipient using a script sends it in the X-Access-Token header.
It also helps to send a checksum with the link, for example the SHA-256 of the file. The recipient can compare it after downloading, which catches a truncated or wrong file. Since a one-time share cannot be downloaded twice, a mismatch means asking the sender for a new share, so check before deleting your original copy.
curl --fail https://socket.help/files/FILE_ID \
-H "X-Access-Token: $FILE_ACCESS_TOKEN" \
--output logs.tar.gzCheck a share without using up the download
Only a full GET of /files/FILE_ID counts as a download. A GET of /files/FILE_ID/info returns the name, size, visibility, expiry, and remaining downloads without consuming anything, and so does a HEAD request. Private shares still need the access token for both.
This matters for one-time links. The download is counted when the server starts sending the file, so an interrupted transfer still uses it up. In a browser, opening a preview also counts as the download. If a transfer fails partway, create a new share rather than retrying the old link.
curl https://socket.help/files/FILE_ID/info \
-H "X-Access-Token: $FILE_ACCESS_TOKEN"Clean up and know the limits
After the one download, the contents are gone but the metadata remains until expiry. Delete the share with the management token if you want it removed straight away, or if the transfer did not happen and you want to make sure nobody else can take it.
Without an account you can hold up to five resources and 32 MiB of storage at a time, and a share lasts at most one hour. A free account allows up to 24 hours. Files are not scanned for malware and always download as attachments. The access token controls who can download; it is not end-to-end encryption, so encrypt anything confidential before you upload it.
curl -X DELETE https://socket.help/api/files/FILE_ID \
-H "Authorization: Bearer $FILE_MANAGEMENT_TOKEN"Questions people ask
What happens after the one download?
The stored contents are removed. Later requests get a 404 response saying the file is unavailable, expired, or out of downloads.
Can I check the file without using the download?
Yes. GET /files/FILE_ID/info and HEAD requests return details without counting as a download.
How large can the file be?
Up to 10 MiB per file. Without an account you can store up to 32 MiB across five resources at a time.
Is the file encrypted?
The access token restricts downloads, but it is not end-to-end encryption. Encrypt sensitive files before uploading.