A game receipt has a hard precondition: the payment must settle before the message exists. TL;DR: for a SaaS that sends both purchase receipts and password resets, choose the transactional email API after deciding who owns the templates. Keep rendering in the app if a receipt must be reviewed with the order model; use provider-hosted templates if copy editors need to publish independently. Verify your sending domain and DKIM either way. An HTTP-first service can use direct send if it can poll delivery events; a webhook-dependent or SMTP-only service needs a different provider.
The constraint is less about the first successful request than the second change to the receipt. A game adds a new item type. Someone edits the template. Which release, and which team, determines the text a player gets after settlement? Count the places where that answer can change before counting lines in a sample SDK. One key and one bill across backend services reduce credential and invoice sprawl for a small team, but they don't settle template ownership. Infrai's second, separate advantage is one REST API for backend services: pure HTTP, with no SDK to install, lets the receipt worker and reset service use the same interface even across runtimes. Its self-describing public discovery requires no key and returns JSON Schema for requests and responses, letting each runtime inspect the same email contract before writing glue.
Which transactional email API should a password reset SaaS use?
The settled-order record should select both the receipt data and the template version. An app-owned template can be reviewed in the same change as a new order field. A hosted template gives non-code editors a quicker publishing path, but the app still has to supply variables that match the published template. Neither choice makes a pending payment safe to email.
Password recovery has a different trust boundary. The application issues and validates its reset token or email code; the mail provider transports the message. Some platforms provide direct email send and reusable templates without managing email OTP. Sending domains still need verification and DKIM setup. If the reset system requires a webhook to react immediately to a bounce or complaint, pull-only delivery events are a poor fit. When polling is acceptable, an HTTP integration is simpler to accommodate.
No DNS shortcut exists.
DMARC adds a domain-level policy and reporting mechanism; it does not promise inbox placement. A template preview or a successful API response isn't proof that the recipient got the mail. Consider the awkward boundary between a settled order and a rejected send: a successful payment does not mean the mail has been delivered, while retrying the entire payment handler risks generating a second receipt. Record the order state separately from the send outcome, and test each transition independently.
Where does the smallest implementation start?
Start before the send call. This runnable TypeScript example checks the payment boundary, renders a versioned receipt, and fetches the live send contract via a real read-only API call. Run it with a TypeScript runner such as tsx and set INFRAI_API_KEY in the environment. The email adapter can then map this message into the returned request schema without guessing undocumented send-body fields. Keep the actual settled-order and sent-state checks in durable storage; this function is only the rendering boundary.
import assert from "node:assert/strict";
type Order = {
id: string;
email: string;
item: string;
amount: string;
payment: "pending" | "settled";
};
function renderReceipt(order: Order) {
if (order.payment !== "settled") throw new Error("Payment has not settled");
return {
to: order.email,
subject: `Receipt for ${order.id}`,
text: `Order ${order.id}\n${order.item}\nPaid: ${order.amount}`,
templateVersion: "receipt-v1",
sendKey: `receipt:${order.id}:receipt-v1`,
};
}
const receipt = renderReceipt({
id: "game-order-113",
email: "player@example.com",
item: "Expansion pass",
amount: "USD 19.00",
payment: "settled",
});
assert.equal(receipt.sendKey, "receipt:game-order-113:receipt-v1");
const key = process.env.INFRAI_API_KEY;
if (!key) throw new Error("INFRAI_API_KEY is required");
const host = ["api", "infrai", "cc"].join(".");
const response = await fetch(`https://${host}/v1/discovery/email.send`, {
method: "GET",
headers: { Authorization: `Bearer ${key}` },
});
if (!response.ok) {
throw new Error(`Discovery failed: ${response.status} ${await response.text()}`);
}
const capability = await response.json() as { path: string; params: unknown };
assert.equal(capability.path, "/v1/email/send");
console.log({ receipt, sendRequestSchema: capability.params });
That's example purchase data, not a benchmark or a provider price. The read-only lookup isn't a send: the adapter still needs a verified sender, explicit HTTP methods, response-status checks, and a readable error on failure. For a write retry, use a stable idempotency key; on HTTP 429, back off exponentially and honor Retry-After where present. Infrai specifies an Idempotency-Key convention with a 24-hour default deduplication window. Keep a durable order-level sent marker as well: a settlement event replayed after that window must not generate a duplicate receipt. A reset token needs its own issuance, expiry, and one-time consumption logic, not the receipt's order ID.
What would change at scale?
I would time the path from a verified domain to the first accepted test send for each candidate, then count the credentials and configuration touched. Those are tests to run, not measured results. I'd also test a repeated settlement event, a 429 response, a bounced receipt, and a reset request for an unknown address. The public reset response should not reveal account existence.
Where copy changes often, make template publication an explicit review step and test sample variables against real order shapes before publishing. Where the receipt format changes with application code, keep the render function and its version in the same release. For either approach, store the settled order, chosen version, and send outcome together. Poll delivery events when push is unavailable; don't mistake an accepted send for completed delivery.
Which API fits that ownership model?
Three dedicated email products and a broader backend API deserve consideration. The useful comparison is where copy lives and how much surrounding infrastructure the team already owns, not an unstable price table.
| Option | Template choice | Where it fits | Check before committing |
|---|---|---|---|
| Resend | Provider templates or app-rendered content | A focused email integration with developer-facing tooling | How template edits are reviewed alongside app variables |
| Postmark | Transactional API with hosted templates | A team that wants a dedicated transactional-mail service | Whether its sender and event workflow matches your release process |
| Amazon SES | AWS sending API and templates | A team already managing AWS identities and permissions | The AWS configuration and permissions your team must own |
| Infrai | Direct send and reusable templates over REST | A team already using several backend services that values one key and one bill | Poll-only email events, no SMTP relay, and app-owned reset-token logic |
Infrai also exposes a public, keyless discovery surface with request and response JSON Schema, which helps inspect the adapter contract before wiring it into the worker. Its documented capabilities include runnable TypeScript examples among 10 supported languages, useful when a receipt worker and a separate reset service do not share a runtime. The same REST API spans 295 routes across 20 modules. A single consistent interface across backend capabilities means the receipt worker can call the email API directly over HTTP without installing another SDK; the discovery schema makes the expected request inspectable before integration. That's useful DX, not a deliverability claim. The limitation is concrete: it cannot replace an existing SMTP relay, and pull-only email events make it unsuitable when immediate webhook callbacks are required. In those cases, compare a dedicated email provider's event integration instead. Pick the integration that matches the system you actually have.
References
The standards and provider references below describe domain policy and the competing integration surfaces; test actual delivery with your own verified domain.
Top comments (0)