React Email + NoticeAPI

Keep the email in React.
Send the rendered output.

Render the component in your Node runtime, then send the resulting HTML and text through one project-aware client. NoticeAPI never imports or executes your component.

The optional noticeapi/react entry needs Node 20 because its upstream renderer does. The core NoticeAPI SDK remains Node 18+.

receipt.tsxOne explicit runtime boundaryLocal render
  1. 01SourceReceiptEmail.tsxComponent + typed props
  2. 02Your runtimerenderEmail()Runs locally on Node 20
  3. 03Output{ html, text }Plain message strings
  4. 04Deliveryemails.send()NoticeAPI accepts the send
Only the compiled HTML and text cross into NoticeAPI.
LocalComponent execution
Node 20Optional render helper
Node 18+Core SDK client
HTML + textDefault render output
A deliberate boundary

Your application renders it.
NoticeAPI delivers it.

The integration is a small handoff between code you own and an email record you can inspect.

01
Author

Keep the component in source control

Own the JSX, props, preview workflow, tests, and review history in the application that already knows the data.

02
Render

Execute React in your runtime

The optional noticeapi/react entry calls the upstream renderer locally and returns HTML plus a text alternative by default.

03
Send

Pass strings across the boundary

NoticeAPI receives the sender, recipient, subject, HTML, and text. It never imports or executes your component.

04
Read

Follow the stored delivery record

The send returns an email id. Fetch it for status and recipient events, or configure signed delivery webhooks.

One local render, one normal send

The integration is smaller than it sounds.

Install the SDK, React, and the upstream renderer. The optional helper turns the component into both message bodies before the send begins.

send-receipt.tsxTypeScript
import { NoticeAPI } from "noticeapi";
import { renderEmail } from "noticeapi/react";
import { ReceiptEmail } from "./emails/receipt";

const notice = new NoticeAPI(
  process.env.NOTICEAPI_API_KEY!,
  { projectId: process.env.NOTICEAPI_PROJECT_ID },
);

const { html, text } = await renderEmail(
  <ReceiptEmail order={order} />,
);

const { id } = await notice.emails.send(
  {
    from: "Acme <[email protected]>",
    to: order.customerEmail,
    subject: `Receipt ${order.number}`,
    html,
    text,
  },
  { idempotencyKey: `receipt-${order.id}` },
);

const email = await notice.emails.get(id);
Clear ownership

No remote React runtime hiding in the send path.

Keep code execution with your application. Give NoticeAPI the finished message and responsibility for the delivery workflow.

Before the handoff

Your application owns

  • React components and typed props
  • Preview, test, and review workflow
  • The Node runtime that executes rendering
  • Application data and content decisions
After the handoff

NoticeAPI owns

  • Project and sender authorization
  • Verified-domain and provider delivery
  • Suppression checks and stored message record
  • Recipient events and optional signed webhooks
Delivery you can read back

The component becomes an observable email.

Rendering ends before the network request. From that point on, use the same send result, stored record, and supported delivery events as any other NoticeAPI message.

The send returns an id

emails.send() resolves with the NoticeAPI email id, provider, and provider message id when one is available.

The record stays queryable

emails.get(id) returns the stored sender, recipients, subject, delivery status, and time-ordered recipient events.

Webhooks remain optional

Configure an HTTPS endpoint when your app should receive supported delivery events without polling, and verify every HMAC signature.

emails.get(id)JSON
{
  "id": "em_01J...",
  "status": "sent",
  "deliveryStatus": "delivered",
  "events": [
    {
      "type": "delivered",
      "recipient": "[email protected]",
      "detail": "Mailbox accepted the message.",
      "at": "2026-07-24T15:04:05.000Z"
    }
  ]
}
Choose where content lives

Three valid template paths. One send API.

React Email is the code-owned path. Direct rendering and stored NoticeAPI templates remain first-class when they better match the team editing the message.

Recommended helper

Use noticeapi/react

renderEmail() returns HTML and generates a text alternative by default. Set plainText: false only when you intentionally want HTML alone.

import { renderEmail } from "noticeapi/react"
Existing renderer

Keep @react-email/render

Already render React Email yourself? Keep that implementation and pass the resulting HTML and text strings to the normal send method.

import { render } from "@react-email/render"
Content-managed path

Use a stored template

Choose NoticeAPI templates when content should be managed outside the codebase and sent later by template id with merge variables.

templateId: "tpl_receipt"
Keep your rendering workflow

Send the first compiled message.

Render the component locally, pass the HTML and text to one project-scoped client, and keep the resulting email id.