Send Email
POST /api/v1/messages
Required permission: send
Sends a single transactional email. The message is queued immediately and delivered asynchronously. You receive a message_id to track delivery status.
Request body
{ "from_email": "hello@yourdomain.com", "from_name": "Your App", "to_email": "user@example.com", "to_name": "John Doe", "subject": "Your order is confirmed", "body": "<h1>Order confirmed</h1><p>Thanks for your purchase.</p>", "reply_to": "support@yourdomain.com", "attachments": [ { "filename": "invoice.pdf", "content": "JVBERi0xLjQK...", "content_type": "application/pdf" } ]}Fields
| Field | Type | Required | Description |
|---|---|---|---|
from_email | string | ✅ | Sender address. Must belong to a verified domain on your account. |
from_name | string | — | Sender display name shown in email clients. |
to_email | string | ✅ | Recipient email address. |
to_name | string | — | Recipient display name. |
subject | string | ✅ | Email subject line (max 998 characters). |
body | string | ✅ | HTML email body. Dangerous tags (<script>, <iframe>, on* handlers) are automatically stripped. |
reply_to | string | — | Reply-To address. Recipients’ mail clients direct replies here instead of from_email. |
attachments | array | — | File attachments (see below). |
Attachment object
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | ✅ | Filename shown to the recipient (max 255 chars). |
content | string | ✅ | Base64-encoded file content. |
content_type | string | ✅ | MIME type, e.g. application/pdf, image/png. |
Response
HTTP 202 Accepted
{ "status": "success", "data": { "message_id": "550e8400-e29b-41d4-a716-446655440000" }}The message_id is a UUID you can use to:
- Query message status via
GET /api/v1/messages/{id} - Correlate webhook events
Code examples
curl -X POST https://api.emitlo.com/api/v1/messages \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from_email": "hello@yourdomain.com", "from_name": "Your App", "to_email": "user@example.com", "subject": "Your order is confirmed", "body": "<h1>Order confirmed</h1><p>Thanks for your purchase.</p>" }'const response = await fetch('https://api.emitlo.com/api/v1/messages', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ from_email: 'hello@yourdomain.com', from_name: 'Your App', to_email: 'user@example.com', subject: 'Your order is confirmed', body: '<h1>Order confirmed</h1><p>Thanks for your purchase.</p>', }),});
if (!response.ok) { const error = await response.json(); throw new Error(error.error.message);}
const { data } = await response.json();console.log('Sent:', data.message_id);<?php$ch = curl_init('https://api.emitlo.com/api/v1/messages');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'from_email' => 'hello@yourdomain.com', 'from_name' => 'Your App', 'to_email' => 'user@example.com', 'subject' => 'Your order is confirmed', 'body' => '<h1>Order confirmed</h1><p>Thanks for your purchase.</p>', ]),]);
$response = json_decode(curl_exec($ch), true);curl_close($ch);
echo $response['data']['message_id'];import httpx
client = httpx.Client()
response = client.post( "https://api.emitlo.com/api/v1/messages", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "from_email": "hello@yourdomain.com", "from_name": "Your App", "to_email": "user@example.com", "subject": "Your order is confirmed", "body": "<h1>Order confirmed</h1><p>Thanks for your purchase.</p>", },)
response.raise_for_status()print(response.json()["data"]["message_id"])With attachment
import { readFileSync } from 'fs';
const pdf = readFileSync('./invoice.pdf');
const response = await fetch('https://api.emitlo.com/api/v1/messages', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ from_email: 'billing@yourdomain.com', to_email: 'customer@example.com', subject: 'Your invoice #1042', body: '<p>Please find your invoice attached.</p>', attachments: [ { filename: 'invoice-1042.pdf', content: pdf.toString('base64'), content_type: 'application/pdf', }, ], }),});import base64, httpx
with open("invoice.pdf", "rb") as f: pdf_b64 = base64.b64encode(f.read()).decode()
response = httpx.post( "https://api.emitlo.com/api/v1/messages", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "from_email": "billing@yourdomain.com", "to_email": "customer@example.com", "subject": "Your invoice #1042", "body": "<p>Please find your invoice attached.</p>", "attachments": [ { "filename": "invoice-1042.pdf", "content": pdf_b64, "content_type": "application/pdf", } ], },)Common errors
| Error | Cause | Fix |
|---|---|---|
UNAUTHENTICATED | Invalid API key | Check your Authorization header |
FORBIDDEN | Credential missing send permission | Create a credential with send permission |
VALIDATION_ERROR on from_email | Domain not verified | Verify your domain first |
RATE_LIMITED | Too many requests | Respect the Retry-After header |
ATTACHMENT_TOO_LARGE | File exceeds plan limit | Compress the file or upgrade your plan |