{"skill":{"slug":"mailgun-api","displayName":"Mailgun","summary":"Mailgun API integration with managed OAuth. Transactional email service for sending, receiving, and tracking emails. Use this skill when users want to send e...","description":"---\nname: mailgun\ndescription: |\n  Mailgun API integration with managed OAuth. Transactional email service for sending, receiving, and tracking emails.\n  Use this skill when users want to send emails, manage domains, routes, templates, mailing lists, or suppressions in Mailgun.\n  For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).\ncompatibility: Requires network access and valid Maton API key\nmetadata:\n  author: maton\n  version: \"1.0\"\n  clawdbot:\n    emoji: 🧠\n    homepage: \"https://maton.ai\"\n    requires:\n      env:\n        - MATON_API_KEY\n---\n\n# Mailgun\n\nAccess the Mailgun API with managed OAuth authentication. Send transactional emails, manage domains, routes, templates, mailing lists, suppressions, and webhooks.\n\n## Quick Start\n\n```bash\n# List domains\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/mailgun/v3/domains')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n## Base URL\n\n```\nhttps://api.maton.ai/mailgun/v3/{resource}\n```\n\nMaton proxies requests to `api.mailgun.net/v3` (US region) and automatically injects your OAuth token.\n\n**Regional Note:** Mailgun has US and EU regions. The gateway defaults to US region (api.mailgun.net).\n\n## Authentication\n\nAll requests require the Maton API key in the Authorization header:\n\n```\nAuthorization: Bearer $MATON_API_KEY\n```\n\n**Environment Variable:** Set your API key as `MATON_API_KEY`:\n\n```bash\nexport MATON_API_KEY=\"YOUR_API_KEY\"\n```\n\n### Getting Your API Key\n\n1. Sign in or create an account at [maton.ai](https://maton.ai)\n2. Go to [maton.ai/settings](https://maton.ai/settings)\n3. Copy your API key\n\n## Connection Management\n\nManage your Mailgun OAuth connections at `https://api.maton.ai`.\n\n### List Connections\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections?app=mailgun&status=ACTIVE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Create Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\ndata = json.dumps({'app': 'mailgun'}).encode()\nreq = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Content-Type', 'application/json')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Get Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n**Response:**\n```json\n{\n  \"connection\": {\n    \"connection_id\": \"{connection_id}\",\n    \"status\": \"ACTIVE\",\n    \"creation_time\": \"2026-02-12T02:24:16.551210Z\",\n    \"last_updated_time\": \"2026-02-12T02:25:03.542838Z\",\n    \"url\": \"https://connect.maton.ai/?session_token=...\",\n    \"app\": \"mailgun\",\n    \"metadata\": {}\n  }\n}\n```\n\nOpen the returned `url` in a browser to complete OAuth authorization.\n\n### Delete Connection\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Specifying Connection\n\nIf you have multiple Mailgun connections, specify which one to use with the `Maton-Connection` header:\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/mailgun/v3/domains')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nreq.add_header('Maton-Connection', '{connection_id}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\nIf you have multiple connections, always include this header to ensure requests go to the intended account.\n\n## Security & Permissions\n\n- Access is scoped to messages, domains, routes, events, and mailing lists within the connected Mailgun account.\n- **All write operations require explicit user approval.** Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.\n\n## API Reference\n\n**Important:** Mailgun API uses `application/x-www-form-urlencoded` for POST/PUT requests, not JSON.\n\n### Domains\n\n#### List Domains\n\n```bash\nGET /mailgun/v3/domains\n```\n\nReturns all domains for the account.\n\n#### Get Domain\n\n```bash\nGET /mailgun/v3/domains/{domain_name}\n```\n\n#### Create Domain\n\n```bash\nPOST /mailgun/v3/domains\nContent-Type: application/x-www-form-urlencoded\n\nname=example.com&smtp_password=supersecret\n```\n\n#### Delete Domain\n\n```bash\nDELETE /mailgun/v3/domains/{domain_name}\n```\n\n### Messages\n\n#### Send Message\n\n```bash\nPOST /mailgun/v3/{domain_name}/messages\nContent-Type: application/x-www-form-urlencoded\n\nfrom=sender@example.com&to=recipient@example.com&subject=Hello&text=Hello World\n```\n\nParameters:\n- `from` (required) - Sender email address\n- `to` (required) - Recipient(s), comma-separated\n- `cc` - CC recipients\n- `bcc` - BCC recipients\n- `subject` (required) - Email subject\n- `text` - Plain text body\n- `html` - HTML body\n- `template` - Name of stored template to use\n- `o:tag` - Tag for tracking\n- `o:tracking` - Enable/disable tracking (yes/no)\n- `o:tracking-clicks` - Enable click tracking\n- `o:tracking-opens` - Enable open tracking\n- `h:X-Custom-Header` - Custom headers (prefix with h:)\n- `v:custom-var` - Custom variables for templates (prefix with v:)\n\n#### Send MIME Message\n\n```bash\nPOST /mailgun/v3/{domain_name}/messages.mime\nContent-Type: multipart/form-data\n\nto=recipient@example.com&message=<MIME content>\n```\n\n### Events\n\n#### List Events\n\n```bash\nGET /mailgun/v3/{domain_name}/events\n```\n\nQuery parameters:\n- `begin` - Start time (RFC 2822 or Unix timestamp)\n- `end` - End time\n- `ascending` - Sort order (yes/no)\n- `limit` - Results per page (max 300)\n- `event` - Filter by event type (accepted, delivered, failed, opened, clicked, unsubscribed, complained, stored)\n- `from` - Filter by sender\n- `to` - Filter by recipient\n- `tags` - Filter by tags\n\n### Routes\n\nRoutes are defined globally per account, not per domain.\n\n#### List Routes\n\n```bash\nGET /mailgun/v3/routes\n```\n\nQuery parameters:\n- `skip` - Number of records to skip\n- `limit` - Number of records to return\n\n#### Create Route\n\n```bash\nPOST /mailgun/v3/routes\nContent-Type: application/x-www-form-urlencoded\n\npriority=0&description=My Route&expression=match_recipient(\".*@example.com\")&action=forward(\"https://example.com/webhook\")\n```\n\nParameters:\n- `priority` - Route priority (lower = higher priority)\n- `description` - Route description\n- `expression` - Filter expression (match_recipient, match_header, catch_all)\n- `action` - Action(s) to take (forward, store, stop)\n\n#### Get Route\n\n```bash\nGET /mailgun/v3/routes/{route_id}\n```\n\n#### Update Route\n\n```bash\nPUT /mailgun/v3/routes/{route_id}\nContent-Type: application/x-www-form-urlencoded\n\npriority=1&description=Updated Route\n```\n\n#### Delete Route\n\n```bash\nDELETE /mailgun/v3/routes/{route_id}\n```\n\n### Webhooks\n\n#### List Webhooks\n\n```bash\nGET /mailgun/v3/domains/{domain_name}/webhooks\n```\n\n#### Create Webhook\n\n```bash\nPOST /mailgun/v3/domains/{domain_name}/webhooks\nContent-Type: application/x-www-form-urlencoded\n\nid=delivered&url=https://example.com/webhook\n```\n\nWebhook types: `accepted`, `delivered`, `opened`, `clicked`, `unsubscribed`, `complained`, `permanent_fail`, `temporary_fail`\n\n#### Get Webhook\n\n```bash\nGET /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}\n```\n\n#### Update Webhook\n\n```bash\nPUT /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}\nContent-Type: application/x-www-form-urlencoded\n\nurl=https://example.com/new-webhook\n```\n\n#### Delete Webhook\n\n```bash\nDELETE /mailgun/v3/domains/{domain_name}/webhooks/{webhook_type}\n```\n\n### Templates\n\n#### List Templates\n\n```bash\nGET /mailgun/v3/{domain_name}/templates\n```\n\n#### Create Template\n\n```bash\nPOST /mailgun/v3/{domain_name}/templates\nContent-Type: application/x-www-form-urlencoded\n\nname=my-template&description=Welcome email&template=<html><body>Hello {{name}}</body></html>\n```\n\n#### Get Template\n\n```bash\nGET /mailgun/v3/{domain_name}/templates/{template_name}\n```\n\n#### Delete Template\n\n```bash\nDELETE /mailgun/v3/{domain_name}/templates/{template_name}\n```\n\n### Mailing Lists\n\n#### List Mailing Lists\n\n```bash\nGET /mailgun/v3/lists/pages\n```\n\n#### Create Mailing List\n\n```bash\nPOST /mailgun/v3/lists\nContent-Type: application/x-www-form-urlencoded\n\naddress=newsletter@example.com&name=Newsletter&description=Monthly newsletter&access_level=readonly\n```\n\nAccess levels: `readonly`, `members`, `everyone`\n\n#### Get Mailing List\n\n```bash\nGET /mailgun/v3/lists/{list_address}\n```\n\n#### Update Mailing List\n\n```bash\nPUT /mailgun/v3/lists/{list_address}\nContent-Type: application/x-www-form-urlencoded\n\nname=Updated Newsletter\n```\n\n#### Delete Mailing List\n\n```bash\nDELETE /mailgun/v3/lists/{list_address}\n```\n\n### Mailing List Members\n\n#### List Members\n\n```bash\nGET /mailgun/v3/lists/{list_address}/members/pages\n```\n\n#### Add Member\n\n```bash\nPOST /mailgun/v3/lists/{list_address}/members\nContent-Type: application/x-www-form-urlencoded\n\naddress=member@example.com&name=John Doe&subscribed=yes\n```\n\n#### Get Member\n\n```bash\nGET /mailgun/v3/lists/{list_address}/members/{member_address}\n```\n\n#### Update Member\n\n```bash\nPUT /mailgun/v3/lists/{list_address}/members/{member_address}\nContent-Type: application/x-www-form-urlencoded\n\nname=Jane Doe&subscribed=no\n```\n\n#### Delete Member\n\n```bash\nDELETE /mailgun/v3/lists/{list_address}/members/{member_address}\n```\n\n### Suppressions\n\n#### Bounces\n\n```bash\n# List bounces\nGET /mailgun/v3/{domain_name}/bounces\n\n# Add bounce\nPOST /mailgun/v3/{domain_name}/bounces\nContent-Type: application/x-www-form-urlencoded\n\naddress=bounced@example.com&code=550&error=Mailbox not found\n\n# Get bounce\nGET /mailgun/v3/{domain_name}/bounces/{address}\n\n# Delete bounce\nDELETE /mailgun/v3/{domain_name}/bounces/{address}\n```\n\n#### Unsubscribes\n\n```bash\n# List unsubscribes\nGET /mailgun/v3/{domain_name}/unsubscribes\n\n# Add unsubscribe\nPOST /mailgun/v3/{domain_name}/unsubscribes\nContent-Type: application/x-www-form-urlencoded\n\naddress=unsubscribed@example.com&tag=*\n\n# Delete unsubscribe\nDELETE /mailgun/v3/{domain_name}/unsubscribes/{address}\n```\n\n#### Complaints\n\n```bash\n# List complaints\nGET /mailgun/v3/{domain_name}/complaints\n\n# Add complaint\nPOST /mailgun/v3/{domain_name}/complaints\nContent-Type: application/x-www-form-urlencoded\n\naddress=complainer@example.com\n\n# Delete complaint\nDELETE /mailgun/v3/{domain_name}/complaints/{address}\n```\n\n#### Whitelists\n\n```bash\n# List whitelists\nGET /mailgun/v3/{domain_name}/whitelists\n\n# Add to whitelist\nPOST /mailgun/v3/{domain_name}/whitelists\nContent-Type: application/x-www-form-urlencoded\n\naddress=allowed@example.com\n\n# Delete from whitelist\nDELETE /mailgun/v3/{domain_name}/whitelists/{address}\n```\n\n### Statistics\n\n#### Get Stats\n\n```bash\nGET /mailgun/v3/{domain_name}/stats/total?event=delivered&event=opened\n```\n\nQuery parameters:\n- `event` (required) - Event type(s): accepted, delivered, failed, opened, clicked, unsubscribed, complained\n- `start` - Start date (RFC 2822 or Unix timestamp)\n- `end` - End date\n- `resolution` - Data resolution (hour, day, month)\n- `duration` - Period to show stats for\n\n### Tags\n\n#### List Tags\n\n```bash\nGET /mailgun/v3/{domain_name}/tags\n```\n\n#### Get Tag\n\n```bash\nGET /mailgun/v3/{domain_name}/tags/{tag_name}\n```\n\n#### Delete Tag\n\n```bash\nDELETE /mailgun/v3/{domain_name}/tags/{tag_name}\n```\n\n### IPs\n\n#### List IPs\n\n```bash\nGET /mailgun/v3/ips\n```\n\n#### Get IP\n\n```bash\nGET /mailgun/v3/ips/{ip_address}\n```\n\n### Domain Tracking\n\n#### Get Tracking Settings\n\n```bash\nGET /mailgun/v3/domains/{domain_name}/tracking\n```\n\n#### Update Open Tracking\n\n```bash\nPUT /mailgun/v3/domains/{domain_name}/tracking/open\nContent-Type: application/x-www-form-urlencoded\n\nactive=yes\n```\n\n#### Update Click Tracking\n\n```bash\nPUT /mailgun/v3/domains/{domain_name}/tracking/click\nContent-Type: application/x-www-form-urlencoded\n\nactive=yes\n```\n\n#### Update Unsubscribe Tracking\n\n```bash\nPUT /mailgun/v3/domains/{domain_name}/tracking/unsubscribe\nContent-Type: application/x-www-form-urlencoded\n\nactive=yes&html_footer=<a href=\"%unsubscribe_url%\">Unsubscribe</a>\n```\n\n### Credentials\n\n#### List Credentials\n\n```bash\nGET /mailgun/v3/domains/{domain_name}/credentials\n```\n\n#### Create Credential\n\n```bash\nPOST /mailgun/v3/domains/{domain_name}/credentials\nContent-Type: application/x-www-form-urlencoded\n\nlogin=alice&password=supersecret\n```\n\n#### Delete Credential\n\n```bash\nDELETE /mailgun/v3/domains/{domain_name}/credentials/{login}\n```\n\n## Pagination\n\nMailgun uses cursor-based pagination:\n\n```json\n{\n  \"items\": [...],\n  \"paging\": {\n    \"first\": \"https://api.mailgun.net/v3/.../pages?page=first&limit=100\",\n    \"last\": \"https://api.mailgun.net/v3/.../pages?page=last&limit=100\",\n    \"next\": \"https://api.mailgun.net/v3/.../pages?page=next&limit=100\",\n    \"previous\": \"https://api.mailgun.net/v3/.../pages?page=prev&limit=100\"\n  }\n}\n```\n\nUse `limit` parameter to control page size (default: 100).\n\n## Code Examples\n\n### JavaScript - Send Email\n\n```javascript\nconst formData = new URLSearchParams();\nformData.append('from', 'sender@example.com');\nformData.append('to', 'recipient@example.com');\nformData.append('subject', 'Hello');\nformData.append('text', 'Hello World!');\n\nconst response = await fetch(\n  'https://api.maton.ai/mailgun/v3/example.com/messages',\n  {\n    method: 'POST',\n    headers: {\n      'Authorization': `Bearer ${process.env.MATON_API_KEY}`,\n      'Content-Type': 'application/x-www-form-urlencoded'\n    },\n    body: formData.toString()\n  }\n);\nconst result = await response.json();\nconsole.log(result);\n```\n\n### Python - Send Email\n\n```python\nimport os\nimport requests\n\nresponse = requests.post(\n    'https://api.maton.ai/mailgun/v3/example.com/messages',\n    headers={'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'},\n    data={\n        'from': 'sender@example.com',\n        'to': 'recipient@example.com',\n        'subject': 'Hello',\n        'text': 'Hello World!'\n    }\n)\nprint(response.json())\n```\n\n### Python - List Domains\n\n```python\nimport os\nimport requests\n\nresponse = requests.get(\n    'https://api.maton.ai/mailgun/v3/domains',\n    headers={'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'}\n)\ndomains = response.json()\nfor domain in domains['items']:\n    print(f\"{domain['name']}: {domain['state']}\")\n```\n\n### Python - Create Route and Webhook\n\n```python\nimport os\nimport requests\n\nheaders = {'Authorization': f'Bearer {os.environ[\"MATON_API_KEY\"]}'}\ndomain = 'example.com'\n\n# Create route\nroute_response = requests.post(\n    'https://api.maton.ai/mailgun/v3/routes',\n    headers=headers,\n    data={\n        'priority': 0,\n        'description': 'Forward to webhook',\n        'expression': 'match_recipient(\"support@example.com\")',\n        'action': 'forward(\"https://myapp.com/incoming-email\")'\n    }\n)\nprint(f\"Route created: {route_response.json()}\")\n\n# Create webhook\nwebhook_response = requests.post(\n    f'https://api.maton.ai/mailgun/v3/domains/{domain}/webhooks',\n    headers=headers,\n    data={\n        'id': 'delivered',\n        'url': 'https://myapp.com/webhook/delivered'\n    }\n)\nprint(f\"Webhook created: {webhook_response.json()}\")\n```\n\n## Notes\n\n- Mailgun uses `application/x-www-form-urlencoded` for POST/PUT requests, not JSON\n- Domain names must be included in most endpoint paths\n- Routes are global (per account), not per domain\n- Sandbox domains require authorized recipients for sending\n- Dates are returned in RFC 2822 format\n- Event logs are stored for at least 3 days\n- Stats require at least one `event` parameter\n- Templates use Handlebars syntax by default\n- IMPORTANT: When using curl commands, use `curl -g` when URLs contain brackets to disable glob parsing\n- IMPORTANT: When piping curl output to `jq`, environment variables may not expand correctly. Use Python examples instead.\n\n## Rate Limits\n\n| Operation | Limit |\n|-----------|-------|\n| Sending | Varies by plan |\n| API calls | No hard limit, but excessive requests may be throttled |\n\nWhen rate limited, implement exponential backoff for retries.\n\n## Error Handling\n\n| Status | Meaning |\n|--------|---------|\n| 400 | Bad request or missing Mailgun connection |\n| 401 | Invalid or missing Maton API key |\n| 403 | Forbidden (e.g., sandbox domain restrictions) |\n| 404 | Resource not found |\n| 429 | Rate limited |\n| 4xx/5xx | Passthrough error from Mailgun API |\n\n### Troubleshooting: API Key Issues\n\n1. Check that the `MATON_API_KEY` environment variable is set:\n\n```bash\necho $MATON_API_KEY\n```\n\n2. Verify the API key is valid by listing connections:\n\n```bash\npython <<'EOF'\nimport urllib.request, os, json\nreq = urllib.request.Request('https://api.maton.ai/connections')\nreq.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')\nprint(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))\nEOF\n```\n\n### Troubleshooting: Invalid App Name\n\n1. Ensure your URL path starts with `mailgun`. For example:\n\n- Correct: `https://api.maton.ai/mailgun/v3/domains`\n- Incorrect: `https://api.maton.ai/v3/domains`\n\n### Troubleshooting: Sandbox Domain Restrictions\n\nSandbox domains can only send to authorized recipients. To send emails:\n1. Upgrade to a paid plan, or\n2. Add recipient addresses to authorized recipients in the Mailgun dashboard\n\n## Resources\n\n- [Mailgun API Documentation](https://documentation.mailgun.com/docs/mailgun/api-reference/api-overview)\n- [Mailgun API Reference](https://mailgun-docs.redoc.ly/docs/mailgun/api-reference/intro/)\n- [Mailgun Postman Collection](https://www.postman.com/mailgun/mailgun-s-public-workspace/documentation/ik8dl61/mailgun-api)\n- [Maton Community](https://discord.com/invite/dBfFAcefs2)\n- [Maton Support](mailto:support@maton.ai)\n","topics":["Api Integration","Email"],"tags":{"latest":"1.0.1"},"stats":{"comments":0,"downloads":1150,"installsAllTime":43,"installsCurrent":0,"stars":3,"versions":2},"createdAt":1770895627309,"updatedAt":1781739754641},"latestVersion":{"version":"1.0.1","createdAt":1777588713931,"changelog":"- Updated all Maton API endpoint URLs from gateway.maton.ai and ctrl.maton.ai to api.maton.ai.\n- Clarified that the base URL is now https://api.maton.ai/mailgun/v3/{resource}.\n- Updated all example requests and connection management instructions to reflect the new endpoint domain.\n- Deleted the LICENSE.txt file from the package.","license":"MIT-0"},"metadata":{"setup":[{"key":"MATON_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"byungkyu","userId":"s174c3s2kc1ehqj1ytzntezj2983e2aj","displayName":"byungkyu","image":"https://avatars.githubusercontent.com/u/16563684?v=4"},"moderation":null}