Developer Guide

How to Send Emails with an API: A Complete Developer Guide

From your first transactional email to drip sequences — everything you need to know about sending email programmatically in 2026.

10 min read·Updated March 2026

Sending an email through an API sounds simple — and it is, for one email. But building a reliable email system that handles transactional confirmations, drip sequences, and high volume without ending up in spam? That requires understanding a few things first.

This guide covers the full picture: picking an email API, authenticating your domain, sending your first email, and scaling to automation sequences — with real code examples throughout.

1. Picking the right email API

The email API market splits into two categories: infrastructure providers and full-platform tools.

Infrastructure providers

Handle SMTP relay, deliverability, and basic analytics. You own the logic.

  • • Amazon SES — cheapest at $0.10/1K
  • • Mailgun — solid deliverability, basic API
  • • Postmark — best transactional delivery
  • • SendGrid — high volume, complex pricing

Full-platform tools

API + sequences + contacts + analytics. Bring your own sending key (BYOK) to avoid markup.

  • • tinysend — API-first, BYOK, usage-based
  • • Resend — clean API, transactional only
  • • Loops — SaaS email with sequences
  • • Customer.io — enterprise automation

If you just need to fire off password resets, start with a pure infrastructure provider. If you need sequences, contact management, or automation — pick a platform tool that lets you BYOK so you're not paying double for sends.

2. Domain authentication (SPF, DKIM, DMARC)

Before you send a single email, authenticate your domain. Without it, you'll hit spam folders — sometimes immediately. All major mailbox providers (Gmail, Outlook) check these records.

SPF record

SPF (Sender Policy Framework) tells receiving servers which IP addresses are authorized to send email from your domain. Add a TXT record to your DNS:

DNS TXT record — yourdomain.com
v=spf1 include:tinysend.co include:amazonses.com ~all

DKIM record

DKIM (DomainKeys Identified Mail) signs your emails with a cryptographic key, letting receivers verify the message hasn't been tampered with. Your email platform generates a DKIM keypair; you add the public key as a TXT record:

DNS TXT record — selector._domainkey.yourdomain.com
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBA...

DMARC record

DMARC ties SPF and DKIM together and tells receivers what to do with mail that fails either check. Start with p=none to monitor, then harden to p=quarantine or p=reject once you're confident:

DNS TXT record — _dmarc.yourdomain.com
v=DMARC1; p=none; rua=mailto:[email protected]

3. Sending your first email via API

Every email API follows the same pattern: authenticate with an API key, POST a JSON payload with from/to/subject/body, handle the response. Here's what that looks like with a few providers:

tinysend

curl -X POST https://api.tinysend.co/v1/emails \
  -H "Authorization: Bearer ts_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Welcome to the app!",
    "html": "<h1>Welcome</h1><p>Thanks for signing up.</p>"
  }'

Node.js with tinysend SDK

import { Tinysend } from '@tinysend/node'

const client = new Tinysend({ apiKey: process.env.TINYSEND_API_KEY })

await client.emails.send({
  from: '[email protected]',
  to: req.user.email,
  subject: 'Confirm your email address',
  template: 'confirm-email',
  variables: {
    firstName: req.user.name,
    confirmUrl: `https://app.example.com/confirm?token=${token}`
  }
})

Python

import requests

response = requests.post(
    "https://api.tinysend.co/v1/emails",
    headers={
        "Authorization": f"Bearer {os.environ['TINYSEND_API_KEY']}",
        "Content-Type": "application/json"
    },
    json={
        "from": "[email protected]",
        "to": user.email,
        "subject": "Password reset",
        "template": "password-reset",
        "variables": {"resetUrl": reset_url}
    }
)
response.raise_for_status()

4. Transactional vs marketing email

This distinction matters for deliverability, compliance, and infrastructure setup.

TypeExamplesUnsubscribe required?Send separately?
TransactionalPassword reset, receipts, order confirmation, alertsNoYes — dedicated IP/domain
MarketingNewsletters, promotions, announcementsYes (CAN-SPAM/GDPR)Yes — separate domain/IP
Product (drip)Onboarding sequences, re-engagement, feature tipsBest practice: yesIdeally separate

Keep transactional email on a separate subdomain (e.g. mail.yourdomain.com) from marketing. If your marketing mail gets flagged for spam, it won't nuke your transactional reputation.

5. Handling delivery events with webhooks

Set up webhooks to track what happens after you send. At minimum, handle these events:

  • deliveredThe receiving server accepted the message. Log it and move on.
  • bouncedHard bounce = invalid address. Mark that contact as undeliverable immediately, or you'll tank your sender reputation.
  • complainedThe user marked it as spam. Unsubscribe them instantly and remove from all future sends.
  • opened / clickedUse for sequence progression — advance to next email, update engagement score, etc.
// Express webhook handler
app.post('/webhooks/email', express.raw({ type: 'application/json' }), (req, res) => {
  const event = JSON.parse(req.body)

  switch (event.type) {
    case 'email.bounced':
      await db.contacts.update(
        { email: event.data.to },
        { $set: { status: 'bounced', bouncedAt: new Date() } }
      )
      break
    case 'email.complained':
      await db.contacts.update(
        { email: event.data.to },
        { $set: { unsubscribed: true, unsubscribedAt: new Date() } }
      )
      break
    case 'email.opened':
      await sequences.advance(event.data.contactId, event.data.sequenceId)
      break
  }

  res.json({ received: true })
})

6. Building drip sequences and automation

Once you go beyond one-off transactional emails, you need sequences: scheduled series of emails triggered by user behavior. A typical SaaS onboarding sequence looks like this:

1
Day 0 — Welcome email
Triggered on signup. Confirm email, link to key features, set expectations.
2
Day 2 — Feature highlight
If no key action taken yet. Drive toward the "aha moment" — first project, first send, etc.
3
Day 7 — Check-in
Light touchpoint. Share a tip, ask if they have questions. Filter out users who completed onboarding.
4
Day 14 — Social proof / upgrade
Share a customer story. If still on free tier, nudge toward paid with a limited offer.

With tinysend, you define sequences as code in a YAML or JSON config and deploy via CLI. No dragging blocks in a UI:

# tinysend sequence definition
name: onboarding
trigger:
  event: user.signed_up

steps:
  - delay: 0
    template: welcome
    condition: null

  - delay: 2d
    template: feature-highlight
    condition: "contact.properties.has_completed_setup == false"

  - delay: 7d
    template: check-in
    condition: "contact.properties.has_completed_setup == false"

  - delay: 14d
    template: upgrade-nudge
    condition: "contact.properties.plan == 'free'"

7. Avoiding spam filters

Even with perfect domain auth, you can still land in spam. Here's what actually moves the needle:

Warm up new sending IPs
Start at 50-100 emails/day, double every 3-5 days. Sending 10K emails from a cold IP on day 1 will get you blocklisted.
Keep your bounce rate below 2%
Remove hard bounces immediately. A bounce rate over 2% signals a dirty list and triggers spam filtering.
Send from a real address, not no-reply@
Gmail and others treat no-reply@ addresses as lower-reputation. Use team@ or hello@ for better inbox placement.
Use plain-text alternatives
Always send both HTML and plain-text versions. HTML-only emails score worse in spam filters and look suspicious.
Handle unsubscribes immediately
One-click unsubscribe (RFC 8058) is now required by Gmail and Yahoo for bulk senders. Build it in from day one.

Start sending email via API today

tinysend gives you a full email platform — transactional sends, sequences, contact management, and BYOK. API-first, usage-based, free to start.

Get started free →