Custom Password Reset API Selection for Auth Systems Without Webhooks
The most important trade-off is evidence versus coupling: for password recovery and settled-order receipts, choose an email API that lets your application record a durable submission result and later reconcile delivery events without making either workflow depend on a provider-specific webhook. Short answer: put an outbox between the business event and the email API, assign your own stable…
The crux of the decision is balancing evidence reliability against tight coupling to a specific email service. By introducing an intermediary outbox layer, your application can record a durable submission result while maintaining flexibility. Store a unique message key, capture the remote message identifier, and periodically poll for unresolved messages.
For password resets, the proof needed is the reset request and token expiration. For order receipts, it's the immutable payment reference. Avoid storing raw reset tokens in logs. Only log the status code, response time, provider message ID, and a hash of the message content.
The API should give you a stable message identifier and allow querying message events. A polling design works best here. If you can only push events or manually search a dashboard, the compliance record will be incomplete without webhooks.
Model the data flow in your code: when payment settles or an auth request occurs, write an outbox row in the same transaction. A worker will claim the row, render a versioned template, submit through a narrow transport interface, and store the result. A separate reconciler will then poll only the submitted rows with open outcomes.
Define constants for message purpose (password_reset, order_receipt) and delivery states (submitted, delivered, delayed, bounced, unknown). Create interfaces for OutboundMessage, SubmissionEvidence, DeliveryObservation, and EmailTransport.
Implement a function to submit messages. Check if the message has expired and throw an error if so. Use an HTTP POST request with an idempotency key derived from the message key. If the response is not successful, throw an error with the status. Parse the JSON response and store the id.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.