Sending emails
Sending emails through Freesend.
API Endpoint
Prerequisites
Steps
Bearer Token
Ensure you put your API Key as a Bearer token in the Authorization header of the HTTP request:
'Authorization': `Bearer YOUR_API_KEY`
HTTP Body
{
"fromName": "Your Company", // (optional) Display name for the sender
"fromEmail": "hello@yourdomain.com", // Sender email address
"to": "recipient@email.com", // Receiver address
"subject": "Email sent from Freesend!", // Subject for the email
"html": "<h1>Yay! You got the email.</h1>", // (optional) HTML format of the email body
"text": "Yay! You got the email.", // (optional) Text format of the email body
"attachments": [ // (optional) Array of attachments
{
"filename": "invoice.pdf", // Name of the file
"content": "base64EncodedContent", // Base64 encoded file content (optional if url is provided)
"url": "https://example.com/file.pdf", // URL to external file (optional if content is provided)
"contentType": "application/pdf" // (optional) MIME type
}
]
}
API Endpoint
Send a POST
Request to https://freesend.metafog.io/api/send-email
Example Usage
💡 Pro Tip: For a better developer experience, consider using our Freesend SDK which provides type safety, error handling, and a cleaner API.
Send attachments from a remote file
Include the url
parameter to send attachments from a remote file. This parameter accepts a URL to the file you want to attach. Define the file name that will be attached using the filename
parameter.
curl -X POST https://freesend.metafog.io/api/send-email \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fromName": "Your Company",
"fromEmail": "hello@yourdomain.com",
"to": "recipient@email.com",
"subject": "Email with external attachments!",
"html": "<h1>Please find the files attached.</h1>",
"text": "Please find the files attached.",
"attachments": [
{
"filename": "monthly-report.pdf",
"url": "https://example.com/reports/monthly-report.pdf",
"contentType": "application/pdf"
},
{
"filename": "company-logo.png",
"url": "https://example.com/images/logo.png",
"contentType": "image/png"
}
]
}'
Send attachments from a local file
Include the content
parameter to send attachments from a local file. This parameter accepts the Base64 encoded content of the file you want to attach. Define the file name that will be attached using the filename
parameter.
curl -X POST https://freesend.metafog.io/api/send-email \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fromName": "Your Company",
"fromEmail": "hello@yourdomain.com",
"to": "recipient@email.com",
"subject": "Email with attachment from Freesend!",
"html": "<h1>Please find the invoice attached.</h1>",
"text": "Please find the invoice attached.",
"attachments": [
{
"filename": "invoice.pdf",
"content": "JVBERi0xLjQKJcOkw7zDtsOmCjUgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aC...",
"contentType": "application/pdf"
}
]
}'
Field Reference
Main Fields
Field | Type | Required | Description |
---|---|---|---|
fromName | string | No | Display name for the sender (e.g., "Your Company") |
fromEmail | string | Yes | Sender email address |
to | string | Yes | Recipient email address |
subject | string | Yes | Email subject line |
html | string | No* | HTML content of the email |
text | string | No* | Plain text content of the email |
attachments | array | No | Array of attachment objects (see below) |
*At least one of html
or text
is required.
Attachment Object Fields
Field | Type | Required | Description |
---|---|---|---|
filename | string | Yes | Name of the attachment file |
content | string | No* | Base64 encoded file content |
url | string | No* | URL to external file (HTTP/HTTPS only) |
contentType | string | No | MIME type (e.g., "application/pdf", "image/png") |
*Either content
or url
is required, but not both.
Attachment Examples
// Base64 content (recommended for API usage)
{
"filename": "invoice.pdf",
"content": "JVBERi0xLjQKJcOkw7zDtsOmCjUgMCBvYmoKPDwK...",
"contentType": "application/pdf"
}
// URL-based attachment (external file)
{
"filename": "report.pdf",
"url": "https://example.com/reports/monthly-report.pdf",
"contentType": "application/pdf"
}
// Text attachment with base64
{
"filename": "notes.txt",
"content": "SGVsbG8gV29ybGQh", // "Hello World!" in base64
"contentType": "text/plain"
}
// Image attachment from URL
{
"filename": "logo.png",
"url": "https://example.com/images/company-logo.png",
"contentType": "image/png"
}
// Mixed attachments (base64 + URL)
{
"attachments": [
{
"filename": "invoice.pdf",
"content": "base64EncodedPDF...",
"contentType": "application/pdf"
},
{
"filename": "receipt.jpg",
"url": "https://example.com/receipts/12345.jpg",
"contentType": "image/jpeg"
}
]
}
Using the SDK Instead?
If you prefer a more developer-friendly experience with type safety, error handling, and simplified API calls, we provide official SDKs for multiple programming languages.
Available SDKs
- JavaScript/TypeScript - Full TypeScript support, Node.js & browser compatibility
- Python - Python SDK (Coming Soon)
- Go - Go SDK (Coming Soon)
- PHP - PHP SDK (Coming Soon)
- Ruby - Ruby SDK (Coming Soon)
Benefits of Using an SDK
- ✨ Type Safety - Full type definitions and IntelliSense
- 🛡️ Error Handling - Proper error types and status codes
- 🔧 Simplified API - No need to handle HTTP requests manually
- 📎 Attachment Support - Easy file handling with base64 encoding
- 🌐 Cross-Platform - Works in Node.js and browsers
- ⚙️ Customizable - Support for custom base URLs
For complete SDK documentation, examples, and advanced usage, visit our SDK documentation.
Response
Success Response (200)
{
"message": "Email sent successfully"
}
Error Responses
400 Bad Request - Missing Authorization Header
{
"error": "Authorization header not found."
}
400 Bad Request - Invalid Authorization Format
{
"error": "Invalid authorization header. Create a Bearer Token."
}
400 Bad Request - Missing API Key
{
"error": "Invalid or missing API Key."
}
400 Bad Request - Missing Required Fields
{
"error": "Missing required field 'fromEmail'."
}
{
"error": "Missing required field 'to'."
}
{
"error": "Missing required field 'subject'."
}
{
"error": "Missing required field 'text' or 'html'."
}
400 Bad Request - Inactive API Key
{
"error": "This API key is currently inactive."
}
403 Forbidden - Invalid API Key
{
"error": "Invalid API Key or no SMTP configuration found."
}
400 Bad Request - Invalid Attachment Configuration
{
"error": "Attachment 'filename.pdf' must have either 'content' or 'url' field."
}
{
"error": "Attachment 'filename.pdf' cannot have both 'content' and 'url' fields. Use either one."
}
{
"error": "Attachment 'filename.pdf' has invalid URL protocol. Only HTTP and HTTPS are allowed."
}
{
"error": "Attachment 'filename.pdf' has invalid URL format."
}
{
"error": "Attachment 'filename.pdf' URL is not allowed. Internal/local URLs are blocked for security."
}
{
"error": "Attachment 'filename.pdf' URL port is not allowed. Internal service ports are blocked for security."
}
{
"error": "Attachment 'filename.pdf' URL is not allowed. Access to the hosting server is blocked for security."
}
500 Internal Server Error - Email Sending Failed
{
"error": "Error sending email: [specific error message]"
}
500 Internal Server Error - URL Fetch Failed
{
"error": "Error processing attachment 'filename.pdf': Failed to fetch attachment from URL: 404 Not Found"
}
{
"error": "Error processing attachment 'filename.pdf': Timeout fetching attachment from URL (30s limit)"
}
{
"error": "Error processing attachment 'filename.pdf': Attachment file too large: 30MB (max 25MB)"
}
502 Bad Gateway - Transport Error
{
"error": "Could not create the transporter object."
}
Common MIME Types
File Extension | MIME Type |
---|---|
.pdf | application/pdf |
.jpg , .jpeg | image/jpeg |
.png | image/png |
.gif | image/gif |
.txt | text/plain |
.html | text/html |
.css | text/css |
.js | application/javascript |
.json | application/json |
.xml | application/xml |
.csv | text/csv |
.zip | application/zip |
.xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
.pptx | application/vnd.openxmlformats-officedocument.presentationml.presentation |
Security Note
Important: Freesend supports two types of attachments:
- Base64-encoded content: For direct file uploads (recommended for smaller files)
- URL-based attachments: For external files accessible via HTTP/HTTPS URLs
Security Protections:
- Server-side file paths are not supported
- Internal/local URLs are blocked (localhost, private IPs, .local domains)
- Access to the hosting server is blocked
- Common internal service ports are blocked
- Only public, external URLs are allowed
Best Practices
File Size Limits
- Keep base64 attachments under 25MB for best performance
- For larger files, consider using URL-based attachments instead
- URL-based attachments can handle larger files since they're downloaded on-demand
Base64 Encoding
- Always encode binary files as base64
- Remove any data URL prefixes (e.g.,
data:application/pdf;base64,
) - Use proper content type headers for better email client compatibility
URL-based Attachments
- Ensure URLs are publicly accessible and return proper HTTP status codes
- Use HTTPS URLs for security
- URLs should return the actual file content, not redirects
- File size limit: 25MB per attachment
- Timeout limit: 30 seconds per URL fetch
- URLs must be accessible from Freesend's servers
- Security: Only external, public URLs are allowed (internal/local URLs are blocked)
Multiple Attachments
{
"attachments": [
{
"filename": "invoice.pdf",
"content": "base64EncodedPDF...",
"contentType": "application/pdf"
},
{
"filename": "receipt.jpg",
"url": "https://example.com/receipts/12345.jpg",
"contentType": "image/jpeg"
},
{
"filename": "report.pdf",
"url": "https://api.example.com/reports/monthly.pdf",
"contentType": "application/pdf"
}
]
}