Mailgun Email API
Agent Instructions
- Always ask the user for their region (US or EU) if not already known. Region determines the base URL and cannot be changed after domain creation.
- Before generating code, check for existing files or environment variables for and .
- When the user mentions events, logs, stats, or tags — use the current APIs (), never the deprecated v3 endpoints.
- For domain CRUD operations, use (not v3).
- For detailed API parameters, fetch the linked doc pages rather than guessing.
Overview
Mailgun (by Sinch) provides REST API and SMTP relay for transactional and bulk email — sending, receiving, tracking, and suppression management.
Getting Started
Authentication
See sinch-authentication for full auth setup.
All requests use HTTP Basic Auth — username:
, password: your Mailgun private API key. Find it at Mailgun Dashboard > Account Settings > API Keys.
Two key types:
- Primary Account API Key — full access to all endpoints and domains
- Domain Sending Keys — restricted to and for one domain
Base URLs
Always match the base URL to the domain's region. Data never crosses regions.
| Service | US | EU |
|---|
| REST API | | |
| Outgoing SMTP | | |
| Inbound SMTP | , | , |
| Open/Click Tracking | | |
Send an Email
bash
curl -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/YOUR_DOMAIN/messages \
-F from='Sender <sender@YOUR_DOMAIN>' \
-F to='recipient@example.com' \
-F subject='Hello from Mailgun' \
-F text='This is a test email.' \
-F html='<h1>Hello</h1><p>HTML body.</p>'
Response:
{"id": "<message-id@YOUR_DOMAIN>", "message": "Queued. Thank you."}
The Messages API uses
— use
flags, not
with JSON.
Node.js SDK
bash
npm install mailgun.js form-data
javascript
const Mailgun = require('mailgun.js');
const formData = require('form-data');
const mg = new Mailgun(formData).client({
username: 'api',
key: 'YOUR_API_KEY',
// For EU: url: 'https://api.eu.mailgun.net'
});
mg.messages.create('YOUR_DOMAIN', {
from: 'Sender <sender@YOUR_DOMAIN>',
to: ['recipient@example.com'],
subject: 'Hello',
text: 'Testing Mailgun!',
});
For other SDKs:
SDK Reference
Key Concepts
Domains
- Sandbox domain — provided on signup (e.g., ). Only pre-authorized recipients can receive mail.
- Custom domain — requires DNS verification (SPF, DKIM, MX). Domain CRUD uses (not v3). Only remains on v3. See Domains API
Sending
- REST API —
POST /v3/{domain}/messages
with , , , , , , , , attachments, headers, tags, variables
- SMTP — port 587 TLS, credentials per-domain via
/v3/domains/{domain}/credentials
. See Credentials API
- MIME —
POST /v3/{domain}/messages.mime
- Batch — up to 1,000 recipients per call using for personalization
- Test mode — add to simulate without delivery
- Scheduling — (RFC-2822),
o:deliverytime-optimize-period
(STO), (TZO)
- Tracking — , , per message; or configure at domain level via
/v3/domains/{name}/tracking
. See Domain Tracking API
Send options (
,
,
,
params) are limited to 16KB total per request.
For full parameters:
Messages API
Templates
Two levels:
- Domain — . See Domain Templates API
- Account — (shared across all domains). See Account Templates API
Reference by name when sending:
-F template='welcome-template' -F t:variables='{"name":"John"}'
. Each template supports up to 40 versions.
Webhooks
Real-time HTTP POST notifications for email events.
- Domain —
/v3/domains/{domain}/webhooks
(v3) or /v4/domains/{domain}/webhooks
(v4). See Domain Webhooks API
- Account — (fires across all domains). See Account Webhooks API
Event types:
,
,
,
,
,
,
,
Events and Analytics
- Logs — for querying event data. The legacy is deprecated. See Logs API
- Metrics —
POST /v1/analytics/metrics
for aggregated analytics with dimensions, filters, resolutions. Replaces deprecated . See Metrics API
- Tags — when sending; manage via . Legacy is deprecated. See Tags API
Data retention: Logs — at least 3 days (legacy). Metrics — hourly 60 days, daily 1 year, monthly indefinite.
Inbound Routing
Routes API — match incoming messages by recipient pattern or header expression, then forward, store, or webhook. Configure both
and
MX records.
Suppressions and Allowlists
Per-domain suppression lists that Mailgun auto-populates. Sending to suppressed addresses silently drops.
- Bounces —
- Unsubscribes —
/v3/{domain}/unsubscribes
- Complaints —
- Allowlist — — prevents addresses from being added to bounce lists
Mailing Lists
Mailing Lists API —
to create/manage lists,
/v3/lists/{address}/members
for members. Bulk upload via
or
endpoints.
Stored Messages
Retrieve:
GET /v3/domains/{domain}/messages/{storage_key}
. Resend:
to same path. See
Messages API
Infrastructure Management
For IPs, IP Pools, IP Warmup, DKIM Keys, and Subaccounts — see references/infrastructure.md.
Common Patterns
Batch send with personalization
Add
as JSON mapping each recipient address to their variables. Use
%recipient.variable_name%
in subject/body. Max 1,000 recipients per call. See
Batch Sending
Set up domain webhooks
- Create webhook via
POST /v3/domains/{domain}/webhooks
with (event type) and fields
- Verify HMAC signature on incoming webhooks using your webhook signing key (SHA256). See Securing Webhooks
- Return 2xx or Mailgun retries with exponential backoff for ~8 hours
Schedule and cancel delivery
- Schedule: add
-F o:deliverytime='RFC-2822-date'
to send call
- Cancel:
DELETE /v3/{domain}/envelopes
to bulk-delete all scheduled/undelivered mail
Configure inbound email
- Add MX records pointing to and (priority 10)
- Create route via with (match pattern) and (forward/store/webhook). See Routes Guide
Gotchas
- Sandbox domains — only pre-authorized recipients. Add them in the dashboard first.
- Region mismatch — always use the base URL matching the domain's region. US domains 404 on EU endpoints and vice versa.
- only — the Messages endpoint does not accept JSON. Use in curl.
- Date format — RFC-2822 with numerical timezone offsets (+0500), not abbreviated names (EST, CET).
- Domains API is v4 — use for CRUD. Only
DELETE /v3/domains/{name}
remains on v3.
- Events/Stats deprecated — use (not ) and
POST /v1/analytics/metrics
(not ).
- Tags deprecated — use (not ).
- Suppression auto-populate — Mailgun silently drops messages to bounced/unsubscribed/complained addresses.
- Rate limits — response. Check , , headers. Use exponential backoff.
- Send options 16KB cap — , , , params combined max 16KB per request.
- Webhook caching — changes take up to 10 minutes. URLs are deduplicated across account and domain levels.
- IP warmup — new dedicated IPs need gradual volume ramp. Use to manage programmatically.
- Two MX records — configure both and for inbound routing.
- API key security — never expose the primary key client-side. Use Domain Sending Keys for restricted access.
Links
References
- references/infrastructure.md — IPs, IP Pools, Dynamic Pools, IP Warmup, DKIM Keys, Subaccounts