Create a verified domain, generate an API key, and send only after Milesender marks the domain production ready. Every project starts in sandbox, so you can build the whole integration before DNS is even in the picture.
ms_test_ key to confirm the integration works end to end.ms_live_) or SMTP credential and you're sending production email.One endpoint handles every send. Authenticate with a bearer token — use a sandbox key while you build, swap in a live key once your domain is verified.
curl https://api.milesender.com/v1/emails \
-H "Authorization: Bearer ms_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"from": "Milesender <hello@example.com>",
"to": ["user@gmail.com"],
"subject": "Welcome to Milesender",
"html": "<h1>Hello</h1>",
"text": "Hello"
}'Any language or platform with an SMTP client works without a Milesender library — point it at these settings using a generated SMTP credential.
Host
smtp.milesender.com
Port
587 (STARTTLS) or 465 (TLS)
Username
ms_smtp_xxxxx
Password
generated with the credential
Add a domain from Dashboard → Domainsand Milesender generates four DNS records scoped to that domain. Verification is automatic — Milesender polls your DNS provider and flips each record's status as it resolves, no manual "check now" step required in production.
All three exist to answer the same question for a receiving inbox: was this email actually sent by who it claims to be from? Milesender requires all three before unlocking production sending, because passing only one or two is exactly the gap spammers exploit.
Subscribe an endpoint from Dashboard → Webhooks and Milesender POSTs a signed JSON payload for every event you select.
{
"type": "email.delivered",
"created_at": "2026-07-15T14:02:08Z",
"data": {
"id": "email_01JZ9G2Q",
"to": "user@gmail.com",
"from": "hello@example.com",
"subject": "Welcome to Milesender"
}
}Every error response includes a stable `code` you can match on in code, not just an HTTP status.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A required field is missing or malformed. The response body names the field. |
| 401 | invalid_api_key | The key is missing, revoked, or doesn't match the environment (test vs. live). |
| 403 | domain_not_verified | You're sending from a domain that hasn't passed SPF/DKIM/DMARC verification yet. |
| 422 | invalid_recipient | The `to` address failed basic syntax validation before Milesender queued the send. |
| 429 | rate_limited | You've exceeded your plan's requests-per-second limit. Retry after the `Retry-After` header. |
| 500 | internal_error | Something failed on Milesender's side. Safe to retry with backoff. |
Limits are per credential, not per workspace, so a busy sandbox key never affects your production sending.
| Credential | Requests | Volume |
|---|---|---|
| Sandbox key (ms_test_) | 10 requests / second | 100 emails / day |
| Live key (ms_live_) | 50 requests / second | Plan-based, see billing |
| SMTP (ms_smtp_) | 20 connections / second | Plan-based, see billing |
import { Milesender } from "@milesender/node";
const milesender = new Milesender(process.env.MILESENDER_API_KEY);
await milesender.emails.send({
from: "Milesender <hello@example.com>",
to: "user@gmail.com",
subject: "Welcome",
html: "<p>Your account is ready.</p>",
});Call the API from a route handler so your API key never reaches the client.
import { Milesender } from "@milesender/node";
const milesender = new Milesender(process.env.MILESENDER_API_KEY);
export async function POST(request: Request) {
const { email } = await request.json();
await milesender.emails.send({
from: "Milesender <hello@example.com>",
to: email,
subject: "Welcome",
html: "<p>Your account is ready.</p>",
});
return Response.json({ ok: true });
}Drop an SMTP credential into your mail config — Laravel's mailer needs no Milesender-specific package.
MAIL_MAILER=smtp
MAIL_HOST=smtp.milesender.com
MAIL_PORT=587
MAIL_USERNAME=ms_smtp_xxxxx
MAIL_PASSWORD=your_smtp_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="hello@example.com"from milesender import Milesender
milesender = Milesender("ms_live_xxxxx")
milesender.emails.send(
from_="Milesender <hello@example.com>",
to="user@gmail.com",
subject="Welcome",
html="<p>Your account is ready.</p>",
)client := milesender.NewClient("ms_live_xxxxx")
_, err := client.Emails.Send(ctx, &milesender.SendRequest{
From: "Milesender <hello@example.com>",
To: "user@gmail.com",
Subject: "Welcome",
Html: "<p>Your account is ready.</p>",
})