Access the Mailgun API with managed OAuth authentication. Send transactional emails, manage domains, routes, templates, mailing lists, suppressions, and webhooks.
# List domains
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/mailgun/v3/domains')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/mailgun/v3/{resource}
Maton proxies requests to api.mailgun.net/v3 (US region) and automatically injects your OAuth token.
Regional Note: Mailgun has US and EU regions. The gateway defaults to US region (api.mailgun.net).
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Mailgun OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=mailgun&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'mailgun'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-12T02:24:16.551210Z",
"last_updated_time": "2026-02-12T02:25:03.542838Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "mailgun",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Mailgun connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/mailgun/v3/domains')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Important: Mailgun API uses application/x-www-form-urlencoded for POST/PUT requests, not JSON.
GET /mailgun/v3/domains
Returns all domains for the account.
GET /mailgun/v3/domains/{domain_name}
POST /mailgun/v3/domains
Content-Type: application/x-www-form-urlencoded
name=example.com&smtp_password=supersecret
DELETE /mailgun/v3/domains/{domain_name}
POST /mailgun/v3/{domain_name}/messages
Content-Type: application/x-www-form-urlencoded
from=sender@example.com&to=recipient@example.com&subject=Hello&text=Hello World
Parameters:
from (required) - Sender email addressto (required) - Recipient(s), comma-separatedcc - CC recipientsbcc - BCC recipientssubject (required) - Email subjecttext - Plain text bodyhtml - HTML bodytemplate - Name of stored template to useo:tag - Tag for trackingo:tracking - Enable/disable tracking (yes/no)o:tracking-clicks - Enable click trackingo:tracking-opens - Enable open trackingh:X-Custom-Header - Custom headers (prefix with h:)v:custom-var - Custom variables for templates (prefix with v:)POST /mailgun/v3/{domain_name}/messages.mime
Content-Type: multipart/form-data
to=recipient@example.com&message=<MIME content>
GET /mailgun/v3/{domain_name}/events
Query parameters:
begin - Start time (RFC 2822 or Unix timestamp)end - End timeascending - Sort order (yes/no)limit - Results per page (max 300)event - Filter by event type (accepted, delivered, failed, opened, clicked, unsubscribed, complained, stored)from - Filter by senderto - Filter by recipienttags - Filter by tagsRoutes are defined globally per account, not per domain.
GET /mailgun/v3/routes
Query parameters:
skip - Number of records to skiplimit - Number of records to returnPOST /mailgun/v3/routes
Content-Type: application/x-www-form-urlencoded
priority=0&description=My Route&expression=match_recipient(".*@example.com")&action=forward("https://example.com/webhook")
Parameters:
priority - Route priority (lower = higher priority)description - Route descriptionexpression - Filter expression (match_recipient, match_header, catch_all)action - Action(s) to take (forward, store, stop)GET /mailgun/v3/routes/{route_id}
PUT /mailgun/v3/routes/{route_id}
Content-Type: application/x-www-form-urlencoded
priority=1&description=Updated Route
DELETE /mailgun/v3/routes/{route_id}
GET /mailgun/v3/domains/{domain_name}/webhooks
POST /mailgun/v3/domains/{domain_name}/webhooks
Content-Type: application/x-www-form-urlencoded
id=delivered&url=https://example.com/webhook
Webhook types: accepted, delivered, opened, clicked, unsubscribed, complained, permanent_fail, temporary_fail
GET /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
PUT /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
Content-Type: application/x-www-form-urlencoded
url=https://example.com/new-webhook
DELETE /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}
GET /mailgun/v3/{domain_name}/templates
POST /mailgun/v3/{domain_name}/templates
Content-Type: application/x-www-form-urlencoded
name=my-template&description=Welcome email&template=<html><body>Hello {{name}}</body></html>
GET /mailgun/v3/{domain_name}/templates/{template_name}
DELETE /mailgun/v3/{domain_name}/templates/{template_name}
GET /mailgun/v3/lists/pages
POST /mailgun/v3/lists
Content-Type: application/x-www-form-urlencoded
address=newsletter@example.com&name=Newsletter&description=Monthly newsletter&access_level=readonly
Access levels: readonly, members, everyone
GET /mailgun/v3/lists/{list_address}
PUT /mailgun/v3/lists/{list_address}
Content-Type: application/x-www-form-urlencoded
name=Updated Newsletter
DELETE /mailgun/v3/lists/{list_address}
GET /mailgun/v3/lists/{list_address}/members/pages
POST /mailgun/v3/lists/{list_address}/members
Content-Type: application/x-www-form-urlencoded
address=member@example.com&name=John Doe&subscribed=yes
GET /mailgun/v3/lists/{list_address}/members/{member_address}
PUT /mailgun/v3/lists/{list_address}/members/{member_address}
Content-Type: application/x-www-form-urlencoded
name=Jane Doe&subscribed=no
DELETE /mailgun/v3/lists/{list_address}/members/{member_address}
# List bounces
GET /mailgun/v3/{domain_name}/bounces
# Add bounce
POST /mailgun/v3/{domain_name}/bounces
Content-Type: application/x-www-form-urlencoded
address=bounced@example.com&code=550&error=Mailbox not found
# Get bounce
GET /mailgun/v3/{domain_name}/bounces/{address}
# Delete bounce
DELETE /mailgun/v3/{domain_name}/bounces/{address}
# List unsubscribes
GET /mailgun/v3/{domain_name}/unsubscribes
# Add unsubscribe
POST /mailgun/v3/{domain_name}/unsubscribes
Content-Type: application/x-www-form-urlencoded
address=unsubscribed@example.com&tag=*
# Delete unsubscribe
DELETE /mailgun/v3/{domain_name}/unsubscribes/{address}
# List complaints
GET /mailgun/v3/{domain_name}/complaints
# Add complaint
POST /mailgun/v3/{domain_name}/complaints
Content-Type: application/x-www-form-urlencoded
address=complainer@example.com
# Delete complaint
DELETE /mailgun/v3/{domain_name}/complaints/{address}
# List whitelists
GET /mailgun/v3/{domain_name}/whitelists
# Add to whitelist
POST /mailgun/v3/{domain_name}/whitelists
Content-Type: application/x-www-form-urlencoded
address=allowed@example.com
# Delete from whitelist
DELETE /mailgun/v3/{domain_name}/whitelists/{address}
GET /mailgun/v3/{domain_name}/stats/total?event=delivered&event=opened
Query parameters:
event (required) - Event type(s): accepted, delivered, failed, opened, clicked, unsubscribed, complainedstart - Start date (RFC 2822 or Unix timestamp)end - End dateresolution - Data resolution (hour, day, month)duration - Period to show stats forGET /mailgun/v3/{domain_name}/tags
GET /mailgun/v3/{domain_name}/tags/{tag_name}
DELETE /mailgun/v3/{domain_name}/tags/{tag_name}
GET /mailgun/v3/ips
GET /mailgun/v3/ips/{ip_address}
GET /mailgun/v3/domains/{domain_name}/tracking
PUT /mailgun/v3/domains/{domain_name}/tracking/open
Content-Type: application/x-www-form-urlencoded
active=yes
PUT /mailgun/v3/domains/{domain_name}/tracking/click
Content-Type: application/x-www-form-urlencoded
active=yes
PUT /mailgun/v3/domains/{domain_name}/tracking/unsubscribe
Content-Type: application/x-www-form-urlencoded
active=yes&html_footer=<a href="%unsubscribe_url%">Unsubscribe</a>
GET /mailgun/v3/domains/{domain_name}/credentials
POST /mailgun/v3/domains/{domain_name}/credentials
Content-Type: application/x-www-form-urlencoded
login=alice&password=supersecret
DELETE /mailgun/v3/domains/{domain_name}/credentials/{login}
Mailgun uses cursor-based pagination:
{
"items": [...],
"paging": {
"first": "https://api.mailgun.net/v3/.../pages?page=first&limit=100",
"last": "https://api.mailgun.net/v3/.../pages?page=last&limit=100",
"next": "https://api.mailgun.net/v3/.../pages?page=next&limit=100",
"previous": "https://api.mailgun.net/v3/.../pages?page=prev&limit=100"
}
}
Use limit parameter to control page size (default: 100).
const formData = new URLSearchParams();
formData.append('from', 'sender@example.com');
formData.append('to', 'recipient@example.com');
formData.append('subject', 'Hello');
formData.append('text', 'Hello World!');
const response = await fetch(
'https://api.maton.ai/mailgun/v3/example.com/messages',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
}
);
const result = await response.json();
console.log(result);
import os
import requests
response = requests.post(
'https://api.maton.ai/mailgun/v3/example.com/messages',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
data={
'from': 'sender@example.com',
'to': 'recipient@example.com',
'subject': 'Hello',
'text': 'Hello World!'
}
)
print(response.json())
import os
import requests
response = requests.get(
'https://api.maton.ai/mailgun/v3/domains',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
domains = response.json()
for domain in domains['items']:
print(f"{domain['name']}: {domain['state']}")
import os
import requests
headers = {'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
domain = 'example.com'
# Create route
route_response = requests.post(
'https://api.maton.ai/mailgun/v3/routes',
headers=headers,
data={
'priority': 0,
'description': 'Forward to webhook',
'expression': 'match_recipient("support@example.com")',
'action': 'forward("https://myapp.com/incoming-email")'
}
)
print(f"Route created: {route_response.json()}")
# Create webhook
webhook_response = requests.post(
f'https://api.maton.ai/mailgun/v3/domains/{domain}/webhooks',
headers=headers,
data={
'id': 'delivered',
'url': 'https://myapp.com/webhook/delivered'
}
)
print(f"Webhook created: {webhook_response.json()}")
application/x-www-form-urlencoded for POST/PUT requests, not JSONevent parametercurl -g when URLs contain brackets to disable glob parsingjq, environment variables may not expand correctly. Use Python examples instead.| Operation | Limit |
|---|---|
| ----------- | ------- |
| Sending | Varies by plan |
| API calls | No hard limit, but excessive requests may be throttled |
When rate limited, implement exponential backoff for retries.
| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Bad request or missing Mailgun connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden (e.g., sandbox domain restrictions) |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Mailgun API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
mailgun. For example:https://api.maton.ai/mailgun/v3/domainshttps://api.maton.ai/v3/domainsSandbox domains can only send to authorized recipients. To send emails:
共 2 个版本