Mailman Engine API
Mailman is a high-performance transactional email gateway written in Go. It abstracts upstream delivery providers (Resend, Brevo, SendGrid, Amazon SES, and native SMTP) behind a unified, resilient HTTP REST interface.
Mailman eliminates cross-origin resource sharing (CORS) barriers, provides automated background queuing with exponential backoff retries, tracks link clicks and opens, and exposes function calling schemas for autonomous AI agents.
Quickstart
Send your first email using cURL in seconds.
Dispatch a request to POST https://mailman.cloudrails.in/api/v1/send with your credentials:
curl -X POST https://mailman.cloudrails.in/api/v1/send \
-H "Content-Type: application/json" \
-H "x-api-access-code: YOUR_ACCESS_CODE" \
-H "x-api-secret-key: YOUR_SECRET_KEY" \
-d '{
"to": "recipient@example.com",
"replyTo": "support@yourdomain.com",
"subject": "Hello from Mailman",
"html": "<p>This is a transactional message sent via Mailman Engine.</p>",
"trackOpens": true,
"trackClicks": true
}'
Authentication & Access Codes
Authenticate API dispatch requests via two required HTTP headers.
Every programmatic dispatch request must provide both credentials in the request headers:
| Header | Format | Description |
|---|---|---|
| x-api-access-code | name@mailman | The public routing identifier for your API key (e.g. vtx@mailman). |
| x-api-secret-key | sk_live_... | The confidential private secret generated when the API key is issued. Never commit this key to version control. |
CORS Resilience & Universal Connectivity
Engineered to connect with any framework, client, or serverless runtime.
Unlike traditional mail proxies that block browser-based or cross-domain fetch calls, Mailman provides complete preflight support:
- Preflight OPTIONS Support: All preflight requests return
204 No Contentwith cached permissions for 24 hours (Access-Control-Max-Age: 86400). - Dynamic Origin Reflection: Automatically reflects the caller's origin for web applications, SPAs, and mobile WebViews.
- Allowed Headers: Explicitly allows
Content-Type, Authorization, x-api-access-code, x-api-secret-key, Accept, Origin, X-Requested-With, Cache-Control. - Connectable Everywhere: Seamlessly integrate from browser client-side code, Next.js server actions, Cloudflare Workers, Supabase Edge Functions, Node.js, Python, or automation platforms (n8n, Make, Zapier).
Email Dispatch API
Request Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Required | Recipient email address. |
| subject | string | Required | Subject line of the email. |
| html | string | Optional | HTML body. Links are rewritten through the tracking gateway when trackClicks is enabled. |
| text | string | Optional | Plaintext fallback content. |
| recipientName | string | Optional | Display name for recipient. |
| replyTo | string | Optional | Custom Reply-To email address (e.g. support@yourdomain.com). If omitted, automatically inherits the server's configured default Reply-To. |
| queue | boolean | Optional | Dispatches asynchronously through the background worker queue with exponential backoff retries (defaults to true). |
| trackOpens | boolean | Optional | Injects a transparent 1x1 tracking pixel to record email opens. Default false. |
| trackClicks | boolean | Optional | Rewrites links for real-time click telemetry. Default false. |
| variables | object | Optional | Key-value dictionary of placeholders replaced inside subject and HTML (e.g. {{name}}). |
| attachments | array | Optional | Array of file attachments (PDFs, invoices, images). Each item accepts filename, contentType (e.g. application/pdf), and base64-encoded content. |
| fromEmail | string | Optional | Custom sender email address override (e.g. team@yourdomain.com). Defaults to the connected mail server's verified From address. |
| fromName | string | Optional | Custom sender display name (e.g. Acme Notifications). |
| templateId | string | Optional | Server-side stored template identifier (e.g. tpl_auth_code, tpl_letter). Automatically populates HTML and subject with template contents and merges provided variables. |
| idempotencyKey | string | Optional | Unique client key to prevent duplicate sends on network retries. Can also be passed via the Idempotency-Key HTTP header. |
| sandbox | boolean | Optional | Sandbox / Dry-run simulation mode. Renders variables and templates, checks authentication, logs the transaction, but skips the external network dispatch. Can also be enabled via x-mailman-sandbox: true header. |
| webhookUrl | string | Optional | HTTPS callback endpoint to receive asynchronous event notifications when the message is delivered, fails/bounces, is opened, or has links clicked. |
| mailServerId | string | Optional | Explicitly override the upstream mail server, or specify "round_robin" to orchestrate and balance across all active servers with remaining capacity. |
Response Schemas
{
"success": true,
"status": "sent",
"messageId": "msg_api_vtx_core_1790501913118477680",
"mailServer": "Primary Resend"
}
{
"success": true,
"status": "queued",
"queueId": "q_1790501907577260795_api_vtx_core",
"messageId": "msg_api_vtx_core_1790501907577227391",
"mailServer": "Primary Resend"
}
Error Codes
| Code | Meaning | Resolution |
|---|---|---|
| 401 Unauthorized | Missing or invalid headers. | Verify x-api-access-code and x-api-secret-key match an active API key. |
| 429 Too Many Requests | Daily limit quota reached. | Adjust the daily quota in the Manage API view or enable queue: true. |
| 502 Bad Gateway | Upstream provider rejected dispatch. | Check the provider API key or SMTP credentials configured on the assigned server in the Servers tab. |
Delivery Status & Message Polling
Poll the real-time status, opens, clicks, or error report of any dispatched email using its messageId or id.
curl -X GET "https://mailman.cloudrails.in/api/v1/messages/msg_api_live_1790501907577227391" \
-H "x-api-access-code: vtx@mailman" \
-H "x-api-secret-key: sk_live_..."
{
"success": true,
"messageId": "msg_api_live_1790501907577227391",
"status": "sent", // "sent" | "queued" | "failed" | "sandbox"
"recipient": "user@example.com",
"sender": "team@example.com",
"subject": "Your verification code",
"mailServer": "Primary Resend",
"provider": "resend",
"idempotencyKey": "req_849201",
"opens": 1,
"clicks": 0,
"error": "",
"timestamp": "2026-10-02T12:00:00Z"
}
Delivery, Bounce & Engagement Webhooks
When you specify webhookUrl in your dispatch payload, Mailman automatically posts JSON event payloads to your server as soon as the email status updates.
{
"event": "email.sent", // "email.sent" | "email.failed" | "email.sandbox" | "email.opened" | "email.clicked"
"messageId": "msg_api_live_1790501907577227391",
"recipient": "user@example.com",
"subject": "Your verification code",
"status": "sent",
"mailServer": "Primary Resend",
"timestamp": "2026-10-02T12:00:01Z",
"error": "" // Populated with bounce/rejection message if event is "email.failed"
}
Bulk / Batch Dispatch API
Dispatch up to 1,000 personalized emails in a single request with high-speed parallel worker execution.
curl -X POST https://mailman.cloudrails.in/api/v1/send/bulk \
-H "Content-Type: application/json" \
-H "x-api-access-code: vtx@mailman" \
-H "x-api-secret-key: sk_live_..." \
-d '{
"concurrency": 20,
"messages": [
{
"to": "alex@example.com",
"templateId": "tpl_auth_code",
"variables": { "code": "482019" }
},
{
"to": "sarah@example.com",
"templateId": "tpl_letter",
"variables": { "name": "Sarah", "company": "Acme Inc" }
}
]
}'
Background Queue & Retries
Asynchronous worker pool with exponential backoff.
When sending transactional or bulk notifications, Mailman automatically enqueues emails into an asynchronous worker pool (returning an instant 202 Accepted) so your API callers are never blocked by slow network sockets or remote mail server latency.
If an upstream service encounters a temporary timeout or rate limit, the worker retains the item in the pending state and automatically retries with exponential backoff (up to 3 attempts). Track queue activity in real-time in the Queue view within the console.
PDF & File Attachments API
Send invoices, reports, PDFs, and documents natively across all mail providers.
Mailman has full support for PDF attachments over the REST API. Attachments are passed in the attachments array encoded as standard Base64. Mailman automatically formats and transmits them using the correct MIME headers and provider specs (Resend, Brevo, SendGrid, Postmark, and native SMTP):
curl -X POST https://mailman.cloudrails.in/api/v1/send \
-H "Content-Type: application/json" \
-H "x-api-access-code: YOUR_ACCESS_CODE" \
-H "x-api-secret-key: YOUR_SECRET_KEY" \
-d '{
"to": "client@example.com",
"subject": "Your Monthly Invoice (PDF)",
"html": "<p>Please find your PDF invoice attached.</p>",
"replyTo": "billing@yourdomain.com",
"attachments": [
{
"filename": "invoice-2026.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjQKJcTl8uXrp/Og0MTGCjQgMCBvYmoK..."
}
]
}'
AI Agent Function Calling
Equip autonomous LLM agents (OpenAI, Anthropic Claude, Google Gemini) to dispatch emails safely.
OpenAI Function Tool Schema
Provide this definition in your agent's tools array:
{
"type": "function",
"function": {
"name": "send_transactional_email",
"description": "Dispatches a transactional email through Mailman Engine gateway.",
"parameters": {
"type": "object",
"properties": {
"to": {
"type": "string",
"description": "Recipient email address."
},
"subject": {
"type": "string",
"description": "Concise and professional subject line."
},
"html": {
"type": "string",
"description": "Semantic HTML formatted body. Do not output markdown."
},
"replyTo": {
"type": "string",
"description": "Optional custom Reply-To email address (e.g. support@company.com)."
},
"trackOpens": {
"type": "boolean",
"description": "Whether to inject open tracking pixel."
},
"trackClicks": {
"type": "boolean",
"description": "Whether to track link clicks."
},
"queue": {
"type": "boolean",
"description": "Whether to deliver asynchronously via background queue."
}
},
"required": ["to", "subject", "html"]
}
}
}
Anthropic Claude Tool Specification
{
"name": "send_transactional_email",
"description": "Sends transactional email via Mailman Engine gateway.",
"input_schema": {
"type": "object",
"properties": {
"to": { "type": "string", "description": "Destination email address." },
"subject": { "type": "string", "description": "Subject line." },
"html": { "type": "string", "description": "HTML content of the email." },
"replyTo": { "type": "string", "description": "Optional custom Reply-To email address." }
},
"required": ["to", "subject", "html"]
}
}
Recommended Agent System Prompt
You have access to the `send_transactional_email` tool connected to Mailman Engine.
1. RECIPIENT & SUBJECT: Always confirm the recipient address. Generate a clear subject without spam trigger words.
2. HTML BODY: Output clean semantic HTML (<p>, <h2>, <strong>, <ul>, <li>, <a href="...">). Never output raw markdown.
3. STATUS HANDLING: HTTP 200 means dispatched immediately. HTTP 202 means queued for delivery.
SDKs & Code Examples
Standard implementation patterns for major programming languages.
import axios from 'axios';
export async function sendEmailNotification(to: string, subject: string, html: string) {
const response = await axios.post(
'https://mailman.cloudrails.in/api/v1/send',
{
to,
subject,
html,
replyTo: 'support@yourdomain.com',
trackOpens: true,
trackClicks: true,
queue: true
},
{
headers: {
'Content-Type': 'application/json',
'x-api-access-code': process.env.MAILMAN_ACCESS_CODE!,
'x-api-secret-key': process.env.MAILMAN_SECRET_KEY!
}
}
);
return response.data;
}
import os
import requests
def dispatch_email(recipient: str, subject: str, html_body: str, reply_to: str = None):
url = "https://mailman.cloudrails.in/api/v1/send"
headers = {
"Content-Type": "application/json",
"x-api-access-code": os.environ["MAILMAN_ACCESS_CODE"],
"x-api-secret-key": os.environ["MAILMAN_SECRET_KEY"]
}
payload = {
"to": recipient,
"subject": subject,
"html": html_body,
"replyTo": reply_to or "support@yourdomain.com",
"trackOpens": True,
"trackClicks": True
}
res = requests.post(url, json=payload, headers=headers, timeout=15)
res.raise_for_status()
return res.json()
package mailman
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
type DispatchPayload struct {
To string `json:"to"`
Subject string `json:"subject"`
HTML string `json:"html"`
TrackOpens bool `json:"trackOpens"`
TrackClicks bool `json:"trackClicks"`
}
func SendEmail(to, subject, html string) error {
payload := DispatchPayload{
To: to,
Subject: subject,
HTML: html,
TrackOpens: true,
TrackClicks: true,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://mailman.cloudrails.in/api/v1/send", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-api-access-code", os.Getenv("MAILMAN_ACCESS_CODE"))
req.Header.Set("x-api-secret-key", os.Getenv("MAILMAN_SECRET_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
return fmt.Errorf("dispatch returned status %d", resp.StatusCode)
}
return nil
}