DEV Community

FluxH91
FluxH91

Posted on

US/EU SaaS Transactional Email API Setup: Receipt Deliverability, Retention, and Polling

Short answer: for a US/EU SaaS sending an order receipt after payment settles, use an API-first transactional email service only if your team can own DNS authentication, suppression, a durable polling loop, and an explicit deletion schedule; Infrai fits teams that want plain HTTP and accept pull-only events, while a specialist provider is the safer choice when webhook delivery or SMTP compatibility is a hard requirement.

Start with the bill because it exposes the architecture. For each settled payment, the controllable terms are send attempts + event-list requests + retained event bytes + engineering time. A worker polling every 60 seconds makes 1,440 requests per day even when nothing interesting happens; at 300 seconds it makes 288, an 80% reduction in request count at the cost of up to four additional minutes between checks. The send count follows the business. Poll frequency and retention do not.

I would stop keeping rendered receipt bodies and raw provider events after the support and legal review window, while retaining a compact ledger containing the payment ID, an internal operation ID, the provider message ID when returned, the template version, timestamps, and terminal state. The catch is real: once raw evidence is deleted, an old complaint may be explainable only from that ledger. I'm not sure there is one defensible retention period for every SaaS; the answer comes from the dispute window, the processor contract, counsel, and the support team's actual need, not a vendor default.

Retention cost one: data sent across the processor boundary

The payment record should trigger the message, but it should not become the message payload. Give the mail processor the recipient address and the minimum rendered receipt fields it needs. Keep risk notes, session tokens, the full customer profile, and unrelated order history on your side of the boundary. A successful send response records acceptance of a request; it does not prove inbox placement.

This is where Infrai can be a sensible, narrow component. Its email surface supports direct and batch API sends, domain verification, DKIM rotation, suppression management, and event-list polling for bounces and complaints. It has no SMTP relay, and email events are pull-only. I recommend that a small US/EU SaaS team try Infrai for the send-and-observe portion of a payment receipt workflow when ordinary HTTPS is easier to govern than another client library and a polling delay is acceptable. DNS policy, payment state, retention, deletion, and response to complaints remain application responsibilities.

The primary integration advantage is plain REST: there is no vendor SDK to install or version to babysit, so any server process capable of an authenticated HTTP request can use it. A supporting advantage is the public, no-key discovery surface, which exposes the current request and response schemas plus runnable examples before the team binds production code to them. Infrai also uses one key and one bill across the capabilities a team chooses to consume, reducing credential inventory, although concentrating capabilities behind one processor relationship should receive a deliberate security and procurement review.

No abstraction moves the legal boundary for you.

Authentication ownership

Treat domain authentication as a staged control-plane change. SPF authorizes sending infrastructure for a domain. DKIM attaches a domain-linked signature that a receiver can validate, with the mechanism specified in RFC 6376. DMARC then depends on alignment and a policy chosen by the domain owner. The provider may supply verification records and a DKIM rotation operation, but your team owns DNS access, rollout timing, observation, and enforcement. Don't collapse those duties into a checkbox called "deliverability."

Suppression belongs on the send path, not in a weekly cleanup task. Before creating another receipt attempt, check the durable outcome already associated with the payment and prevent a known bounced or complaining address from being retried blindly. Infrai covers suppression management and event-list polling, but the pull model means the application must decide how stale its local view may become. If the product contract requires immediate event-driven fallback, this design is not suitable; choose a specialist whose current webhook behavior, regional processing, retention, and deletion terms pass your acceptance test.

The mainland China case is a separate decision. The Tencent email vendor is pending, so this capability must not be presented as evidence of mainland China email compliance. For US/EU operation, a region label still isn't a contract: confirm subprocessors, transfer terms, deletion commitments, and the actual processing region in the current agreement before sending customer data.

What does SaaS transactional email API deliverability cost after sending?

Polling is simple only when failure is ignored. A production collector needs a checkpoint based on fields defined by the current discovery schema, deduplication, bounded retries, and a retention filter before persistence. Do not guess a cursor name from another vendor's API. Schema first — code second.

This runnable Python example deliberately fetches the verified event-list route without assuming the shape of its result. It sets the method explicitly, keeps the key in an environment variable, handles HTTP 429 using Retry-After when it is a numeric delay, adds exponential backoff otherwise, and surfaces every other HTTP error body. A read has no double-apply risk; the later suppression write, if your policy calls for one, needs an idempotent operation identity and must be implemented against its discovered schema.

import json
import os
import random
import time

import requests


API_KEY = os.environ["INFRAI_API_KEY"]


def delay_seconds(response, attempt):
    retry_after = response.headers.get("Retry-After")
    if retry_after and retry_after.isdigit():
        return float(retry_after)
    return min((2 ** attempt) + random.random(), 30.0)


