Emails API
Send single or bulk personalized emails with attachments using the Forma Mail API.
Try it live! Use the Interactive API Explorer for a full interactive experience with all endpoints.
Overview
The Emails API allows you to send template-based emails with:
- Variable substitution - Personalize emails with dynamic content
- Multiple recipients - Send to, CC, and BCC recipients
- Attachments - Include PDF, Excel, or file attachments
- Template-generated attachments - Dynamically create attachments from templates
- Scheduling - Schedule emails for future delivery
- Priority control - Set email priority (high, normal, low)
- Bulk sending - Send personalized emails to up to 1,000 recipients
Base URL: https://api.formamail.com/api
Authentication: All endpoints require an API Key
Send Email
Send a single email using a template.
Endpoint
POST /emails/sendHeaders
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | UUID of the email template to use |
version | string | No | Template version: published (default), draft, or version number |
to | array | Yes | Array of recipient objects (email + optional name) |
cc | array | No | Array of CC recipient objects |
bcc | array | No | Array of BCC recipient objects |
replyTo | string | No | Reply-to email address |
variables | object | Yes | Variables to populate the template |
attachments | array | No | Array of attachment objects |
priority | string | No | Email priority: low, normal (default), high |
scheduledAt | string | No | ISO 8601 datetime for scheduled sending |
headers | object | No | Custom email headers (key-value pairs) |
tags | array | No | Tags for categorization (max 50, alphanumeric/hyphen/underscore) |
metadata | object | No | Custom metadata for tracking |
Recipient Object
{
"email": "user@example.com",
"name": "John Doe"
}Attachment Object
You can attach files in multiple ways:
Option 1: Base64 Content
{
"filename": "invoice.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjQK..."
}Option 2: URL
{
"filename": "report.pdf",
"contentType": "application/pdf",
"url": "https://example.com/files/report.pdf"
}Option 3: Template-Generated (PDF/Excel)
{
"filename": "invoice-{{invoiceNumber}}.pdf",
"attachmentTemplateId": "template-uuid",
"variables": {
"invoiceNumber": "INV-001",
"amount": 150.00
},
"outputFormats": ["pdf"]
}Option 4: Asset Gallery
{
"filename": "company-logo.png",
"assetId": "asset-uuid"
}Example Request
Basic Email
curl -X POST https://api.formamail.com/api/emails/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"to": [
{
"email": "customer@example.com",
"name": "Jane Smith"
}
],
"variables": {
"firstName": "Jane",
"orderNumber": "ORD-12345",
"totalAmount": "$150.00",
"orderDate": "2024-11-19"
}
}'Email with PDF Attachment
curl -X POST https://api.formamail.com/api/emails/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"to": [{
"email": "customer@example.com",
"name": "Jane Smith"
}],
"variables": {
"firstName": "Jane",
"invoiceNumber": "INV-2024-001"
},
"attachments": [{
"filename": "invoice-{{invoiceNumber}}.pdf",
"attachmentTemplateId": "660e8400-e29b-41d4-a716-446655440001",
"variables": {
"customerName": "Jane Smith",
"invoiceNumber": "INV-2024-001",
"amount": 299.99,
"items": [
{"name": "Product A", "qty": 2, "price": 99.99},
{"name": "Product B", "qty": 1, "price": 100.00}
]
},
"outputFormats": ["pdf"]
}]
}'Scheduled Email
curl -X POST https://api.formamail.com/api/emails/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"to": [{"email": "customer@example.com"}],
"variables": {"name": "Customer"},
"scheduledAt": "2024-12-25T10:00:00Z",
"priority": "high"
}'Response
Success (201 Created)
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"messageId": "<1234567890@formamail.com>",
"status": "queued",
"recipientCount": 1,
"attachmentCount": 1,
"queuedAt": "2024-11-19T12:00:00.000Z",
"estimatedDeliveryAt": "2024-11-19T12:00:30.000Z"
}Response Fields:
| Field | Type | Description |
|---|---|---|
id | string | Unique email log ID |
messageId | string | RFC 5322 message ID |
status | string | Email status: queued, scheduled, processing, sent, delivered, failed |
recipientCount | number | Total number of recipients (to + cc + bcc) |
attachmentCount | number | Total number of attachments |
queuedAt | string | Timestamp when email was queued |
estimatedDeliveryAt | string | Estimated delivery time |
Try It
Ready to test this endpoint?
- Interactive API Explorer - Full OpenAPI documentation with request builder
- API Playground - Test with your API key in the dashboard
Bulk Personalized Send
Send personalized emails to multiple recipients (up to 1,000 per request).
Endpoint
POST /emails/send/bulkKey Features
- âś… Personalized variables per recipient
- âś… Template-generated attachments (PDF/Excel) per recipient
- âś… Base variables shared across all recipients
- âś… Dry run mode for validation without sending
- âś… Progress tracking with batch status endpoint
- âś… Scheduling for future delivery
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Email template UUID |
version | string | No | Template version (default: published) |
recipients | array | Yes | Array of recipient objects (min: 1, max: 1000) |
baseVariables | object | No | Variables shared across all recipients |
attachments | array | No | Attachments for all recipients |
replyTo | string | No | Reply-to email address |
priority | string | No | Priority: low, normal, high |
headers | object | No | Custom headers |
tags | array | No | Tags for tracking |
metadata | object | No | Metadata for tracking |
batchName | string | No | Name for this batch |
dryRun | boolean | No | Validate without sending (default: false) |
scheduledAt | string | No | Schedule for future delivery |
Recipient Object (Bulk)
{
"email": "customer@example.com",
"name": "John Doe",
"variables": {
"firstName": "John",
"invoiceNumber": "INV-001",
"amount": 150.00,
"items": [...]
},
"attachmentOverrides": [...]
}Bulk Attachment Object
{
"filename": "invoice-{{invoiceNumber}}.pdf",
"attachmentTemplateId": "template-uuid",
"baseVariables": {
"companyName": "Acme Corp",
"companyLogo": "https://example.com/logo.png"
},
"recipientVariableFields": ["invoiceNumber", "amount", "items"],
"outputFormats": ["pdf"],
"required": true
}Example Requests
Basic Bulk Send
curl -X POST https://api.formamail.com/api/emails/send/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"baseVariables": {
"companyName": "Acme Corp",
"supportEmail": "support@acme.com",
"year": 2024
},
"recipients": [
{
"email": "customer1@example.com",
"name": "John Doe",
"variables": {
"firstName": "John",
"orderNumber": "ORD-001",
"amount": 99.99
}
},
{
"email": "customer2@example.com",
"name": "Jane Smith",
"variables": {
"firstName": "Jane",
"orderNumber": "ORD-002",
"amount": 149.99
}
}
],
"batchName": "Monthly Newsletter - November 2024"
}'Bulk with Template-Generated PDFs
curl -X POST https://api.formamail.com/api/emails/send/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "email-template-uuid",
"baseVariables": {
"companyName": "Acme Corp",
"companyAddress": "123 Business St",
"taxRate": 0.08
},
"attachments": [{
"filename": "invoice-{{invoiceNumber}}.pdf",
"attachmentTemplateId": "invoice-template-uuid",
"baseVariables": {
"companyLogo": "https://acme.com/logo.png",
"footer": "Thank you for your business!"
},
"recipientVariableFields": ["invoiceNumber", "customerInfo", "items", "total"],
"outputFormats": ["pdf"],
"required": true
}],
"recipients": [
{
"email": "customer1@example.com",
"name": "John Doe",
"variables": {
"firstName": "John",
"invoiceNumber": "INV-2024-001",
"customerInfo": {
"name": "John Doe",
"address": "456 Customer Lane",
"phone": "+1-555-0001"
},
"items": [
{"description": "Product A", "quantity": 2, "price": 50.00},
{"description": "Product B", "quantity": 1, "price": 75.00}
],
"total": 175.00
}
},
{
"email": "customer2@example.com",
"name": "Jane Smith",
"variables": {
"firstName": "Jane",
"invoiceNumber": "INV-2024-002",
"customerInfo": {
"name": "Jane Smith",
"address": "789 Client Road",
"phone": "+1-555-0002"
},
"items": [
{"description": "Product C", "quantity": 3, "price": 100.00}
],
"total": 300.00
}
}
],
"batchName": "Monthly Invoices - November 2024",
"tags": ["invoices", "billing", "automated"]
}'Dry Run (Validation Only)
curl -X POST https://api.formamail.com/api/emails/send/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"recipients": [{...}, {...}],
"dryRun": true
}'Response
Success (201 Created)
{
"batchId": "880e8400-e29b-41d4-a716-446655440000",
"totalEmails": 100,
"status": "queued",
"message": "Successfully queued 100 emails for sending",
"createdAt": "2024-11-19T12:00:00.000Z",
"estimatedCompletionAt": "2024-11-19T12:05:00.000Z"
}Dry Run Response
{
"valid": true,
"totalEmails": 100,
"totalQuotaCost": 150,
"costBreakdown": {
"emails": 100,
"attachments": 50
},
"quotaStatus": {
"emailQuota": {
"used": 850,
"limit": 1000,
"remaining": 150
},
"attachmentQuota": {
"used": 320,
"limit": 500,
"remaining": 180
}
},
"recipientValidation": {
"totalRecipients": 100,
"validEmails": 98,
"invalidEmails": 2
},
"templateValidation": {
"templateFound": true,
"templateType": "email",
"requiredVariables": ["firstName", "orderNumber"],
"missingVariables": []
},
"warnings": [
"2 recipients have invalid email addresses and will be skipped"
]
}Try It
Ready to test this endpoint?
- Interactive API Explorer - Full OpenAPI documentation with request builder
- API Playground - Test with your API key in the dashboard
Get Batch Status
Track the progress of a bulk email batch.
Endpoint
GET /emails/batch/:batchId/statusExample
curl https://api.formamail.com/api/emails/batch/880e8400-e29b-41d4-a716-446655440000/status \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"batchId": "880e8400-e29b-41d4-a716-446655440000",
"batchName": "Monthly Newsletter - November 2024",
"status": "processing",
"totalEmails": 100,
"sent": 75,
"delivered": 70,
"failed": 2,
"queued": 20,
"processing": 5,
"progress": 75,
"queuedAt": "2024-11-19T12:00:00.000Z",
"startedAt": "2024-11-19T12:00:10.000Z",
"completedAt": null
}Batch Status Values:
queued- Batch is waiting to be processedprocessing- Emails are being sentcompleted- All emails sent (successfully or failed)cancelled- Batch was cancelledscheduled- Batch is scheduled for future sending
Cancel Batch
Cancel a queued or processing batch.
Endpoint
POST /emails/batch/:batchId/cancelExample
curl -X POST https://api.formamail.com/api/emails/batch/880e8400-e29b-41d4-a716-446655440000/cancel \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"batchId": "880e8400-e29b-41d4-a716-446655440000",
"status": "cancelled",
"message": "Batch cancelled successfully. 20 emails were not sent.",
"totalEmails": 100,
"sent": 75,
"cancelled": 20,
"failed": 5
}Get Email Details
Retrieve details of a single email by ID.
Endpoint
GET /emails/:idExample
curl https://api.formamail.com/api/emails/770e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"messageId": "<1234567890@formamail.com>",
"status": "delivered",
"emailTemplateName": "Order Confirmation",
"recipientCount": 1,
"attachmentCount": 1,
"queuedAt": "2024-11-19T12:00:00.000Z",
"processingAt": "2024-11-19T12:00:05.000Z",
"sentAt": "2024-11-19T12:00:10.000Z",
"deliveredAt": "2024-11-19T12:00:15.000Z",
"metadata": {
"recipients": {
"to": [{"email": "customer@example.com", "name": "Jane Smith"}],
"cc": [],
"bcc": []
},
"variables": {
"firstName": "Jane",
"orderNumber": "ORD-12345"
},
"attachments": [...]
},
"createdAt": "2024-11-19T12:00:00.000Z",
"updatedAt": "2024-11-19T12:00:15.000Z"
}Query Emails
Query and filter email logs with pagination.
Endpoint
GET /emails?page=1&limit=20&status=delivered&startDate=2024-11-01Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | number | Page number (default: 1) |
limit | number | Items per page (default: 20, max: 100) |
status | string | Filter by status |
templateId | string | Filter by template |
startDate | string | Filter from date (ISO 8601) |
endDate | string | Filter to date (ISO 8601) |
search | string | Search recipients or subject |
Example
curl "https://api.formamail.com/api/emails?page=1&limit=20&status=delivered" \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"data": [
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"status": "delivered",
"emailTemplateName": "Order Confirmation",
"recipientCount": 1,
"sentAt": "2024-11-19T12:00:10.000Z",
"deliveredAt": "2024-11-19T12:00:15.000Z"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 150,
"totalPages": 8
}
}Retry Failed Email
Retry sending a failed email.
Endpoint
POST /emails/:id/retryExample
curl -X POST https://api.formamail.com/api/emails/770e8400-e29b-41d4-a716-446655440000/retry \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"message": "Email queued for retry",
"retryCount": 1,
"queuedAt": "2024-11-19T13:00:00.000Z"
}Code Examples
Node.js / JavaScript
const axios = require('axios');
const client = axios.create({
baseURL: 'https://api.formamail.com/api',
headers: {
'Authorization': `Bearer ${process.env.FORMA_MAIL_API_KEY}`,
'Content-Type': 'application/json'
}
});
// Send single email
async function sendEmail() {
const response = await client.post('/emails/send', {
templateId: 'your-template-id',
to: [{ email: 'user@example.com', name: 'John Doe' }],
variables: {
firstName: 'John',
orderNumber: 'ORD-12345'
}
});
console.log('Email sent:', response.data.id);
return response.data;
}
// Send bulk personalized emails
async function sendBulkEmails() {
const response = await client.post('/emails/send/bulk', {
templateId: 'your-template-id',
baseVariables: {
companyName: 'Acme Corp'
},
recipients: [
{
email: 'customer1@example.com',
variables: { firstName: 'John', orderNumber: 'ORD-001' }
},
{
email: 'customer2@example.com',
variables: { firstName: 'Jane', orderNumber: 'ORD-002' }
}
],
batchName: 'Order Confirmations'
});
console.log('Batch queued:', response.data.batchId);
// Poll for status
const batchId = response.data.batchId;
const status = await client.get(`/emails/batch/${batchId}/status`);
console.log('Batch progress:', status.data.progress + '%');
return response.data;
}Python
import requests
import os
API_KEY = os.getenv('FORMA_MAIL_API_KEY')
BASE_URL = 'https://api.formamail.com/api'
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
# Send single email
def send_email():
response = requests.post(
f'{BASE_URL}/emails/send',
headers=headers,
json={
'templateId': 'your-template-id',
'to': [{'email': 'user@example.com', 'name': 'John Doe'}],
'variables': {
'firstName': 'John',
'orderNumber': 'ORD-12345'
}
}
)
result = response.json()
print(f"Email sent: {result['id']}")
return result
# Send bulk personalized emails
def send_bulk_emails():
response = requests.post(
f'{BASE_URL}/emails/send/bulk',
headers=headers,
json={
'templateId': 'your-template-id',
'baseVariables': {'companyName': 'Acme Corp'},
'recipients': [
{
'email': 'customer1@example.com',
'variables': {'firstName': 'John', 'orderNumber': 'ORD-001'}
},
{
'email': 'customer2@example.com',
'variables': {'firstName': 'Jane', 'orderNumber': 'ORD-002'}
}
],
'batchName': 'Order Confirmations'
}
)
result = response.json()
print(f"Batch queued: {result['batchId']}")
# Poll for status
batch_id = result['batchId']
status_response = requests.get(
f'{BASE_URL}/emails/batch/{batch_id}/status',
headers=headers
)
status = status_response.json()
print(f"Batch progress: {status['progress']}%")
return resultError Responses
All errors return a structured response:
{
"statusCode": 400,
"code": "VALIDATION_ERROR",
"message": "Invalid request data",
"timestamp": "2024-11-19T12:00:00.000Z",
"path": "/api/emails/send",
"errors": [
{
"field": "to",
"message": "At least one recipient is required"
}
]
}Common Errors
| Status | Code | Description | Solution |
|---|---|---|---|
| 400 | VALIDATION_ERROR | Invalid request data | Check request format and required fields |
| 401 | UNAUTHORIZED | Missing or invalid API key | Include valid API key in Authorization header |
| 404 | TEMPLATE_NOT_FOUND | Template ID not found | Verify template exists and you have access |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests | Wait and retry with exponential backoff |
| 429 | QUOTA_EXCEEDED | Monthly quota exceeded | Upgrade plan or wait for quota reset |
| 500 | INTERNAL_ERROR | Server error | Contact support if persists |
Best Practices
âś… DO
- Use dry run for bulk sends to validate before sending
- Include meaningful tags for easier tracking and filtering
- Store email IDs for tracking and retry logic
- Handle rate limits with exponential backoff
- Monitor batch progress for large bulk sends
- Use base variables for shared data in bulk sends
- Set appropriate priority based on email importance
- Test with small batches before scaling up
❌ DON’T
- Don’t exceed 1,000 recipients per bulk request
- Don’t send without testing templates first
- Don’t ignore quota warnings - monitor usage
- Don’t retry immediately on rate limit errors
- Don’t hardcode template IDs - use environment variables
- Don’t send to unverified domains in production
Next Steps
- Authentication Guide →
- Template Management →
- Attachment Generation →
- Analytics & Tracking →
- Error Handling →
Back to API Reference