Email API integration needs five things done right: API key in environment variables (never in code), retries with exponential backoff for 5xx errors, idempotency keys to prevent duplicate sends on retry, webhook handlers for bounces and complaints that update your suppression list, and a separate transactional vs marketing subdomain. Skip any of these and you'll have an incident within 6 months.
Email API Integration: Implementation Patterns
The mechanics of calling an email API are simple — POST to an endpoint, get back a 202. The reason most integrations end up in production incidents isn't the call itself, it's everything around it: retry logic, idempotency, webhook handling, suppression lists, and subdomain strategy.
The cluster around "send email api" includes secure email api, email api integration, email rest api, mail sending api, and email delivery api. All the same job — get email from your application into recipients' inboxes — viewed through different parts of the implementation. This guide covers the patterns that hold up across SendGrid, Mailgun, Postmark, Resend, and AWS SES.
Authentication: Get It Right Once
Every modern email API uses bearer token auth or AWS Signature v4 (for SES). Two rules:
- API keys in environment variables, never in source. Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, Doppler) in production.
- Scoped keys. Most providers let you create send-only keys vs admin keys. Your application should only have the minimum permission needed.
Example with SendGrid in Node:
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
await sgMail.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Order confirmed',
html: orderConfirmationHtml,
headers: { 'X-Entity-Ref-ID': orderId },
});
The X-Entity-Ref-ID is your idempotency key (see below). Always include one.
Retries and Idempotency
Email APIs return three categories of response:
- 2xx — accepted. Don't retry. Email is in their queue.
- 4xx — your fault (bad address, missing field, key revoked). Don't retry. Fix and resubmit.
- 5xx — their fault (transient). Retry with exponential backoff.
The trap: you retry a 5xx that actually delivered (timeout after the send went through). Without idempotency, the recipient gets two emails.
Most providers accept an idempotency key — SendGrid via X-Entity-Ref-ID, Postmark via MessageStream and Tag, Mailgun via v:my-key variables. Use the same key on retry and the provider will dedupe.
Practitioner note: Postmark is the only major provider that honors idempotency-keys natively in their
IdempotencyKeyheader on the messages endpoint. For others, you build your own dedupe — store the message hash + recipient in your DB with a unique constraint, return early if a duplicate is attempted within 24h.
Webhook Handling: The Part Everyone Skips
Send endpoint returns 202. Email is queued. What happens next — delivery, bounce, complaint, open, click — comes back via webhooks. Without webhook handling, you have no idea what's actually working.
Minimum webhooks to handle:
- bounce (hard) — add to suppression list permanently
- complaint / spam — add to suppression list permanently, investigate why
- dropped / blocked — recipient on suppression already, log and skip
- delivered — useful for support ("did the password reset land?")
Optional but valuable: open and click for marketing email engagement tracking.
Verify webhook signatures. Every major provider signs the request:
- SendGrid uses an Ed25519 signature in
X-Twilio-Email-Event-Webhook-Signature - Postmark uses HTTP Basic Auth on your endpoint
- Mailgun signs with HMAC-SHA256
- AWS SES uses SNS message signing
If you don't verify signatures, anyone can POST fake bounce events to your endpoint and suppress legitimate addresses.
Suppression List Architecture
Most providers maintain a suppression list internally. Trusting only the provider's list breaks if you ever migrate providers — you'll re-send to addresses that already complained.
Maintain a suppression table in your application database:
CREATE TABLE email_suppressions (
email VARCHAR(254) PRIMARY KEY,
reason VARCHAR(50) NOT NULL, -- 'bounce', 'complaint', 'unsubscribe'
suppressed_at TIMESTAMP DEFAULT NOW(),
provider_id VARCHAR(100),
metadata JSONB
);
Check this table before every send. Add to it on every bounce/complaint webhook. Sync it to your provider's suppression list during onboarding to a new provider.
Subdomain Strategy
Send transactional and marketing from different subdomains. This protects your transactional reputation from marketing list issues.
| Mail type | Subdomain example | Why separate |
|---|---|---|
| Transactional | send.example.com | High engagement, must reach inbox |
| Marketing | mail.example.com | Variable engagement, separate reputation |
| Cold outbound | outreach.example.com | Burns reputation, must isolate |
Authentication (SPF, DKIM, DMARC) on each subdomain. See SPF setup guide and DKIM setup guide.
Practitioner note: The most common migration disaster I see: company moves from one ESP to another, doesn't transfer their suppression list, and re-mails 5000 addresses that previously complained. The new ESP's spam complaint rate spikes within 24 hours and the account gets put on review. Always export suppression on migration.
Rate Limiting and Batching
Each provider has different per-second send limits — usually 10-100/sec on standard tiers, more on enterprise. Build a rate limiter or use a queue.
For bulk sends (newsletter to 50K recipients), use the provider's batch endpoint:
- SendGrid —
personalizationsarray, up to 1000 recipients per call - Mailgun — Batch Sending with recipient-variables, up to 1000 per call
- SES —
SendBulkTemplatedEmail, up to 50 recipients per call - Postmark —
/email/batchendpoint, up to 500 messages per call
Don't loop calling the single-send endpoint 50,000 times. You'll hit rate limits and the cost in API call overhead is significant.
Receive Email Via API
If your application needs to receive parsed inbound mail (replies to support tickets, email-to-app workflows):
- Point MX records at the provider's inbound infrastructure
- Configure inbound routes for the addresses you want to receive
- Receive parsed JSON at your webhook endpoint
- Verify webhook signatures
Providers with mature inbound: Mailgun, SendGrid, Postmark, Mailersend. See free email API comparison for the picks.
Testing in Development
Don't send real email from dev or staging. Options:
- Mailtrap — captures SMTP/API traffic, shows messages, ~3K free/mo
- Mailpit — self-hosted, free, single binary
- Provider sandbox modes — SES sandbox, SendGrid sandbox mode
Configure your dev environment to point at one of these. Production sends to real recipients via the actual provider.
If you need help architecting an email API integration that scales and stays out of spam folders, book a consultation. I work with engineering teams on sender domain setup, authentication, webhook architecture, and migration plans across the major email APIs.
Sources
- SendGrid v3 API Reference
- Postmark Developer Docs
- Mailgun API Documentation
- Resend API Reference
- AWS SES Developer Guide
- RFC 5321 — SMTP
v1.0 · May 2026
Frequently Asked Questions
How do I send email via API?
Make an authenticated HTTPS POST to the provider's send endpoint with from, to, subject, and html or text body. Most providers use bearer token auth in the Authorization header. Handle the response — 200/202 means accepted for delivery, not delivered. Watch webhooks for actual delivery, bounces, and complaints.
What is a secure email API?
A secure email API requires TLS 1.2+ for transport, token-based authentication (not basic auth), API keys scoped to specific permissions (send-only vs admin), and webhook signature verification to prevent forged callbacks. Rotate keys at least annually. Store keys in a secrets manager, never in source code.
What is an email delivery API?
An email delivery API is a REST or SMTP service that accepts your email payload and handles routing, authentication signing, IP rotation, retry logic, and ISP-specific optimization to maximize inbox placement. Examples: SendGrid, Mailgun, Postmark, AWS SES, Resend.
How do I handle bounces from an email API?
Set up the provider's webhook endpoint to receive bounce events. Hard bounces (550 errors) get added to your permanent suppression list immediately. Soft bounces (4xx) trigger retry; suppress after 3-5 consecutive failures. Most providers auto-suppress hard bounces but you still need to mirror that in your application database.
Can I send email from a web app without an API?
Technically yes via SMTP libraries, but you'll hit deliverability and rate limit issues. Even SMTP needs to go through a managed sender (SendGrid SMTP relay, AWS SES SMTP) for any real volume. Direct SMTP from your application server is for prototype only — production needs a sender service.
Want this handled for you?
Free 30-minute strategy call. Walk away with a plan either way.