Emails
The Emails API allows you to send individual and batch emails, manage scheduling, track delivery status, and monitor bounces, complaints, and unsubscribes.
Base URL
https://api.unsent.dev/v1/emailsOverview
The Emails API provides comprehensive functionality for sending, managing, and tracking emails. It supports both individual and batch sending, template-based emails, scheduling, and detailed tracking capabilities.
Features
Send individual emails
Send single emails with customizable content or templates
Batch email sending
Send up to 100 emails in a single API call
Email scheduling
Schedule emails to be sent at specific times
Email tracking
Track delivery status, bounces, complaints, and unsubscribes
Email management
Update, reschedule, or cancel scheduled emails
Attachments
Send up to 10 attachments with your emails
Custom headers
Add custom SMTP headers to your emails
Quick Start
Send a simple email
curl -X POST https://api.unsent.dev/v1/emails \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"to": "recipient@example.com",
"from": "sender@yourdomain.com",
"subject": "Hello from Unsent",
"text": "This is a plain text email",
"html": "<p>This is an <strong>HTML</strong> email</p>"
}'Send with a template
curl -X POST https://api.unsent.dev/v1/emails \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"from": "sender@yourdomain.com",
"templateId": "template_abc123",
"variables": {
"name": "John Doe",
"orderNumber": "12345"
}
}'Schedule an email
curl -X POST https://api.unsent.dev/v1/emails \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"to": "recipient@example.com",
"from": "sender@yourdomain.com",
"subject": "Scheduled email",
"html": "<p>This email is scheduled for later.</p>",
"scheduledAt": "2024-12-25T10:00:00Z"
}'API Endpoints
Endpoint Details
Send Email
POST /v1/emails
Send a single email with full customization options.
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
to | string or string[] | Yes | Recipient email address(es) |
from | string | Yes | Sender email address |
subject | string | Conditional* | Email subject line |
html | string | Conditional* | HTML email body |
text | string | Conditional* | Plain text email body |
templateId | string | No | ID of a template to use |
variables | object | No | Key-value pairs for template variables (e.g., {{name}}) |
replyTo | string or string[] | No | Reply-to address(es) |
cc | string or string[] | No | CC recipient(s) |
bcc | string or string[] | No | BCC recipient(s) |
headers | object | No | Custom SMTP headers |
attachments | array | No | File attachments (max 10) |
scheduledAt | string | No | ISO 8601 datetime to schedule sending |
inReplyToId | string | No | Email ID this is replying to |
*Required: Either subject or templateId must be provided. Either text, html, or templateId must be provided.
Using Templates
When using templateId:
- The template must belong to your team
subject,html, andtextare optional (template values will be used)- You can override template values by providing them in the request
- Use
variablesto replace placeholders like{{name}}in the template
Attachments Format
{
"attachments": [
{
"filename": "invoice.pdf",
"content": "base64-encoded-file-content"
}
]
}Response
{
"emailId": "email_abc123"
}Batch Send Emails
POST /v1/emails/batch
Send multiple emails in a single request (up to 100 emails per batch).
Request Body
An array of email objects, each following the same schema as the single email endpoint:
[
{
"to": "user1@example.com",
"from": "sender@yourdomain.com",
"subject": "Welcome!",
"html": "<p>Welcome to our service!</p>"
},
{
"to": "user2@example.com",
"from": "sender@yourdomain.com",
"subject": "Welcome!",
"html": "<p>Welcome to our service!</p>"
}
]Response
{
"data": [
{ "emailId": "email_abc123" },
{ "emailId": "email_def456" }
]
}List Emails
GET /v1/emails
Retrieve a paginated list of emails sent by your team.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number for pagination |
limit | number | 20 | Number of results per page (max 20) |
startDate | string | - | Filter emails created after this ISO 8601 date |
endDate | string | - | Filter emails created before this ISO 8601 date |
domainId | string or string[] | - | Filter by domain ID(s) |
Example Request
curl -X GET "https://api.unsent.dev/v1/emails?page=1&limit=20&startDate=2024-01-01T00:00:00Z" \
-H "Authorization: Bearer your-api-key"Response
{
"data": [
{
"id": "email_abc123",
"to": "user@example.com",
"from": "sender@yourdomain.com",
"subject": "Welcome!",
"html": "<p>Welcome!</p>",
"text": null,
"latestStatus": "DELIVERED",
"scheduledAt": null,
"domainId": "domain_xyz",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:15Z",
"replyTo": null,
"cc": null,
"bcc": null
}
],
"count": 150
}Get Email Details
GET /v1/emails/{emailId}
Retrieve detailed information about a specific email, including delivery events.
Response
{
"id": "email_abc123",
"teamId": "team_xyz",
"to": "user@example.com",
"from": "sender@yourdomain.com",
"subject": "Welcome!",
"html": "<p>Welcome!</p>",
"text": null,
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:15Z",
"replyTo": null,
"cc": null,
"bcc": null,
"emailEvents": [
{
"emailId": "email_abc123",
"status": "QUEUED",
"createdAt": "2024-01-15T10:30:00Z",
"data": {}
},
{
"emailId": "email_abc123",
"status": "SENT",
"createdAt": "2024-01-15T10:30:01Z",
"data": {}
},
{
"emailId": "email_abc123",
"status": "DELIVERED",
"createdAt": "2024-01-15T10:30:15Z",
"data": {}
}
]
}Email Status Values
QUEUED- Email is queued for sendingSENT- Email has been sent to the SMTP serverDELIVERED- Email was successfully deliveredBOUNCED- Email bouncedCOMPLAINED- Recipient marked as spamOPENED- Recipient opened the emailCLICKED- Recipient clicked a link
Get Email Events
GET /v1/emails/{emailId}/events
Retrieve all events (sent, delivered, opened, etc.) for a specific email.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
emailId | string | Yes | The unique identifier of the email |
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | No | 1 | Page number |
limit | number | No | 50 | Results per page (max 100) |
status | string | No | - | Filter by event status (e.g., DELIVERED, OPENED) |
startDate | string | No | - | Filter events after this date (ISO 8601) |
curl -X GET https://api.unsent.dev/v1/emails/email_123/events?limit=10 \
-H "Authorization: Bearer your-api-key"Response (200 OK):
{
"events": [
{
"id": "evt_123",
"emailId": "email_123",
"status": "DELIVERED",
"data": {},
"teamId": "team_abc",
"createdAt": "2024-01-15T10:30:15Z"
},
{
"id": "evt_122",
"emailId": "email_123",
"status": "SENT",
"data": {},
"teamId": "team_abc",
"createdAt": "2024-01-15T10:30:01Z"
}
],
"page": 1,
"limit": 10
}Error Responses:
- 400 Bad Request - Invalid parameters
- 401 Unauthorized - Invalid API key
- 404 Not Found - Email not found
- 500 Internal Server Error - Server error
Update Email
PATCH /v1/emails/{emailId}
Update a scheduled email's send time or clear the schedule.
Request Body
{
"scheduledAt": "2024-12-26T10:00:00Z" // or null to clear
}Use Cases
- Reschedule an email to a different time
- Clear scheduling by passing
nullto send immediately
Response
{
"emailId": "email_abc123"
}Cancel Email
POST /v1/emails/{emailId}/cancel
Cancel a scheduled email before it's sent.
Note: You can only cancel emails that are scheduled (not yet sent).
Response
{
"emailId": "email_abc123"
}Get Bounces
GET /v1/emails/bounces
Retrieve a list of emails that bounced.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Results per page (max 100) |
Response
{
"data": [
{
"id": "email_abc123",
"email": "bounced@example.com",
"subject": "Welcome!",
"status": "BOUNCED",
"createdAt": "2024-01-15T10:30:00Z"
}
],
"count": 5
}Get Complaints
GET /v1/emails/complaints
Retrieve emails that were marked as spam by recipients.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Results per page (max 100) |
Response
{
"data": [
{
"id": "email_abc123",
"email": "user@example.com",
"subject": "Newsletter",
"status": "COMPLAINED",
"createdAt": "2024-01-15T10:30:00Z"
}
],
"count": 2
}Get Unsubscribes
GET /v1/emails/unsubscribes
Retrieve contacts who have unsubscribed from your emails.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Results per page (max 100) |
Response
{
"data": [
{
"id": "contact_abc123",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"reason": "UNSUBSCRIBED",
"contactBookId": "book_xyz",
"createdAt": "2024-01-15T10:30:00Z"
}
],
"count": 10
}Idempotency
The Emails API supports idempotency for both single and batch email sending to prevent duplicate sends during retries.
How It Works
Pass an Idempotency-Key header (up to 256 characters) with your request:
- Same key + same request body → Returns the original
emailIdwith 200 OK without re-sending - Same key + different request body → Returns 409 Conflict with code
NOT_UNIQUE - Same key while request is processing → Returns 409 Conflict; retry after completion
Idempotency entries expire after 24 hours.
Example Usage
curl -X POST https://api.unsent.dev/v1/emails \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-12345-confirmation" \
-d '{
"to": "customer@example.com",
"from": "orders@yourdomain.com",
"subject": "Order Confirmation",
"html": "<p>Thank you for your order!</p>"
}'Best Practices
- Use unique keys per logical operation (e.g., order ID, signup ID)
- Include context in the key for debugging (e.g.,
order-12345-confirmation) - Reuse the same key when retrying a failed request
- Works with both
/v1/emailsand/v1/emails/batchendpoints
Common Use Cases
Transactional Emails
- Password resets
- Order confirmations
- Shipping notifications
- Account verifications
Marketing Emails
- Newsletters
- Promotional campaigns
- Product announcements
- Customer engagement
Automated Notifications
- System alerts
- Status updates
- Reminder emails
- Report deliveries
Rate Limits
- Send email (
POST /v1/emails): 100 requests per minute - Batch send (
POST /v1/emails/batch): 1000 emails per minute (max 100 per batch) - List/Get endpoints: 100 requests per minute
- Tracking endpoints (bounces/complaints/unsubscribes): 100 requests per minute
Best Practices
Sending Emails
- Use templates for consistent branding and easier maintenance
- Include both text and HTML versions for better deliverability and accessibility
- Verify your sending domain before going to production
- Use idempotency keys for critical transactional emails to prevent duplicates
- Set appropriate reply-to addresses to handle customer responses
Performance
- Use batch sending (
/v1/emails/batch) when sending to multiple recipients - Schedule emails during off-peak hours for better deliverability
- Limit attachments to necessary files only (max 10 per email)
Tracking & Monitoring
- Monitor bounces regularly via
/v1/emails/bouncesand remove invalid addresses - Handle complaints by checking
/v1/emails/complaintsand respecting opt-outs - Track unsubscribes via
/v1/emails/unsubscribesand update your contact lists - Use email events from
GET /v1/emails/{emailId}to track delivery lifecycle
Template Usage
- Create reusable templates in the dashboard for common email types
- Use variables (
{{name}},{{orderNumber}}) for personalization - Override template content when needed by passing
subject,html, ortextin the request - Test templates before using them in production campaigns