Getting Started
Maillayer is a transactional email API built for developers. Send emails with a single REST API call — no SMTP configuration, no complex SDKs.
Base URL
All API requests are made to:
https://maillayer.com
How it works
- Add and verify your domain — configure DKIM records so your emails are properly authenticated.
- Create an API key — generate a key from the dashboard to authenticate your requests.
- Send emails — POST to
/api/v1/emailswith your payload. Maillayer queues, sends, and tracks delivery.
Authentication
All API requests require a Bearer token in the Authorization header. API keys are created from the Maillayer dashboard.
Header format
Authorization: Bearer ml_live_your_api_key
API key types
| Prefix | Environment | Description |
|---|---|---|
ml_live_ | Production | Sends real emails. Use in production. |
ml_test_ | Test | Validates requests but does not send. Use for development. |
Example request
curl https://maillayer.com/api/v1/emails \
-H "Authorization: Bearer ml_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"from":"[email protected]","to":"[email protected]","subject":"Test","text":"Hello"}'Send Email
Send a transactional email by making a POST request. Emails are queued and sent asynchronously with automatic retries.
/api/v1/emailsRequest body
fromstringrequiredtostringrequiredsubjectstringrequiredhtmlstringhtml or text is required.textstringhtml is also provided.replyTostringccstring[]bccstring[]tagsstring[]Example request
curl -X POST https://maillayer.com/api/v1/emails \
-H "Authorization: Bearer ml_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "[email protected]",
"to": "[email protected]",
"subject": "Order Confirmed",
"html": "<h1>Thanks for your order!</h1><p>We\'ll ship it soon.</p>",
"replyTo": "[email protected]",
"tags": ["order", "transactional"]
}'Example with Node.js
const response = await fetch('https://maillayer.com/api/v1/emails', {
method: 'POST',
headers: {
'Authorization': 'Bearer ml_live_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome to Acme',
html: '<p>Thanks for signing up!</p>',
}),
});
const data = await response.json();
console.log(data.id); // "665f1a2b3c4d5e6f7a8b9c0d"Response
Returns 202 Accepted when the email is queued for delivery.
{
"id": "665f1a2b3c4d5e6f7a8b9c0d",
"status": "queued",
"from": "[email protected]",
"to": "[email protected]",
"subject": "Order Confirmed",
"createdAt": "2025-01-15T10:30:00.000Z"
}Domains
Before sending emails, you must add and verify at least one domain. Verification configures DKIM signing to authenticate your emails and improve deliverability.
Adding a domain
- Go to Domains in the Maillayer dashboard.
- Enter your domain name (e.g.
yourdomain.com) and click Add Domain. - Maillayer generates 3 CNAME records for DKIM verification.
DNS configuration
Add the provided CNAME records to your domain's DNS settings. The records look like this:
| Type | Name | Value |
|---|---|---|
CNAME | abcdef._domainkey.yourdomain.com | abcdef.dkim.amazonses.com |
CNAME | ghijkl._domainkey.yourdomain.com | ghijkl.dkim.amazonses.com |
CNAME | mnopqr._domainkey.yourdomain.com | mnopqr.dkim.amazonses.com |
Verification
After adding the DNS records, click Verify in the dashboard. DNS propagation typically takes a few minutes but can take up to 72 hours. Once verified, the domain status changes to verified and you can start sending.
403 error.API Keys
API keys authenticate your requests to the Maillayer API. Each key is scoped to your account and can be revoked at any time.
Creating a key
- Go to API Keys in the dashboard.
- Click Create API Key.
- Give the key a name (e.g. "Production" or "Staging").
- Copy the key immediately — it is only shown once.
Revoking a key
To revoke a key, go to API Keys in the dashboard and click Revoke next to the key. Revoked keys immediately stop working and cannot be restored.
Best practices
- Use separate keys for production and development.
- Store keys in environment variables, never in source code.
- Rotate keys periodically.
- Revoke unused keys immediately.
Webhooks
Maillayer sends webhook events to notify your application about email delivery status changes. Configure a webhook URL in the dashboard to start receiving events.
Event types
| Event | Description |
|---|---|
email.delivered | Email was successfully delivered to the recipient's mail server. |
email.bounced | Email bounced (hard or soft). Hard bounces are added to the suppression list automatically. |
email.complained | Recipient marked the email as spam. The address is suppressed automatically. |
Webhook payload
{
"event": "email.delivered",
"emailId": "665f1a2b3c4d5e6f7a8b9c0d",
"to": "[email protected]",
"from": "[email protected]",
"subject": "Order Confirmed",
"timestamp": "2025-01-15T10:30:05.000Z"
}Bounce event payload
{
"event": "email.bounced",
"emailId": "665f1a2b3c4d5e6f7a8b9c0d",
"to": "[email protected]",
"bounceType": "Permanent",
"bounceSubType": "General",
"timestamp": "2025-01-15T10:30:05.000Z"
}Error Codes
The API returns standard HTTP status codes. Error responses include a JSON body with a message field describing the issue.
Error response format
{
"error": "Validation failed",
"message": "The 'to' field is required."
}Status codes
| Code | Meaning | Common causes |
|---|---|---|
202 | Accepted | Email queued for delivery. This is the success response. |
400 | Bad Request | Missing or invalid parameters. Check required fields (from, to, subject). |
401 | Unauthorized | Missing or invalid API key. Ensure the Authorization header is correct. |
403 | Forbidden | Domain not verified, or recipient is on the suppression list. |
429 | Too Many Requests | Rate limit exceeded. Slow down and retry after the Retry-After header value. |
500 | Internal Server Error | Something went wrong on our end. Retry the request or contact support. |
Rate Limits
API requests are rate-limited per account based on your plan. Limits are applied per calendar month.
| Plan | Emails / month | Domains | Rate limit |
|---|---|---|---|
| Free | 300 | 1 | 1 req/sec |
| Starter | 10,000 | 5 | 10 req/sec |
| Growth | 30,000 | Unlimited | 50 req/sec |
| Business | 50,000 | Unlimited | 100 req/sec |
Rate limit headers
Every response includes rate limit information in the headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per second. |
X-RateLimit-Remaining | Requests remaining in the current window. |
Retry-After | Seconds to wait before retrying (only on 429 responses). |