Send Email
curl --request POST \
--url https://api.example.com/emails \
--header 'Content-Type: application/json' \
--data '
{
"from": "<string>",
"to": [
"<string>"
],
"subject": "<string>",
"html": "<string>",
"text": "<string>",
"cc": [
"<string>"
],
"bcc": [
"<string>"
],
"reply_to": [
"<string>"
],
"headers": {},
"attachments": [
{}
],
"idempotencyKey": "<string>",
"tracking": {}
}
'import requests
url = "https://api.example.com/emails"
payload = {
"from": "<string>",
"to": ["<string>"],
"subject": "<string>",
"html": "<string>",
"text": "<string>",
"cc": ["<string>"],
"bcc": ["<string>"],
"reply_to": ["<string>"],
"headers": {},
"attachments": [{}],
"idempotencyKey": "<string>",
"tracking": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
from: '<string>',
to: ['<string>'],
subject: '<string>',
html: '<string>',
text: '<string>',
cc: ['<string>'],
bcc: ['<string>'],
reply_to: ['<string>'],
headers: {},
attachments: [{}],
idempotencyKey: '<string>',
tracking: {}
})
};
fetch('https://api.example.com/emails', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/emails",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => '<string>',
'to' => [
'<string>'
],
'subject' => '<string>',
'html' => '<string>',
'text' => '<string>',
'cc' => [
'<string>'
],
'bcc' => [
'<string>'
],
'reply_to' => [
'<string>'
],
'headers' => [
],
'attachments' => [
[
]
],
'idempotencyKey' => '<string>',
'tracking' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/emails"
payload := strings.NewReader("{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/emails")
.header("Content-Type", "application/json")
.body("{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/emails")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "<string>",
"created_at": "<string>",
"to": "<string>",
"subject": "<string>",
"from": "<string>"
}Emails
Send Email
Send a transactional email
Send Email
curl --request POST \
--url https://api.example.com/emails \
--header 'Content-Type: application/json' \
--data '
{
"from": "<string>",
"to": [
"<string>"
],
"subject": "<string>",
"html": "<string>",
"text": "<string>",
"cc": [
"<string>"
],
"bcc": [
"<string>"
],
"reply_to": [
"<string>"
],
"headers": {},
"attachments": [
{}
],
"idempotencyKey": "<string>",
"tracking": {}
}
'import requests
url = "https://api.example.com/emails"
payload = {
"from": "<string>",
"to": ["<string>"],
"subject": "<string>",
"html": "<string>",
"text": "<string>",
"cc": ["<string>"],
"bcc": ["<string>"],
"reply_to": ["<string>"],
"headers": {},
"attachments": [{}],
"idempotencyKey": "<string>",
"tracking": {}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
from: '<string>',
to: ['<string>'],
subject: '<string>',
html: '<string>',
text: '<string>',
cc: ['<string>'],
bcc: ['<string>'],
reply_to: ['<string>'],
headers: {},
attachments: [{}],
idempotencyKey: '<string>',
tracking: {}
})
};
fetch('https://api.example.com/emails', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/emails",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'from' => '<string>',
'to' => [
'<string>'
],
'subject' => '<string>',
'html' => '<string>',
'text' => '<string>',
'cc' => [
'<string>'
],
'bcc' => [
'<string>'
],
'reply_to' => [
'<string>'
],
'headers' => [
],
'attachments' => [
[
]
],
'idempotencyKey' => '<string>',
'tracking' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/emails"
payload := strings.NewReader("{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/emails")
.header("Content-Type", "application/json")
.body("{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/emails")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"from\": \"<string>\",\n \"to\": [\n \"<string>\"\n ],\n \"subject\": \"<string>\",\n \"html\": \"<string>\",\n \"text\": \"<string>\",\n \"cc\": [\n \"<string>\"\n ],\n \"bcc\": [\n \"<string>\"\n ],\n \"reply_to\": [\n \"<string>\"\n ],\n \"headers\": {},\n \"attachments\": [\n {}\n ],\n \"idempotencyKey\": \"<string>\",\n \"tracking\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "<string>",
"created_at": "<string>",
"to": "<string>",
"subject": "<string>",
"from": "<string>"
}Description
Send a transactional email using Sendly. This is the most common and versatile endpoint.Parameters
Email address of the sender. Must be a verified domain in your account.
Examples:
noreply@yourdomain.com, no-reply@mail.yourdomain.comEmail address(es) of the recipient. Can be a string or array.
Email subject. Maximum 255 characters.
HTML content of the email. Required if
text is not provided.Plain text content. Used as fallback if
html is not provided.CC recipient(s). Visible to all recipients.
BCC recipient(s). Visible only on server.
Reply-to address(es).
Custom headers. Example:
{"X-Custom-Header": "value"}Array of file attachments:
filename(string): File namecontent(string | Buffer): Base64 encoded contentcontent_type(string): MIME type (e.g.,application/pdf)cid(string): Content ID for inline images
Unique key to prevent duplicates. Resending with the same key returns the previous response.
Tracking options:
open(boolean): Track opens. Default: falseclick(boolean): Track clicks. Default: false
Response
Unique email ID. Use to check status later.
Current email status.
ISO 8601 timestamp of creation.
Recipient email address.
Email subject.
Sender email address.
Examples
Basic Email
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Welcome!",
"html": "<h1>Hello!</h1><p>Thanks for signing up.</p>"
}'
import { Sendly } from '@sendlyapp/sdk'
const client = new Sendly('se_your_api_key')
const response = await client.emails.send({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome!',
html: '<h1>Hello!</h1><p>Thanks for signing up.</p>'
})
console.log('Email ID:', response.id)
import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
host: 'smtp.usesendly.app',
port: 587,
secure: false,
auth: {
user: 'se_your_api_key',
pass: 'se_your_api_key'
}
})
await transporter.sendMail({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome!',
html: '<h1>Hello!</h1><p>Thanks for signing up.</p>'
})
Multiple Recipients
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": ["user1@example.com", "user2@example.com"],
"cc": "admin@yourdomain.com",
"subject": "Important Notice",
"html": "<p>This is important...</p>"
}'
await client.emails.send({
from: 'noreply@yourdomain.com',
to: ['user1@example.com', 'user2@example.com'],
cc: 'admin@yourdomain.com',
subject: 'Important Notice',
html: '<p>This is important...</p>'
})
await transporter.sendMail({
from: 'noreply@yourdomain.com',
to: ['user1@example.com', 'user2@example.com'],
cc: 'admin@yourdomain.com',
subject: 'Important Notice',
html: '<p>This is important...</p>'
})
With Tracking
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Newsletter",
"html": "<h1>Newsletter</h1><p>Content...</p>",
"tracking": {
"open": true,
"click": true
}
}'
const response = await client.emails.send({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Newsletter',
html: '<h1>Newsletter</h1><p>Content...</p>',
tracking: {
open: true,
click: true
}
})
await transporter.sendMail({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Newsletter',
html: '<h1>Newsletter</h1><p>Content...</p>',
headers: {
'X-Track-Opens': 'true',
'X-Track-Clicks': 'true'
}
})
With Attachments
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Your Document",
"html": "<p>See attached PDF</p>",
"attachments": [
{
"filename": "document.pdf",
"content": "JVBERi0xLjQKJeLj...",
"content_type": "application/pdf"
}
]
}'
import fs from 'fs'
const pdfContent = fs.readFileSync('document.pdf')
const base64 = pdfContent.toString('base64')
await client.emails.send({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Your Document',
html: '<p>See attached PDF</p>',
attachments: [
{
filename: 'document.pdf',
content: base64,
content_type: 'application/pdf'
}
]
})
import fs from 'fs'
await transporter.sendMail({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Your Document',
html: '<p>See attached PDF</p>',
attachments: [
{
filename: 'document.pdf',
path: 'document.pdf'
}
]
})
With Idempotency Key
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Payment Confirmation",
"html": "<p>Your payment was processed</p>",
"idempotencyKey": "payment-123"
}'
await client.emails.send({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Payment Confirmation',
html: '<p>Your payment was processed</p>',
idempotencyKey: 'payment-123'
})
await transporter.sendMail({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Payment Confirmation',
html: '<p>Your payment was processed</p>',
messageId: 'payment-123'
})
Error Handling
import { SendlyError } from '@sendlyapp/sdk'
try {
await client.emails.send({
from: 'noreply@invalid.com',
to: 'user@example.com',
subject: 'Email',
html: '<p>Content</p>'
})
} catch (error) {
if (error instanceof SendlyError) {
console.error(`Error ${error.status}: ${error.message}`)
}
}
# Will return 400 Bad Request with error details
curl -X POST https://api.usesendly.app/v1/emails \
-H "Authorization: Bearer se_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "invalid-email",
"to": "user@example.com"
}'
# Response:
# {
# "code": "INVALID_EMAIL",
# "message": "The email address is invalid",
# "status": 400
# }
Limits
- Recipients per email: Maximum 10,000
- Attachment size: Maximum 25 MB per email
- Send rate: 1,000 emails/minute
- Auto-retries: Up to 5 times for temporary errors
Notes
- The
fromaddress must be a verified domain - Emails are queued for immediate processing
- Initial status is always
QUEUED - Use
idempotencyKeyfor critical transactions - Open tracking requires an image in the email
Need help? Contact support@usesendly.app
⌘I