· 8 min read

API vs SMTP: Which to Use for Transactional Email

Technical comparison of REST API and SMTP for sending transactional email. Performance, error handling, and implementation examples.

Modern email services offer two ways to send transactional email: REST API and SMTP. Both work, but they have different trade-offs. This guide helps you choose.

Quick Comparison

Factor REST API SMTP
Ease of Use Simple More complex
Error Handling Structured JSON Error codes
Connection Overhead Per request Persistent connection
Bulk Sending Batched API calls Persistent connection
Legacy Support Requires code Works with any client
Firewall Issues Port 443 (HTTPS) Port 587/465 may be blocked

REST API

REST APIs use standard HTTP requests. Send a POST with JSON payload, get a JSON response. Modern and straightforward.

Advantages

  • Structured error responses with detailed information
  • Uses standard HTTPS on port 443 (rarely blocked)
  • Easy to debug with standard HTTP tools
  • SDK support in every language
  • Batch sending in single requests

Example: Sequenzy API

import { Sequenzy } from '@sequenzy/sdk';

const sequenzy = new Sequenzy({ apiKey: process.env.SEQUENZY_API_KEY });

try {
  const result = await sequenzy.send({
    to: 'user@example.com',
    template: 'password-reset',
    variables: {
      resetLink: 'https://app.example.com/reset/abc123'
    }
  });

  console.log('Message ID:', result.id);
} catch (error) {
  // Structured error handling
  if (error.code === 'invalid_recipient') {
    console.log('Invalid email address');
  } else if (error.code === 'rate_limited') {
    console.log('Too many requests, retry after:', error.retryAfter);
  }
}

Example: Resend API

import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

const { data, error } = await resend.emails.send({
  from: 'noreply@example.com',
  to: 'user@example.com',
  subject: 'Reset your password',
  html: '<p>Click here to reset...</p>'
});

if (error) {
  console.error('Failed to send:', error.message);
} else {
  console.log('Sent:', data.id);
}

Example: Raw HTTP Request

curl -X POST https://api.sequenzy.com/v1/send \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "template": "password-reset",
    "variables": {
      "resetLink": "https://app.example.com/reset/abc123"
    }
  }'

SMTP

SMTP (Simple Mail Transfer Protocol) is the original email protocol. Connect to a server, authenticate, send the message using SMTP commands.

Advantages

  • Works with any email client or library
  • Persistent connections for high-volume sending
  • Required for some legacy systems
  • Can use existing email infrastructure

Example: Node.js with Nodemailer

import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: 'smtp.sequenzy.com',
  port: 587,
  secure: false, // TLS
  auth: {
    user: 'apikey',
    pass: process.env.SEQUENZY_API_KEY
  }
});

try {
  const info = await transporter.sendMail({
    from: 'noreply@example.com',
    to: 'user@example.com',
    subject: 'Reset your password',
    html: '<p>Click here to reset...</p>'
  });

  console.log('Message sent:', info.messageId);
} catch (error) {
  // SMTP error codes are less descriptive
  console.error('SMTP error:', error.message);
}

Example: Python with smtplib

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

msg = MIMEMultipart('alternative')
msg['Subject'] = 'Reset your password'
msg['From'] = 'noreply@example.com'
msg['To'] = 'user@example.com'

html = '<p>Click here to reset...</p>'
msg.attach(MIMEText(html, 'html'))

with smtplib.SMTP('smtp.sequenzy.com', 587) as server:
    server.starttls()
    server.login('apikey', os.environ['SEQUENZY_API_KEY'])
    server.send_message(msg)

When to Use API

  • Building a new application
  • You want better error handling
  • Using templates managed by the email service
  • You need batch sending capabilities
  • Firewall blocks SMTP ports

When to Use SMTP

  • Integrating with legacy systems
  • Using existing email-sending code
  • Sending from email clients (Outlook, Thunderbird)
  • Very high volume with persistent connections
  • CMS or application only supports SMTP

Performance Considerations

Connection Overhead

Each SMTP session requires a TCP handshake, TLS negotiation, and authentication. For single emails, this overhead is significant. APIs have similar overhead per request but handle it more efficiently.

// SMTP: Keep connection open for multiple sends
const transporter = nodemailer.createTransport({...});

// Send many emails on same connection
for (const recipient of recipients) {
  await transporter.sendMail({
    to: recipient.email,
    ...
  });
}

// Close when done
transporter.close();

API Batching

Many APIs support sending to multiple recipients in one request:

// Batch sending with API
await sequenzy.sendBatch([
  { to: 'user1@example.com', template: 'welcome' },
  { to: 'user2@example.com', template: 'welcome' },
  { to: 'user3@example.com', template: 'welcome' }
]);

Recommendation

Use API for most applications. Better error handling, easier debugging, and simpler code. The modern approach.

Use SMTP when required. Legacy systems, CMS integrations, or sending from desktop email clients.

Most services like Sequenzy, Postmark, and Resend recommend their API but support SMTP for compatibility.

Compare email services

Find the right transactional email service with great API design.

View Full Comparison