SendDart in Express: Design Routes, Errors and Webhook Middleware

SendDart in Express: Design Routes, Errors and Webhook Middleware

Integrate SendDart with Express using authorized routes, explicit SDK error translation and raw-body webhook verification without global parsing conflicts.

SendDart Team

TL;DR

  • Design Express routes as narrow business actions, record notification intent, and avoid sending before commit so delivery reflects completed state rather than becoming a general mail relay.
  • Validate and authorize request fields, keep provider secrets out of user input, and translate SDK results into application errors to decide accept/reject outcomes rather than relying on Express error middleware.
  • Scope raw-body parsing for webhooks, persist callbacks before slow side effects, and test deployment behavior so one authorized event yields a single, coherent notification history.

Keep the route focused on a business request

An Express route that accepts arbitrary recipient, sender, subject and HTML fields can accidentally become a general mail relay. A safer integration exposes a specific application action: send an account invitation, request a reset or notify an order owner. The route authenticates the caller and derives the allowed message from business data.

This keeps policy near the entry point while allowing a shared worker to handle delivery. The route records notification intent and returns a result that describes what was retained. It does not need to know every detail of the provider's event model.

Express gives applications flexibility in middleware and routing, which makes the order and scope of those components important. Design the email routes and webhook route explicitly rather than attaching a provider client to a broad catch-all endpoint.

Validate and authorize before enqueueing

Validate the fields the user is allowed to supply, then load the relevant account or organization under the current user's scope. An authenticated user is not automatically allowed to send on behalf of every tenant.

Derive the From address and template from trusted configuration. Keep the provider API key and endpoint outside request-controlled input. A contact form should not be able to change the destination service or attach a private internal URL for the server to fetch.

Apply application-level abuse controls to public actions. Provider rate limits protect the service boundary but do not define how often one user may request a reset or invite a teammate. Record a clear outcome when a request is rejected before notification creation.

Translate SDK results into application errors

SendDart's Node.js SDK uses a data/error result for API responses. Inspect the result explicitly and decide whether the notification is accepted, rejected or requires reconciliation. Do not rely on Express error middleware to detect an API error that was returned as ordinary data. SendDart Node.js SDK.

Keep unexpected programming exceptions separate from documented provider rejections. Express has defined error-handling behavior that depends on the framework version and route style; follow the official guidance for propagating asynchronous failures in your application. Express error handling.

The browser response should contain a safe explanation and a support reference where useful, not raw headers, credentials or confidential message content. Operators can receive structured diagnostics through restricted logs and the notification record.

Related reading: Best Email API: Choose With a Production Acceptance Test.

Avoid a send inside an unfinished transaction

If the route is creating an account or order, do not send a final confirmation before the database transaction commits. A later rollback would leave the customer with a message describing an action that did not complete.

Record an outbox or notification intent with the business change and let a worker claim it after commit. The worker should load the immutable message inputs and preserve one operation identity. This also prevents a slow provider call from holding database locks unnecessarily.

For a small synchronous workflow, be explicit about the tradeoff and still retain the operation before submission. A response timeout does not mean the service rejected the message, so recovery cannot simply repeat the route with a new key.

Scope raw-body parsing to the webhook

Webhook signature verification may require the original bytes. SendDart documents verification against the raw body. If a global JSON middleware parses and replaces the body before the webhook handler receives it, the verification path can fail or become incorrectly implemented.

Plan middleware ordering so the webhook route receives the required raw payload under a bounded size limit. After authentication, parse and validate the event. Keep ordinary application routes on their appropriate parsing path rather than weakening all request handling for one callback.

Test the exact deployed middleware stack. A unit test that calls the verifier directly can pass while the real route fails because earlier middleware altered the body. Include a signed fixture sent through the actual HTTP route in the integration suite.

Persist callbacks before slow side effects

Store authenticated event evidence with a unique identity and correlate it to the provider message record. Duplicate deliveries should resolve to the same observation. If the database cannot retain the event, respond according to the provider's retry contract rather than falsely acknowledging processing.

Move slow work into bounded workers after persistence. Updating several analytics systems or downloading attachments in the webhook request can make the endpoint fragile. The public route should establish authenticity and durable receipt, not complete every possible consequence before responding.

Use stored tenant ownership during correlation. An event that cannot yet be matched should enter a controlled reconciliation path, not update the first customer record with a matching email address.

Give the worker a safe shutdown story

An Express process may host both HTTP routes and background work, or the worker may run separately. In either case, deployments and shutdowns can interrupt sends. Stop claiming new jobs when shutting down and preserve evidence for any operation already in progress.

A lease expiry should not automatically reset an uncertain send to untouched work. Retain the original key and provider ID where available. The next worker needs to know whether to retry, retrieve evidence or stop for review.

Test duplicate HTTP submissions, middleware verification, worker interruption and a late callback. Confirm that one authorized business event produces one intended notification and a coherent history.

The result is an Express integration with narrow routes and explicit boundaries. Authentication, parsing, error translation and durable work each have a clear job, making both normal operation and failure diagnosis easier.

Related reading: Email Verification APIs: Compare Results, Uncertainty and Integration.