Guides · Integration

Building a transactional email service

Transactional email (receipts, password resets, confirmations, alerts) is sent one message at a time in response to something a user did. It needs to be fast and reliable, and it should be kept separate from your marketing mail. Here's how to build it on BlacklistGuard.

Set up

  • Verify a sending domain and publish SPF, DKIM, and DMARC. See Set up a sending domain. Your from_email must be on a verified domain.
  • Create an API key for your backend service and keep it server-side. See Authentication.

Keep it separate from marketing

Transactional mail (which users expect and engage with) and marketing mail (which has complaints and unsubscribes) build very different reputations. Don't let your marketing reputation drag down your password resets. A common pattern is to send transactional mail from a dedicated subdomain, for example mail.yourdomain.com for transactional and news.yourdomain.com for marketing, so each builds its own reputation.

Sending a message

Each message is a single POST to the send endpoint:

curl -X POST https://app.blacklistguard.com/api/v1/emails/send \
  -H "X-API-Key: efk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "from_email": "noreply@mail.yourdomain.com",
    "from_name": "Acme",
    "to": "user@example.com",
    "subject": "Reset your password",
    "body": "<p>Click the link to reset your password…</p>"
  }'
ℹThe send endpoint takes one recipient and one HTML/text body per request. It does not render templates. Your application builds the final HTML (with your own templating) and sends it. Attachments are supported; see the reference for the full field list.

Handle the response

A success returns 201 with { "data": { "status": "queued", "id": "…" } }. Store the id so you can look the message up later in Messages. On failure, the envelope has "success": false with an error and a code. Handle at least these:

  • BAD_REQUEST: a bad request, a missing from_email, to or subject, or an unverified sender. Fix and retry.
  • RATE_LIMIT_EXCEEDED: you're sending too fast, or you've reached your workspace's hourly, daily or monthly sending limit. The message says which. Back off and retry later.
  • INSUFFICIENT_BALANCE / PLAN_LIMIT_REACHED: top up or upgrade.
  • SERVICE_SUSPENDED: a payment is overdue. Pay what's due under Billing and sending resumes on its own.
  • SENDING_PAUSED: sending is paused for your account. Contact support.

See the full error codes. Build a short retry with backoff for transient errors (429, 500), but don't retry validation errors.

Respect suppression

Even transactional senders bounce and get complaints. When a bounce shows an address can't receive mail, that address is suppressed automatically, so you won't keep hammering dead addresses. Complaints that come back through feedback loops are suppressed automatically too.

The API still accepts a message to a suppressed address, but doesn't deliver it. In the message log it shows as skipped, with the reason address is suppressed. If a critical message (like a password reset) never arrives, look it up under Messages and check whether the address is on a suppression list. That's usually why.

Monitor

Watch delivery and bounces like any other stream. See Tracking delivery, bounces & complaints. Because users expect transactional mail, a rising bounce or deferral rate here is an early warning worth acting on quickly.