Guide
Sending API
Send from your server with POST /v1/send. A 202 response confirms that MailShogun accepted the message into its queue. Check its status in the panel afterwards.
You need a verified domain, an active plan, a payment method and a key with the send scope. Run the examples on your server; never expose the key in a browser.
Set up your account and domainReviewed on September 11, 2026
Illustrative workflow. Queue acceptance does not guarantee delivery or inbox placement.
POST /v1/send
Authorization: Bearer ms_…
{
"from": "hello@yourdomain.com",
"to": ["you@example.com"],
"subject": "Hello",
"text": "World"
}
Base and authentication
Every key starts with ms_…. You create it on the domain page, under Connection.
- Base
https://api.mailshogun.com- Header
Authorization: Bearer ms_…
The key needs the send scope and must allow your IP, country and sending domain. It also authenticates MCP, subject to its permissions.
The key is shown only once when you create it. If you lose it, revoke the key and create another.
POST /v1/send
JSON body. Content-Type application/json header.
POST https://api.mailshogun.com/v1/send
Fields
| Field | Type | Required | Description |
|---|---|---|---|
from |
string |
yes | Sender. Must belong to a verified domain on the account (and to the key’s domain, if the key is locked to one). |
to |
string[] |
yes | Recipients. At least one is required; there is a per-request maximum. |
subject |
string |
no | Message subject. |
html |
string |
no | HTML body. You may send html, text, or both. |
text |
string |
no | Plain-text body. |
Success: HTTP 202 with {"status":"queued"}. Sending is not instant: it goes into a queue first.
Examples
Set MAILSHOGUN_API_KEY in the server environment. Replace from and to with a verified sender and a mailbox you control. curl uses POSIX shell syntax; JavaScript uses Node.js with fetch in an .mjs file and PHP requires the cURL extension. Running these examples sends an email.
curl
curl -X POST https://api.mailshogun.com/v1/send \
-H "Authorization: Bearer $MAILSHOGUN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": ["you@example.com"],
"subject": "Hello",
"html": "<p>Hello from MailShogun</p>",
"text": "Hello from MailShogun"
}'
Node.js (fetch)
const apiKey = process.env.MAILSHOGUN_API_KEY;
if (!apiKey) throw new Error('Missing MAILSHOGUN_API_KEY');
const response = await fetch('https://api.mailshogun.com/v1/send', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: 'hello@yourdomain.com',
to: ['you@example.com'],
subject: 'Hello',
html: '<p>Hello from MailShogun</p>',
text: 'Hello from MailShogun'
})
});
const body = await response.json();
if (response.status !== 202) {
throw new Error('HTTP ' + response.status + ': ' + JSON.stringify(body));
}
console.log(body);
PHP
<?php
$apiKey = getenv('MAILSHOGUN_API_KEY');
if (!$apiKey) { throw new RuntimeException('Missing MAILSHOGUN_API_KEY'); }
$payload = [
'from' => 'hello@yourdomain.com',
'to' => ['you@example.com'],
'subject' => 'Hello',
'html' => '<p>Hello from MailShogun</p>',
'text' => 'Hello from MailShogun',
];
$ch = curl_init('https://api.mailshogun.com/v1/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$body = curl_exec($ch);
if ($body === false) { throw new RuntimeException(curl_error($ch)); }
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 202 + {"status":"queued"} on success
if ($code !== 202) { throw new RuntimeException('HTTP ' . $code . ': ' . $body); }
echo $body;
Responses and errors
Error bodies are JSON {"error":"…"}. The messages come from MailShogun when it sends.
| HTTP | Case | Detail |
|---|---|---|
202 |
Accepted | {"status":"queued"}. The message is in the queue. |
401 |
Missing or invalid key | missing key, invalid key. Check the ms_ prefix and that the key is still active. |
403 |
Key restricted | Missing send scope, disallowed IP or country, or sender outside the key’s domain. Fix the permission or use an appropriate key. |
400 |
Bad request or domain | from and to are required; invalid JSON; invalid sender; sender domain is not registered (verified) on this account. |
402 |
Billing | Check your plan, payment method and any overdue payments in Billing. |
429 |
Limits | Daily cap, too many sends in a short time, or other account limits (for example bounces). Wait or check Billing and reputation. |
500 |
Internal error | Keep the code and time. Contact support if it persists; avoid retrying without checking the status. |
503 |
Queue unavailable | Service temporarily unavailable. Keep the response and check the status before retrying. |
Daily and send-rate limits are account-wide. A 429 means you hit a cap.
MCP
The same API keys (Bearer ms_…). The tools are list_domains and send_email.
- Endpoint
POST https://mcp.mailshogun.com/mcp- Header
Authorization: Bearer ms_…- Tools
list_domains,send_email
Next step
With the domain verified, a tier and a card, create the key under Connection and send the POST.
Check the result
- HTTP 202 and status queued confirm acceptance. Check Statistics and the recipient mailbox to follow the outcome.
- Fix 400, 401, 402 and 403 errors before retrying. For 429, check the reported limit or restriction; waiting does not resolve every case.
- If the connection drops without a response, the message may already be queued. Check its status before retrying: this API does not document an idempotency key to prevent duplicates.
Continue with
Still stuck? Share the error code, time and affected domain with support. Remove passwords, API keys and message contents. Support