SMTP2GO API Integration
Build email and SMS delivery with the SMTP2GO transactional API.
Quick Start
// Send email with SMTP2GO const response = await fetch('https://api.smtp2go.com/v3/email/send', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ sender: 'noreply@yourdomain.com', to: ['recipient@example.com'], subject: 'Hello from SMTP2GO', html_body: '<h1>Welcome!</h1><p>Your account is ready.</p>', text_body: 'Welcome! Your account is ready.', }), });
const result = await response.json(); // { request_id: "uuid", data: { succeeded: 1, failed: 0, email_id: "1er8bV-6Tw0Mi-7h" } }
Base URLs
Region Base URL
Global https://api.smtp2go.com/v3
US https://us-api.smtp2go.com/v3
EU https://eu-api.smtp2go.com/v3
AU https://au-api.smtp2go.com/v3
Authentication
Two methods supported:
// Method 1: Header (recommended) headers: { 'X-Smtp2go-Api-Key': 'your-api-key' }
// Method 2: Request body body: JSON.stringify({ api_key: 'your-api-key', // ... other params })
Get API keys from SMTP2GO dashboard: Sending > API Keys
Core Endpoints
Send Standard Email
POST /email/send
interface EmailSendRequest { // Required sender: string; // Verified sender email to: string[]; // Recipients (max 100) subject: string;
// Content (at least one required) html_body?: string; text_body?: string;
// Optional cc?: string[]; // CC recipients (max 100) bcc?: string[]; // BCC recipients (max 100) reply_to?: string; custom_headers?: Array<{ header: string; value: string }>; attachments?: Attachment[]; inlines?: InlineImage[];
// Templates template_id?: string; template_data?: Record<string, any>;
// Subaccounts subaccount_id?: string; }
interface Attachment { filename: string; mimetype: string; fileblob?: string; // Base64-encoded content url?: string; // OR URL to fetch from }
interface InlineImage { filename: string; mimetype: string; fileblob: string; cid: string; // Content-ID for HTML reference }
Response:
interface EmailSendResponse { request_id: string; data: { succeeded: number; failed: number; failures: string[]; email_id: string; }; }
Send MIME Email
POST /email/mime
For pre-encoded MIME messages:
const response = await fetch('https://api.smtp2go.com/v3/email/mime', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ mime_email: mimeEncodedString, }), });
Attachments
Base64 Encoding
// Convert file to base64 const fileBuffer = await file.arrayBuffer(); const base64 = btoa(String.fromCharCode(...new Uint8Array(fileBuffer)));
const email = { sender: 'noreply@example.com', to: ['user@example.com'], subject: 'Document attached', text_body: 'Please find the document attached.', attachments: [{ filename: 'report.pdf', fileblob: base64, mimetype: 'application/pdf', }], };
URL Reference (Cached 24h)
const email = { sender: 'noreply@example.com', to: ['user@example.com'], subject: 'Image attached', text_body: 'Photo from our event.', attachments: [{ filename: 'photo.jpg', url: 'https://cdn.example.com/photos/event.jpg', mimetype: 'image/jpeg', }], };
Inline Images in HTML
const email = { sender: 'noreply@example.com', to: ['user@example.com'], subject: 'Newsletter', html_body: '<h1>Welcome</h1><img src="cid:logo123" alt="Logo">', inlines: [{ filename: 'logo.png', fileblob: logoBase64, mimetype: 'image/png', cid: 'logo123', // Reference in HTML as src="cid:logo123" }], };
Limits: Maximum total email size: 50 MB (content + attachments + headers)
Templates
Create Template
POST /template/add
const response = await fetch('https://api.smtp2go.com/v3/template/add', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ template_name: 'welcome-email', html_body: '<h1>Welcome, {{ name }}!</h1><p>Thanks for joining {{ company }}.</p>', text_body: 'Welcome, {{ name }}! Thanks for joining {{ company }}.', }), });
Send with Template
const email = { sender: 'noreply@example.com', to: ['user@example.com'], subject: 'Welcome aboard!', template_id: 'template-uuid-here', template_data: { name: 'John', company: 'Acme Corp', }, };
Template Syntax: HandlebarsJS with {{ variable }} placeholders.
Template Endpoints
Endpoint Method Description
/template/add
POST Create new template
/template/edit
POST Update existing template
/template/delete
POST Remove template
/template/search
POST List/search templates
/template/view
POST Get template details
Webhooks
Configure webhooks to receive real-time delivery notifications.
Event Types
Email Events:
Event Description
processed
Email queued for delivery
delivered
Successfully delivered
open
Recipient opened email
click
Link clicked
bounce
Delivery failed
spam
Marked as spam
unsubscribe
User unsubscribed
resubscribe
User resubscribed
reject
Blocked (suppression/sandbox)
SMS Events:
Event Description
sending
Processing
submitted
Sent to provider
delivered
Confirmed delivery
failed
Delivery failed
rejected
Network blocked
opt-out
Recipient opted out
Webhook Payload (Email)
interface WebhookPayload { event: string; time: string; // Event timestamp sendtime: string; // Original send time sender: string; from_address: string; rcpt: string; // Recipient recipients: string[]; email_id: string; subject: string; bounce?: string; // Bounce type if applicable client?: string; // Email client (for opens) 'geoip-country'?: string; }
Webhook Configuration
POST /webhook/add
await fetch('https://api.smtp2go.com/v3/webhook/add', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ url: 'https://api.yourdomain.com/webhooks/smtp2go', events: ['delivered', 'bounce', 'spam', 'unsubscribe'], }), });
Webhook Endpoints
Endpoint Method Description
/webhook/view
POST List webhooks
/webhook/add
POST Create webhook
/webhook/edit
POST Update webhook
/webhook/remove
POST Delete webhook
Retry Policy: Up to 35 retries over 48 hours. Timeout: 10 seconds.
Statistics
Email Summary
POST /stats/email_summary
Combined report of bounces, cycles, spam, and unsubscribes.
const response = await fetch('https://api.smtp2go.com/v3/stats/email_summary', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({}), });
Statistics Endpoints
Endpoint Method Description
/stats/email_summary
POST Combined statistics
/stats/email_bounces
POST Bounce summary (30 days)
/stats/email_cycle
POST Email cycle data
/stats/email_history
POST Historical data
/stats/email_spam
POST Spam reports
/stats/email_unsubs
POST Unsubscribe data
Activity Search
POST /activity/search (Rate limited: 60/min)
Search for email events:
const response = await fetch('https://api.smtp2go.com/v3/activity/search', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ // Filter parameters }), });
Note: Returns max 1,000 items. For real-time data, use webhooks instead.
Suppressions
Manage email addresses that should not receive emails.
Add Suppression
POST /suppression/add
await fetch('https://api.smtp2go.com/v3/suppression/add', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ email: 'blocked@example.com', }), });
Suppression Endpoints
Endpoint Method Description
/suppression/add
POST Add to suppression list
/suppression/view
POST View suppressions
/suppression/remove
POST Remove from list
SMS
POST /sms/send
const response = await fetch('https://api.smtp2go.com/v3/sms/send', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify({ to: ['+61400000000'], // Max 100 numbers message: 'Your verification code is 123456', }), });
SMS Endpoints
Endpoint Method Description
/sms/send
POST Send SMS
/sms/received
POST View received SMS
/sms/sent
POST View sent SMS
/sms/summary
POST SMS statistics
Response Codes
Code Status Description
200 OK Success
400 Bad Request Invalid parameters
401 Unauthorized Invalid/missing API key
402 Request Failed Valid params, request failed
403 Forbidden Insufficient permissions
404 Not Found Resource not found
429 Too Many Requests Rate limited
5xx Server Error SMTP2GO server issue
Error Response Format
interface ErrorResponse { request_id: string; data: { error: string; error_code: string; field_validation_errors?: Record<string, string>; }; }
Common error codes:
-
E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED
-
API key lacks permission
-
E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD
-
Invalid JSON/email format
-
E_ApiResponseCodes.API_EXCEPTION
-
General API error
Rate Limiting
-
Activity Search: 60 requests/minute
-
Email Search (deprecated): 20 requests/minute
-
Other endpoints: Configurable per API key
Handling 429:
async function sendWithRetry(payload: any, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const response = await fetch('https://api.smtp2go.com/v3/email/send', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY, }, body: JSON.stringify(payload), });
if (response.status === 429) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
continue;
}
return response.json();
} throw new Error('Rate limit exceeded after retries'); }
Cloudflare Workers Integration
// wrangler.jsonc { "name": "email-service", "vars": { "SMTP2GO_REGION": "api" // or "us-api", "eu-api", "au-api" } }
// .dev.vars SMTP2GO_API_KEY=api-XXXXXXXXXXXX
// src/index.ts
export default {
async fetch(request: Request, env: Env) {
const baseUrl = https://${env.SMTP2GO_REGION}.smtp2go.com/v3;
// Send transactional email
const response = await fetch(`${baseUrl}/email/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'noreply@yourdomain.com',
to: ['user@example.com'],
subject: 'Order Confirmation',
template_id: 'order-confirmation-template',
template_data: {
order_id: '12345',
total: '$99.00',
},
}),
});
const result = await response.json();
return Response.json(result);
}, } satisfies ExportedHandler<Env>;
interface Env { SMTP2GO_API_KEY: string; SMTP2GO_REGION: string; }
Sender Verification
Before sending, verify your sender identity:
-
Sender Domain (Recommended): Add and verify domain in SMTP2GO dashboard for SPF/DKIM alignment
-
Single Sender Email: Verify individual email address
Unverified senders are rejected with 400 error.
Common Patterns
Contact Form Handler
export async function handleContactForm(formData: FormData, env: Env) { const name = formData.get('name') as string; const email = formData.get('email') as string; const message = formData.get('message') as string;
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
},
body: JSON.stringify({
sender: 'website@yourdomain.com',
to: ['support@yourdomain.com'],
reply_to: email,
subject: Contact form: ${name},
text_body: From: ${name} <${email}>\n\n${message},
html_body: <p><strong>From:</strong> ${name} &lt;${email}&gt;</p> <hr> <p>${message.replace(/\n/g, '<br>')}</p> ,
}),
});
if (!response.ok) { throw new Error('Failed to send email'); }
return response.json(); }
Webhook Handler
export async function handleWebhook(request: Request) { const payload = await request.json();
switch (payload.event) {
case 'bounce':
// Handle bounce - update user record, retry logic
console.log(Bounce: ${payload.rcpt} - ${payload.bounce});
break;
case 'unsubscribe':
// Update preferences
console.log(`Unsubscribe: ${payload.rcpt}`);
break;
case 'spam':
// Add to suppression, alert team
console.log(`Spam report: ${payload.rcpt}`);
break;
}
return new Response('OK', { status: 200 }); }
Troubleshooting
Issue Cause Solution
401 Unauthorized Missing/invalid API key Check API key in header or body
400 sender not verified Unverified sender domain Verify domain in SMTP2GO dashboard
429 Too Many Requests Rate limit exceeded Implement exponential backoff
Attachment too large Over 50MB total Compress or use URL references
Template variables not replaced Wrong syntax Use {{ variable }} Handlebars syntax
Webhook not receiving events Timeout/errors Check endpoint returns 200 within 10s
References
-
SMTP2GO API Documentation
-
API Reference
-
Getting Started Guide
-
Webhook Documentation
-
Template Guide
Last Updated: 2026-02-06 API Version: v3.0.3