API Documentation
Send transactional emails with a simple REST API. Get started in minutes.
Quickstart
- Create an account at devsmtp.com/login
- Add your domain — the onboarding modal walks you through the four DNS records to publish (1 DKIM TXT, 1 MAIL FROM MX, 1 SPF TXT, plus optional DMARC)
- Generate an API key from Dashboard → API Keys (the onboarding modal also offers to create one for you, scoped to the domain you just added)
- Send your first email using the API — see code examples below
Authentication
All API requests require authentication using a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEY
Keep your API key secret. Never expose it in client-side code or public repositories.
Domain Setup
Add your domain and configure DNS records to start sending emails.
- Go to Domains in the dashboard
- Click Add Domain
- Enter your domain name (e.g.,
mail.yourdomain.com) - We'll register your domain with AWS SES and generate DNS records
We recommend sending transactional emails from a subdomain like mail.yourdomain.com or send.yourdomain.com instead of your root domain.
Why use a subdomain?
- •Reputation isolation: If issues occur, your main domain's reputation stays protected
- •Easier recovery: A subdomain can be replaced if it gets blacklisted
- •Separation of concerns: Keep transactional emails separate from marketing
Example: Instead of hello@yourdomain.com, send from hello@mail.yourdomain.com
New domains use four records (three required, DMARC optional):
- DKIM — one TXT record at
devsmtp._domainkey.<your-domain>containing the public key. We generate the keypair, store the private half in Supabase Vault, and pass it to SES — you publish the public half. - MAIL FROM — one MX record at
send.<your-domain>pointing tofeedback-smtp.eu-west-2.amazonses.com(priority 10). - SPF — one TXT record at
send.<your-domain>withv=spf1 include:amazonses.com -all. This sits on the MAIL FROM subdomain, not your sending domain — that's what removes the “via amazonses.com” label from Gmail. - DMARC (optional) — one TXT record at
_dmarc.<your-domain>. Start withv=DMARC1; p=none;for monitoring.
Cloudflare
- Go to your domain → DNS
- Click Add record
- Choose the record Type (TXT, MX) shown in DevSMTP
- Copy Name and Content from DevSMTP
- Important: Cloudflare proxying doesn't apply to TXT/MX, so no orange cloud to worry about
GoDaddy
- Go to My Products → Your domain → DNS
- Scroll to Records and click Add
- Choose the record Type (TXT, MX) shown in DevSMTP
- Enter Host and value from DevSMTP (for MX, also set Priority to 10)
Fasthosts
- Log into your control panel
- Select your domain → DNS Settings
- Click Add Record and pick the type (TXT or MX) shown in DevSMTP
- Copy Name and Value from DevSMTP
- Repeat for each record in the table
DNS changes can take up to 48 hours to propagate, but usually complete within 1-2 hours. Click the refresh button on your domain to check verification status.
Legacy domains: Domains added before BYODKIM shipped show three CNAME records pointing to *.dkim.amazonses.com instead of one TXT — both flows work, but new domains default to the simpler single-TXT setup.
The DNS records above aren't arbitrary — they each prove something specific to receiving mailbox providers. Here's what each one does:
DKIM — proves the message wasn't tampered with
SES signs every outbound message with the private key we hold for your domain. Receiving servers fetch your public key from the DKIM TXT record (devsmtp._domainkey.<your-domain>) and verify the signature. A passing DKIM signature with d=<your-domain> tells Gmail/Yahoo “this really came from you” and the reputation accrues to your domain — not to amazonses.com.
SPF + MAIL FROM — proves SES is allowed to send
When you add a domain, DevSMTP automatically routes bounce handling through send.<your-domain> (a subdomain of yours). The SPF record there says “Amazon SES is an authorized sender for this subdomain”:
The -all at the end is strict — anything not in the allowlist gets rejected. That's correct for a sending-only subdomain. Putting SPF on the bounce subdomain (rather than your apex) is what unlocks SPF alignment under DMARC and removes the “via amazonses.com” label in Gmail.
DMARC — your policy when SPF/DKIM fail
DMARC tells receivers what to do with messages that fail authentication. Start with monitoring-only:
Run with p=none for 1–2 weeks while you check your reports. Once you're confident everything authenticates cleanly, tighten to p=quarantine and then p=reject to actively block spoofing of your domain.
⚠️ Note: Gmail and Yahoo now require SPF + DKIM + DMARC for bulk senders. The DevSMTP onboarding modal sets all of them up automatically — you just need to publish the records.
Warm-up & Sending Limits
New domains start with low sending limits that automatically increase over time to build sender reputation.
| Time Period | Daily Limit |
|---|---|
| Week 1 (Days 1-7) | 50 emails/day |
| Week 2 (Days 8-14) | 100 emails/day |
| Week 3 (Days 15-21) | 200 emails/day |
| Week 4 (Days 22-30) | 500 emails/day |
| Month 2 (Days 31-60) | 1,000 emails/day |
| After 60 days | 5,000 emails/day |
Limits reset at midnight UTC each day. Check the remaining field in API responses to track usage.
DevSMTP is designed for single-recipient transactional emails. To receive copies of sent emails:
- •Global: Set one email in Settings to receive a copy of every email sent from any domain.
- •Per-Domain: Set up to 3 emails per domain to receive copies only for that project.
Copies are sent via BCC — no code changes required.
Send Email
/api/sendRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | ✓ | Recipient email address |
| from | string | ✓ | Sender email (must be verified domain) |
| subject | string | ✓ | Email subject line |
| html | string | * | HTML email body |
| text | string | * | Plain text email body |
* At least one of html or text is required
💡 Transactional Only: DevSMTP is designed for single-recipient transactional emails (welcome emails, password resets, notifications). Need to receive copies? Configure notification emails in Settings - no code changes needed.
Example Request
{
"to": "user@example.com",
"from": "hello@yourdomain.com",
"subject": "Welcome to our service!",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
"text": "Welcome! Thanks for signing up."
}Example Response
{
"success": true,
"messageId": "01234567-89ab-cdef-0123-456789abcdef",
"remaining": 49
}Test Mode
Test your email integration without sending real emails. Use special test addresses to simulate different delivery scenarios.
| Address | Simulates |
|---|---|
| delivered@devsmtp.dev | Successful delivery |
| bounced@devsmtp.dev | Bounced email |
| complained@devsmtp.dev | Spam complaint |
🧪 No real emails sent: Test emails are logged but never actually sent. They don't count against your daily limits.
curl -X POST https://devsmtp.com/api/v1/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "delivered@devsmtp.dev",
"from": "hello@yourdomain.com",
"subject": "Test Email",
"html": "<h1>Testing!</h1>"
}'Test Mode Response
{
"success": true,
"test": true,
"simulated_status": "sent",
"message": "Test email simulated with status: sent. No actual email was sent.",
"eventId": "test_abc123-def456-..."
}Test emails appear in your logs with a "test" indicator so you can distinguish them from real sends.
- ✓Use test addresses in CI/CD pipelines to validate email integration without sending
- ✓Test all three scenarios (delivered, bounced, complained) to ensure your app handles each correctly
- ✓Check the
test: truefield in responses to detect test mode - ✓Your
fromaddress must still be from a verified domain
Response Codes
| Code | Description |
|---|---|
| 200 | Email sent successfully |
| 400 | Bad request - check your request body |
| 401 | Unauthorized - invalid or missing API key |
| 403 | Forbidden - domain not verified or not owned |
| 429 | Too many requests - daily limit exceeded |
| 500 | Server error - try again later |
SDKs
Official SDKs for Node.js and PHP. Install via your package manager and start sending emails with just a few lines of code.
npm install @devsmtp/sdk
import DevSMTP from '@devsmtp/sdk';
const devsmtp = new DevSMTP('your-api-key');
// Send an email
const result = await devsmtp.send({
to: 'user@example.com',
from: 'hello@mail.yourdomain.com',
subject: 'Welcome!',
html: '<h1>Hello World</h1>'
});
console.log(result.eventId);| Method | Description |
|---|---|
| send(options) | Send a transactional email |
| validate(email) | Validate an email address |
| getStatus() | Get API usage and limits |
| getDomains() | List verified domains |
| getLogs(options?) | Get recent email logs |
import DevSMTP, { DevSMTPError } from '@devsmtp/sdk';
try {
await devsmtp.send({ ... });
} catch (error) {
if (error instanceof DevSMTPError) {
console.error(`Error ${error.statusCode}: ${error.message}`);
}
}Code Examples
Quick examples for sending emails without using an SDK.
curl -X POST https://devsmtp.com/api/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"from": "hello@yourdomain.com",
"subject": "Hello!",
"html": "<h1>Hello World</h1>"
}'Webhooks
Receive real-time notifications when emails bounce or recipients mark them as spam. Configure your webhook URL in the Dashboard settings.
| Event | Description |
|---|---|
| bounce | Email could not be delivered (invalid address, mailbox full, etc.) |
| complaint | Recipient marked the email as spam |
{
"event": "bounce",
"email": "user@example.com",
"bounce_type": "Permanent",
"bounce_subtype": "General",
"timestamp": "2026-01-22T11:24:00Z",
"message_id": "01234567-89ab-cdef-0123-456789abcdef"
}| Bounce Type | Description |
|---|---|
| Permanent | Hard bounce - remove this address from your list |
| Transient | Soft bounce - temporary issue, may succeed later |
{
"event": "complaint",
"email": "user@example.com",
"complaint_type": "abuse",
"timestamp": "2026-01-22T11:24:00Z",
"message_id": "01234567-89ab-cdef-0123-456789abcdef"
}⚠️ Important: When you receive a complaint, immediately stop sending to that address. High complaint rates can affect your sending reputation.
If you configure a webhook secret in your settings, we'll sign each request with an HMAC-SHA256 signature in the X-DevSMTP-Signature header.
// Node.js example
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return signature === expected;
}
// In your webhook handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-devsmtp-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
});Blocklist Monitoring
We automatically monitor your verified domains against major email blocklists and alert you if any issues are detected.
| Blocklist | Type |
|---|---|
| Spamhaus ZEN | IP |
| Spamhaus DBL | Domain |
| Barracuda | IP |
| SpamCop | IP |
| SORBS | IP |
| UCEPROTECT L1 | IP |
- •Shield icons: Each domain shows a shield icon — green if clear, red if listed on any blocklist
- •Last Checked: See when each domain was last scanned
- •Check Now: Click the shield to view details and trigger an immediate scan
- •Alert banner: A warning banner appears on your dashboard if any domain is listed
We send daily email alerts at 9am UTC if any of your domains have been listed or delisted from a blocklist.
Alert emails are sent to:
- Domain-specific emails — if configured in Settings
- Global notification email — if no domain-specific emails are set
- Your account email — as a fallback
💡 Tip: Configure notification emails in Settings to ensure the right people receive blocklist alerts.
- Click the shield icon on the affected domain to see which blocklist(s)
- Click the Remove link to visit the blocklist's removal request page
- Follow their instructions to request delisting
- Most blocklists process removal requests within 24-48 hours
- We'll automatically detect when you're delisted and update your status
Being listed on a blocklist can affect email deliverability. Using a subdomain for transactional emails helps isolate any reputation issues.
AI Integration (MCP Server)
Test emails and check logs directly from your AI coding assistant. Works with Windsurf, Cursor, Claude Desktop, and any MCP-compatible tool.
🤖 Developer-first feature: Let your AI assistant test emails while you code. No context switching needed.
npm install -g @devsmtp/mcp
Add to .windsurf/mcp.json:
{
"mcpServers": {
"devsmtp": {
"command": "devsmtp-mcp",
"env": {
"DEVSMTP_API_KEY": "your-api-key-here"
}
}
}
}| Tool | Description |
|---|---|
| send_test_email | Send a test email |
| check_email_logs | View recent logs |
| validate_email | Validate an address |
| get_api_status | Check usage & limits |
| list_domains | List verified domains |