API Reference
Mailzeno exposes a versioned REST API for sending transactional emails through your own SMTP server.
The base URL for all API requests is:
https://api.mailzeno.devAuthentication
All API requests require a valid API key passed in the Authorization header using the Bearer scheme:
Authorization: Bearer mz_api_your_api_keyAPI keys are validated by hashing (SHA-256) and comparing against stored key hashes. Inactive or invalid keys return a 401 status.
Send Email
v1/emailsSends a transactional email through your configured SMTP server.
Request headers
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer token with your API key |
Content-Type | string | Yes | Must be application/json |
Idempotency-Key | string | No | Unique key to prevent duplicate sends |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
smtpId | string | Yes | SMTP configuration ID |
from | string | Yes | Sender email (must match SMTP account username) |
to | string | string[] | Yes | Recipient email address(es) |
subject | string | Conditional | Email subject (required if not using templates) |
html | string | Conditional | HTML email body (required if not using templates) |
text | string | No | Plain text fallback |
templateId | string | No | Template UUID |
templateKey | string | No | Template lookup key |
variables | object | No | Dynamic variables for template or raw content interpolation |
Provide either html + subject, or a templateId / templateKey.
Example request
curl -X POST https://api.mailzeno.dev/v1/emails \
-H "Authorization: Bearer mz_api_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"smtpId": "your_smtp_id",
"from": "you@example.com",
"to": "recipient@example.com",
"subject": "Hello from Mailzeno",
"html": "<h1>Hello World</h1>"
}'{
"smtpId": "your_smtp_id",
"from": "you@example.com",
"to": "recipient@example.com",
"subject": "Hello",
"html": "<h1>Hello</h1>"
}Success response
{
"success": true,
"messageId": "<unique-message-id@smtp.example.com>"
}Error response
{
"error": "Missing required fields: smtpId, from, to",
"code": "missing_required_fields"
}401 Unauthorized
{
"error": "Invalid or inactive API key",
"code": "invalid_api_key"
}Response headers
Every API response includes these headers:
| Header | Description |
|---|---|
x-request-id | Unique request identifier for debugging |
x-ratelimit-limit | Maximum requests allowed per window |
x-ratelimit-remaining | Remaining requests in the current window |
x-ratelimit-reset | Unix timestamp when the rate limit resets |
retry-after | Seconds to wait before retrying (only on 429) |
Request lifecycle
The API processes each request through this pipeline:
- Authentication — Validate the Bearer token against stored API key hashes
- Plan resolution — Determine the user's plan (
freeorpro) - Rate limiting — Check per-minute and daily rate limits via Redis
- Input validation — Verify required fields are present
- SMTP ownership check — Verify the SMTP config belongs to the authenticated user
- From address validation — Ensure
frommatches the SMTP account username - Template resolution — If using templates, fetch and render with variables
- Usage check — Verify daily send limit not exceeded
- SMTP decryption — Decrypt the stored SMTP password (AES-256-GCM)
- Send via core engine — Send through
@mailzeno/corewith pooling and retry - Logging — Log the email with retention policy
- Usage increment — Update the user's daily send count
API endpoints are rate limited per API key. See the Rate Limits page for details.
Forms API
MailZeno Forms endpoints are documented separately because they include public submit routes, embeds, schema validation, and dashboard management APIs.