Novu Node.js SDK (@novu/node)

A typed Node.js client that wraps Novu's multi-channel notification API into a single object-oriented SDK for triggering events.

SDK
npm
v2.6.6
39,858stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
93/100Excellent
Development Activity100
Maintenance100
Community76
Maturity56
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture78
Code Quality82
Innovation45
Learning Curve85

@novu/node is the original server-side JavaScript/TypeScript client for Novu, an open-source notification infrastructure platform that unifies email, SMS, push, chat, and in-app messaging behind one trigger API. The SDK exposes a single Novu class whose properties (subscribers, events, topics, integrations, messages, tenants, and a dozen more) map one-to-one onto Novu’s REST resources, so calling novu.trigger('workflow-id', { to, payload }) sends a single authenticated request that Novu’s backend fans out across whichever channels a workflow defines.

Novu deprecated @novu/node on March 20, 2025, directing users toward the newer @novu/api package for most JavaScript runtimes, so it is documented here as a legacy but still-installed dependency (44k+ weekly downloads at time of writing) rather than an actively recommended entry point.

What You Get

  • A single Novu client instantiated with a secret key (or NOVU_SECRET_KEY/NOVU_API_KEY env vars) that authenticates every request with an ApiKey header
  • Resource objects for every Novu concept — subscribers, events, topics, integrations, messages, tenants, environments, feeds, layouts, notification groups/templates, execution details, inbound parse, organizations, and workflow overrides
  • trigger, bulkTrigger, broadcast, and cancel methods on events for firing single, batched, org-wide, or in-flight-cancelled notification workflows
  • Built-in retry support via axios-retry, including automatic idempotency-key injection on POST/PATCH so a retried write is never double-applied
  • Full TypeScript typings for every payload and response shape, re-exported alongside shared enums (ChannelTypeEnum, EmailProviderIdEnum, etc.) from the @novu/shared package

Common Use Cases

  • Triggering a transactional workflow (e.g. “password-reset” or “order-shipped”) from a backend API route, letting Novu fan the message out across email/SMS/push based on subscriber preferences
  • Identifying and bulk-creating subscriber records (with channel credentials like device tokens or chat webhook URLs) as part of a user-signup or onboarding flow
  • Broadcasting an announcement to every subscriber in an environment without enumerating recipients individually
  • Managing topics for group-based notification targeting, and querying execution-details/messages endpoints to debug why a specific notification did or didn’t deliver

Under The Hood

Architecture The package is a thin, mechanically consistent facade over Novu’s REST API: a single Novu class (src/lib/novu.ts) builds one shared axios instance carrying the ApiKey auth header and the resolved backend URL, then hands that instance to roughly sixteen resource classes (Subscribers, Events, Topics, Integrations, Messages, Tenants, Environments, Feeds, Layouts, NotificationGroups, NotificationTemplates, ExecutionDetails, InboundParse, Organizations, WorkflowOverrides, Changes), each extending a minimal WithHttp base and implementing one REST resource’s CRUD-shaped methods (list, get, identify, update, trigger, etc.). There is no dependency-injection container, no layering beyond “client -> resource -> http call” — the entire class graph mirrors the API’s URL structure directly, so a change to the shared http client contract (auth, retry, base URL) is the one thing every resource module depends on; changes to one resource never ripple into another.

Tech Stack Written in TypeScript, compiled to dual CommonJS (build/main) and ES module (build/module) outputs via tsc. HTTP transport is axios, wrapped by axios-retry for configurable exponential backoff and idempotency-key handling on non-idempotent methods; handlebars, lodash.get/lodash.merge, and uuid round out the small dependency footprint, alongside a workspace dependency on @novu/shared for the enum/interface definitions shared across Novu’s entire monorepo (CLI, framework, react, dashboard). The Novu class extends Node’s built-in EventEmitter, though the visible surface area doesn’t emit custom events beyond exposing trigger/bulkTrigger/broadcast as bound instance methods.

Code Quality Every resource module ships beside a matching *.spec.ts file (roughly 2,800 lines of Jest specs across ~16 files) that mocks axios wholesale and asserts on the exact request shape (toHaveBeenCalledWith), giving strong contract-level coverage of what each SDK call actually sends over the wire even though it never talks to a live server. Each resource also has a dedicated .interface.ts defining its request/response types, so the public API is fully typed rather than any-typed. ESLint and Prettier are configured at the package level (lint, lint:fix, test:prettier scripts), and the surrounding monorepo runs CodeQL and PR-gating workflows, though there is no package-local CI config to inspect in isolation.

What Makes It Unique There is little architectural novelty here by design — it is a straightforward, one-class-per-REST-resource SDK, the same shape as most hand-written API wrappers. What is notable is Novu’s decision to formally deprecate it in favor of @novu/api rather than silently letting it rot: the npm registry carries an explicit end-of-support notice pointing integrators at the replacement package and migration docs, which is a healthier signal than most abandoned SDKs give.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search