Sometimes you just need to share a file from your terminal. No browser, no drag-and-drop, no GUI. One cURL command sends your file and returns a shareable link.
Basic Upload with cURL
curl -F 'files[][email protected]' https://easysend.co/api/v1/upload
That is it. The -F flag sends a multipart form upload. The @ prefix tells cURL to read from a file. The response is JSON:
{
"success": true,
"short_code": "Ab3Kz",
"share_url": "/Ab3Kz",
"upload_url": "/u/abc123...def456",
"upload_token": "abc123...def456",
"files": [
{"id": 42, "name": "report.pdf", "size": 1048576, "mime_type": "application/pdf"}
]
}
The share link is https://easysend.co/Ab3Kz. Send that to anyone. No account needed on either end. See the full response format in the API documentation.
Extracting the URL with jq
Pipe the JSON response through jq to pull out just the link:
# Get just the short code
curl -s -F 'files[][email protected]' https://easysend.co/api/v1/upload | jq -r '.short_code'
# Build the full URL
curl -s -F 'files[][email protected]' https://easysend.co/api/v1/upload | jq -r '"https://easysend.co/" + .short_code'
# Get the upload token for later use
curl -s -F 'files[][email protected]' https://easysend.co/api/v1/upload | jq -r '.upload_token'
The -s flag silences the progress bar so only JSON comes through. The -r flag on jq outputs raw strings without quotes.
Uploading Multiple Files
Send several files in one request by repeating the -F flag:
curl -F 'files[][email protected]' \
-F 'files[][email protected]' \
-F 'files[][email protected]' \
https://easysend.co/api/v1/upload
All files get bundled under one link. Recipients see every file on a single download page.
Upload every file in a directory with a loop:
# Upload all PDFs in current directory
ARGS=""
for f in *.pdf; do
ARGS="$ARGS -F files[]=@$f"
done
curl $ARGS https://easysend.co/api/v1/upload | jq -r '"https://easysend.co/" + .short_code'
Adding a Description and Custom Code
Include optional fields as additional -F parameters:
curl -F 'files[][email protected]' \
-F 'description=Final design mockups for client review' \
-F 'custom_code=client-mockups' \
https://easysend.co/api/v1/upload
Now the share link is https://easysend.co/client-mockups and recipients see the description when they open the page. Check code availability first:
curl -s https://easysend.co/api/v1/check/client-mockups | jq '.available'
Custom codes must be 3 to 30 characters. Read more about them on the developer API page.
Password Protection
Lock a bundle with a password so only people who know it can download:
curl -F 'files[][email protected]' \
-F 'access_password=s3cret-phrase' \
https://easysend.co/api/v1/upload
Anyone who opens the link will be prompted for the password before they can view or download the file.
Piping stdin to EasySend
You can pipe command output directly to EasySend without creating a temp file:
# Pipe a database dump
pg_dump mydb | curl -F 'files[]=@-;filename=mydb.sql' https://easysend.co/api/v1/upload
# Pipe a tar archive
tar czf - ./project/ | curl -F 'files[]=@-;filename=project.tar.gz' https://easysend.co/api/v1/upload
# Pipe log output
journalctl --since today | curl -F 'files[]=@-;filename=today.log' https://easysend.co/api/v1/upload
The @- tells cURL to read from stdin. The ;filename= part sets the filename since stdin has no name. This is useful for sharing command output, backups and generated data without writing temp files.
Getting Bundle Info
Check the status of a previously uploaded bundle:
# Get full bundle details
curl -s https://easysend.co/api/v1/bundle/Ab3Kz | jq .
# List file names and sizes
curl -s https://easysend.co/api/v1/bundle/Ab3Kz | jq '.files[] | {name, size}'
# Check download count
curl -s https://easysend.co/api/v1/bundle/Ab3Kz | jq '.files[].download_count'
Downloading Files
Download individual files from a bundle using the file ID:
# Get the file ID from bundle info
FILE_ID=$(curl -s https://easysend.co/api/v1/bundle/Ab3Kz | jq -r '.files[0].id')
# Download the file
curl -OJ https://easysend.co/api/v1/download/$FILE_ID
The -O flag saves with the remote filename. The -J flag uses the Content-Disposition header for the filename.
The EasySend CLI - A Simpler Alternative
If you share files from the terminal often, the EasySend CLI wraps all of this into a single command:
# Install
curl -fsSL https://easysend.co/cli/install.sh | bash
# Upload a file
easysend report.pdf
# Output: https://easysend.co/Ab3Kz
# Upload multiple files
easysend file1.pdf file2.png file3.zip
# Copy link to clipboard automatically
easysend report.pdf --copy
# Get bundle info
easysend --info Ab3Kz
# Raw JSON output for scripting
easysend report.pdf --json
The CLI handles JSON parsing, error messages and clipboard integration so you do not have to pipe through jq every time.
CI/CD Integration
Share build artifacts from your CI pipeline with a simple step. Here are examples for popular CI systems:
GitHub Actions
- name: Share build artifacts
run: |
URL=$(curl -s -F 'files[]=@dist/app.zip' \
-F 'description=Build ${{ github.run_number }}' \
https://easysend.co/api/v1/upload | jq -r '"https://easysend.co/" + .short_code')
echo "Download: $URL"
echo "SHARE_URL=$URL" >> $GITHUB_ENV
GitLab CI
share-artifacts:
stage: deploy
script:
- |
URL=$(curl -s -F 'files[]=@build/output.zip' \
-F "description=Pipeline $CI_PIPELINE_ID" \
https://easysend.co/api/v1/upload | jq -r '"https://easysend.co/" + .short_code')
echo "Artifact download link: $URL"
Jenkins Pipeline
stage('Share Artifacts') {
steps {
sh '''
URL=$(curl -s -F 'files[]=@target/app.jar' \
-F "description=Build ${BUILD_NUMBER}" \
https://easysend.co/api/v1/upload | jq -r '"https://easysend.co/" + .short_code')
echo "Download: $URL"
'''
}
}
No tokens or credentials needed. Add file sharing to any pipeline in 3 lines. Learn more on our integration page.
Reusable Bash Functions
Add these functions to your .bashrc or .zshrc for quick file sharing from any terminal session:
# Upload files and print the share link
esend() {
if [ $# -eq 0 ]; then
echo "Usage: esend file1 [file2 ...]"
return 1
fi
local args=""
for f in "$@"; do
if [ ! -f "$f" ]; then
echo "File not found: $f" >&2
return 1
fi
args="$args -F files[]=@$f"
done
local result
result=$(curl -s $args https://easysend.co/api/v1/upload)
local url="https://easysend.co/$(echo "$result" | jq -r '.short_code')"
echo "$url"
# Copy to clipboard if available
if command -v pbcopy &> /dev/null; then
echo -n "$url" | pbcopy
echo "(copied to clipboard)"
elif command -v xclip &> /dev/null; then
echo -n "$url" | xclip -selection clipboard
echo "(copied to clipboard)"
fi
}
# Get info about a bundle
einfo() {
curl -s "https://easysend.co/api/v1/bundle/$1" | jq .
}
# Quick pipe - share command output as a file
epipe() {
local filename="${1:-output.txt}"
curl -s -F "files[]=@-;filename=$filename" https://easysend.co/api/v1/upload \
| jq -r '"https://easysend.co/" + .short_code'
}
Now you can share files and command output instantly:
# Share files
esend report.pdf slides.pptx
# Share command output
dmesg | epipe system-log.txt
# Check a bundle
einfo Ab3Kz
Deleting Files
Remove a file from a bundle using the upload token and file ID:
# Delete a specific file
curl -X DELETE \
-H "Authorization: Bearer abc123...def456" \
https://easysend.co/api/v1/file/42
The upload token was returned in the original upload response. Store it if you plan to manage your bundles later.
Troubleshooting
- 413 error - file is too large. Free uploads max out at 1GB per bundle
- 429 error - rate limited. Wait a few minutes and try again. Limit is 10 uploads per hour
- Connection timeout - add
--connect-timeout 30and--max-time 300for large files - Slow upload - add
--progress-barto see a progress indicator
See the complete API reference for all endpoints and response formats.
Related Guides
- EasySend API Documentation - full endpoint reference
- EasySend CLI - dedicated command-line tool for file sharing
- Upload Files with Python in 3 Lines - Python-focused tutorial
- Add File Sharing to Your React App - frontend integration guide
- Developer API Overview - rate limits, endpoints and use cases