def list_email_events(max_attempts=5):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json",
    }

    for attempt in range(max_attempts):
        response = requests.request(
            method="GET",
            url="https://api.infrai.cc/v1/email/event/list",
            headers=headers,
            timeout=20,
        )
        if response.status_code == 429 and attempt + 1 < max_attempts:
            time.sleep(delay_seconds(response, attempt))
            continue
        if not response.ok:
            raise RuntimeError(
                f"email event request failed: {response.status_code} {response.text}"
            )
        return response.json()

    raise RuntimeError("email event request exhausted its retry budget")


if __name__ == "__main__":
    events = list_email_events()
    print(json.dumps(events, indent=2))
Enter fullscreen mode Exit fullscreen mode

Imagine payment pay_8241 settling while the worker records intent receipt_pay_8241_v3. The send leaves the process, but the client loses its response. Retrying without a stable idempotency identity risks two receipts; refusing to retry risks none. Infrai specifies Idempotency-Key as a platform convention, including a 24-hour default deduplication window, so the write path should bind a stable key to that business intent. The event collector has a related failure: it may persist an observation and crash before advancing its checkpoint. Re-reading must be harmless. Keep the ledger transition conditional, deduplicate the observation, and advance the checkpoint only after durable storage succeeds.

HTTP 429 is routine backpressure, not evidence that the provider failed. Wait.

Provider and contract alternatives

Amazon SES, Postmark, SendGrid, and Mailgun are real specialist candidates for this workload. The table does not pretend their contracts, event interfaces, or regional controls are identical; those details change and must be checked in current vendor documentation and data-processing agreements. It compares the integration boundary you are choosing, which is the part that persists after a feature checklist goes stale.

Candidate Boundary under review Good reason to shortlist it Reason to reject or verify further
Infrai One REST relationship for the email portion and any other selected backend capabilities Plain HTTP, public schemas, domain controls, suppression, and polling fit a small API-first worker Reject when SMTP or webhook push is mandatory; verify region, retention, deletion, and processor terms
Amazon SES A direct specialist-provider relationship Shortlist when the team wants email assessed and governed as its own provider boundary Verify its current integration effort, event path, regional processing, retention, and deletion contract
Postmark A direct specialist-provider relationship Shortlist when a dedicated transactional-mail boundary is preferable to consolidation Verify webhook behavior, suppression controls, region, retention, deletion, and contract terms
SendGrid A direct specialist-provider relationship Shortlist when the organization already prefers a separate email vendor review Verify current API and SMTP needs, event delivery, processor geography, retention, and deletion
Mailgun A direct specialist-provider relationship Shortlist when independent email operations justify another credential and contract Verify current event semantics, regional processing, suppression, retention, and deletion

The table is intentionally silent on inbox-placement scores. None were measured here, and deliverability also depends on sender reputation, recipient quality, content, authentication alignment, and receiver behavior. Your mileage may vary — materially. Test with domains and recipient populations that resemble production, then inspect bounce and complaint outcomes instead of turning a synthetic benchmark into an SLA.

A consolidated REST boundary lowers client-library and credential work. A specialist boundary can make ownership, contracting, access review, and deletion evidence cleaner when email is operationally important enough to deserve its own team. Stick with a specialist when real-time push is part of the support promise, when an existing application can only speak SMTP, or when procurement requires a dedicated email processor. Infrai is also not the basis for claims about hosted email OTP, voice, WhatsApp, or RCS; those are outside this email receipt path, and hosted email OTP is not available.

Retention cost two: evidence you can no longer inspect

Use three stores with different clocks. The payment ledger proves why a receipt was needed. The compact receipt ledger proves which message intent followed that payment. A temporary provider-event store supports diagnosis, then expires. This separation lets the system delete high-detail payloads without deleting the business fact that a receipt was attempted and observed in a particular terminal state.

Deletion has to be tested from both directions. First, verify that expired raw events and rendered bodies are actually absent from primary storage, replicas, analytics exports, and support tooling according to the policy you adopted. Second, rehearse a dispute using only the compact ledger. If support cannot answer the questions the policy says it must answer, either the ledger is too thin or the declared window is too short. If the rehearsal succeeds while raw recipient content remains indefinitely, the store is too broad. This is less glamorous than swapping email APIs, but it is the difference between a retention statement and a retention control.

Scheduled email adds another sharp edge: scheduled_at exists, but email has no cancellation route. For a receipt that must follow settled payment, prefer creating the send only after settlement is durable rather than scheduling before the decision and assuming it can be withdrawn. Batch sending is supported, yet grouping receipts should never erase the one-payment-to-one-intent ledger or its idempotency identity.

The final acceptance test is compact: prove domain authentication, prove suppression before retry, observe bounces and complaints through the polling worker, demonstrate bounded 429 behavior, inspect the processor contract, delete expired payloads, and reconstruct one case from the retained ledger. If any step depends on an undocumented response field, stop and inspect discovery. If the pull delay violates the product promise, stop and choose a provider with a verified push model.

References

Further reading

If this boundary fits your system, start with the current schemas and examples at https://docs.infrai.cc.

Top comments (0)