Notix as a NestJS provider.
In NestJS the client belongs in a provider, so every module that sends gets the same instance through dependency injection and tests can swap it out. The send is a method on a small service; the webhook controller needs Nest's raw body option to verify signatures.
Send an email from NestJS.
import { Injectable } from "@nestjs/common";
import { Notix } from "notix-js";
@Injectable()
export class MailService {
private readonly notix = new Notix(process.env.NOTIX_API_KEY!);
async sendReceipt(to: string, orderId: string) {
const { data, error } = await this.notix.emails.send(
{ from: "Acme <receipts@acme.com>", to, subject: "Your receipt", html: "<p>Thanks.</p>" },
{ idempotencyKey: `order-${orderId}-receipt` },
);
if (error) throw new Error(error.message);
return data?.emailId;
}
}
The from address must be on a domain you have verified in Notix. Step by step: the Node.js quickstart and the longer guide to sending email from NestJS.
One API key, kept on the server.
Create an API key on the API keys page of the Notix console and store it as NOTIX_API_KEY in the environment, read through @nestjs/config if you use it. Read it only in code that runs on the server, never in anything shipped to a browser.
A Send only key is enough for code that only sends: if it leaks, it cannot read your contacts or delete a domain.
NOTIX_API_KEY=notix_xxxxxxxxxxxx
NOTIX_WEBHOOK_SECRET=whsec_xxxxxxxxxxxx
Verify delivery events over the raw body.
Notix signs every webhook call with the webhook's signing secret: an HMAC-SHA256 of the X-Notix-Timestamp header, a dot and the raw body, sent in X-Notix-Signature. The SDKs check the signature and refuse a call more than 5 minutes old.
Nest parses JSON bodies by default. Create the app with rawBody: true and read req.rawBody in the webhook controller.
import { Controller, HttpCode, Post, Req, BadRequestException, type RawBodyRequest } from "@nestjs/common";
import type { Request } from "express";
import { Notix } from "notix-js";
const webhooks = new Notix(process.env.NOTIX_API_KEY!).webhooks(process.env.NOTIX_WEBHOOK_SECRET!);
@Controller("webhooks/notix")
export class NotixWebhookController {
@Post()
@HttpCode(200)
receive(@Req() req: RawBodyRequest<Request>) {
try {
const event = webhooks.constructEvent(req.rawBody!.toString("utf8"), { headers: req.headers });
return { received: event.type };
} catch {
throw new BadRequestException("invalid signature");
}
}
}
Questions, answered.
Where should the Notix client live in a NestJS app?
What if the same request runs twice?
Why is my send refused with a from-address error?
Keep reading.
Send email from NestJS
A provider wrapping notix-js, a controller that sends, a raw-body webhook controller, and configuration through ConfigService.
DocsNode.js
Send an email from Node.js with the notix-js SDK.
IntegrationsIntegrations
Notix inside the frameworks, platforms and AI coding tools you already use, from Next.js and Laravel to Supabase, Vercel and Cursor.
ProductEmail API
One JSON API for transactional and marketing email: send, batch, schedule, webhooks, typed SDKs.
NotixPricing
A free plan with no card, and Pro at $15 a month for 50,000 emails. Only sent volume is metered.
Send your first email in five minutes.
Verify a domain, copy an API key, make one call. The free plan does not ask for a card.