Node SDK, CLI & local MCP
The TypeScript SDK mirrors the REST API across projects, keys, domains, transactional email, templates, marketing, automations, receiving, suppressions, and webhooks. Existing new NoticeAPI(key) calls remain valid; project-aware apps add one optional configuration field.
npm install noticeapi
Project-aware client
import { NoticeAPI } from "noticeapi";
const notice = new NoticeAPI(process.env.NOTICEAPI_API_KEY, {
projectId: process.env.NOTICEAPI_PROJECT_ID,
});
const { id } = await notice.emails.send(
{
from: "Acme <[email protected]>",
to: "[email protected]",
subject: "Receipt",
html: "<p>Thanks!</p>",
},
{ idempotencyKey: "receipt-" + orderId },
);
const email = await notice.emails.get(id);Project-bound keys do not need projectId. Workspace keys set it once in the client, override it on an individual send request, or create a lightweight forProject() view.
const { projects } = await notice.projects.list();
const clientSite = notice.forProject(projects[0].id);
await clientSite.templates.list();
await clientSite.domains.create("send.client.com");
await clientSite.webhooks.create({ url: "https://client.com/api/email-events" });Render React Email locally
Install @react-email/render and React, then import the optional noticeapi/react entry. It returns HTML and a text alternative in your runtime; the send API receives only those strings. This optional entry requires Node 20 because the upstream renderer requires Node 20. The core SDK remains Node 18+.
import { renderEmail } from "noticeapi/react";
import { ReceiptEmail } from "./emails/receipt";
// Rendered here, in your app. NoticeAPI never executes the component.
const { html, text } = await renderEmail(<ReceiptEmail order={order} />);
await notice.emails.send({
from: "Acme <[email protected]>",
to: order.customerEmail,
subject: "Receipt " + order.number,
html,
text,
});Initialize projects and sync templates
The CLI writes .noticeapi.json with non-secret project configuration and safely adds or updates NOTICEAPI_API_KEY and NOTICEAPI_PROJECT_ID in the chosen env file. Template pull uses readable, ID-stable filenames so same-named templates cannot overwrite one another; push skips unchanged templates by fingerprint.
npx noticeapi init npx noticeapi projects list npx noticeapi templates pull npx noticeapi templates push
Local MCP server
The package includes the same tool catalog used by hosted MCP, exposed over stdio for local agent hosts.
NOTICEAPI_API_KEY=ntc_... NOTICEAPI_PROJECT_ID=project_123 \ npx -y -p noticeapi noticeapi-mcp
Stable errors
Non-2xx responses throw NoticeAPIError with HTTP status and a machine-readable code. Permission, project, domain, and policy boundaries should stop an agent instead of being retried.
import { NoticeAPIError } from "noticeapi";
try {
await notice.emails.send({ /* ... */ });
} catch (error) {
if (error instanceof NoticeAPIError) {
error.status; // 403
error.code; // "project_required" | "recipient_suppressed" | ...
}
}See the MCP setup, agent operating guide, and OpenAPI 3.1 contract.