Jesse A. Green / notebook

Novu User Guide

Generated June 2026 from novuhq/novu at b6ab172

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Novu is the open-source communication infrastructure for products and AI agents. It gives you one API and one unified conversation model to reach your users on every channel they live on — an embeddable in-app Inbox, Email, SMS, Push, and Chat (Slack, Microsoft Teams, Telegram, WhatsApp, Discord, and more).

Instead of integrating a separate provider for every channel, writing your own notification feed, and maintaining a webhook handler per platform, you integrate Novu once. You define workflows (the logic and templates behind a kind of notification), trigger them with a single API call, and Novu routes each message to the right channel for each user — with batching (digest), delays, scheduling, per-user preferences, and a real-time <Inbox /> component out of the box.

This guide covers everything you need to use Novu as a developer: getting started on Novu Cloud or self-hosted, sending your first notification, building workflows in code, embedding the Inbox, connecting agents, configuring providers, and troubleshooting. For deployment, architecture, configuration internals, and security hardening, see the companion Novu Admin Guide.

Note

Novu is distributed as a monorepo of apps (API, worker, websocket service, dashboard) and npm packages (@novu/js, @novu/react, @novu/nextjs, @novu/react-native, @novu/framework, @novu/api, and the novu CLI). This guide documents the open-source platform at commit b6ab172. The always-current API reference and channel-specific guides live at docs.novu.co.


Table of Contents

  1. Quick Start
  2. Core Concepts
  3. Installation & Setup
  4. Sending Your First Notification
  5. Building Workflows in Code (@novu/framework)
  6. The novu CLI Reference
  7. Embedding the Inbox
  8. Subscribers & Preferences
  9. Digest, Delay & Scheduling
  10. Channels & Providers
  11. Agent Communication Infrastructure (ACI)
  12. Translations & Layouts
  13. Environments & Promotion
  14. Common Tasks (Recipes)
  15. Troubleshooting
  16. FAQ
  17. Reference

1. Quick Start

There are two ways to run Novu, and the developer experience is the same for both:

  • Novu Cloud — a hosted account at dashboard.novu.co. Fastest way to start; nothing to deploy.
  • Self-hosted — run the full stack with Docker on your own infrastructure (see Installation & Setup and the Admin Guide).

1.1 The fastest path: scaffold a starter app

If you have Node.js installed, you can scaffold a working Novu app — including a Next.js page, a workflow, and an embedded Inbox — with one command:

npx novu@latest init

This walks you through creating an account (or signing in), generates a project from a template, and prints the next steps. Then start the local Dev Studio so notifications you trigger locally show up instantly:

npx novu@latest dev --port 4000
✔ Novu Dev Studio running
  Local Bridge tunnel established
  Studio: http://localhost:2022

Tip

The npx novu@latest dev command opens a local Bridge tunnel and a Studio UI so you can build and test workflows on your machine before promoting them to your cloud or self-hosted environment. Pass --no-studio to skip the UI, or --headless to avoid opening a browser.

1.2 The three things every Novu app does

Every Novu integration boils down to three steps:

  1. Define a workflow — the container for a notification's steps and templates (in the dashboard's no-code editor, or in code with @novu/framework).
  2. Trigger the workflow — make one API call (POST /v1/events/trigger) from your backend with a workflowId, a to subscriber, and a payload.
  3. Deliver & display — Novu runs the workflow, sends each channel's message through the configured provider, and (for in-app) streams it to the <Inbox /> component in real time.
your backend ──trigger──▶ Novu API ──▶ workflow engine ──▶ Email provider
                                                        ├──▶ SMS provider
                                                        ├──▶ Push provider
                                                        ├──▶ Chat provider
                                                        └──▶ In-App Inbox (websocket ▶ <Inbox/>)

Important

A notification is never sent directly to a channel. It is always sent by triggering a workflow, which decides which channels fire, in what order, and under what conditions. This indirection is what lets you change delivery logic without redeploying your app.


2. Core Concepts

Understanding these six concepts is enough to use everything in Novu.

Concept What it is
Workflow A blueprint for a kind of notification. Has a unique trigger identifier (workflowId), a name, and an ordered list of steps.
Trigger The event that starts a workflow — a call to the Novu API with a workflowId, a recipient, and a payload of data.
Step A single action in a workflow: a channel step (email, sms, push, chat, inApp) or a flow-control step (digest, delay, custom).
Subscriber A recipient of notifications, identified by your own subscriberId. Holds channel credentials (email, phone, device tokens) and preferences.
Channel A delivery medium: In-App (Inbox), Email, SMS, Push, or Chat.
Provider The concrete service that delivers a channel's message — e.g. SendGrid or Resend for Email, Twilio for SMS, FCM for Push, Slack for Chat.

Note

A subscriber is your user as Novu sees them. You usually create or update subscribers on the fly when you trigger a workflow (Novu upserts them), or sync them ahead of time. The subscriberId is the stable key you control — use your own user ID.

2.1 The unified conversation model

Beyond one-way notifications, Novu models conversations: inbound messages from a channel (a Slack reply, an email response, a Telegram message) are normalized into one consistent shape and can be routed back to your code or to an agent. This is the foundation of both the product notification features and the Agent Communication Infrastructure (see Section 11).


3. Installation & Setup

3.1 Choosing how to run Novu

Novu Cloud (hosted)

  1. Create a free account at dashboard.novu.co.
  2. Copy your Secret Key (a.k.a. API key) and Application Identifier from Settings → API Keys.
  3. Use https://api.novu.co as your API base URL (or https://eu.api.novu.co for the EU region).

Self-hosted (Docker)

Run the one-line community installer on a host with Docker, curl, and openssl:

curl -fsSL https://raw.githubusercontent.com/novuhq/novu/next/docker/community/setup.sh | bash

The script downloads docker-compose.yml and .env.example, generates secure random secrets, and starts the stack:

▸ Novu is running:
  Dashboard : http://localhost:4000
  API       : http://localhost:3000
  WebSocket : http://localhost:3002

See the Admin Guide for production hardening, full environment-variable reference, and scaling.

Warning

The Secret Key is a server-side credential. Never ship it to the browser or commit it to source control. The browser only ever needs your Application Identifier (a public value) and the subscriber's identity.

3.2 Installing the SDKs

Install only the packages you need:

Package Use it for Install
@novu/api Server-side: trigger workflows, manage subscribers, topics, integrations npm i @novu/api
@novu/react React apps: the <Inbox /> component and hooks npm i @novu/react
@novu/nextjs Next.js apps: SSR-friendly Inbox wrapper npm i @novu/nextjs
@novu/js Framework-agnostic browser/JS client for the Inbox npm i @novu/js
@novu/react-native React Native apps: notification hooks npm i @novu/react-native
@novu/framework Code-first workflow definitions served from your app npm i @novu/framework
novu (CLI) Scaffolding, local dev, sync, agent connect npx novu@latest <command>

Tip

Requirements: Node.js 22 is required to build or self-host the platform itself ("node": ">=22 <23"). The published client SDKs support current LTS Node and modern browsers; React packages target React 19.


4. Sending Your First Notification

After you have a workflow with a trigger identifier (create one in the dashboard, or in code — see Section 5), trigger it from your backend.

4.1 Trigger with the server SDK

import { Novu } from '@novu/api';

const novu = new Novu({ secretKey: process.env.NOVU_SECRET_KEY });

await novu.trigger({
  workflowId: 'welcome-onboarding-email',
  to: {
    subscriberId: 'user_123',
    email: '[email removed]',
  },
  payload: {
    firstName: 'Jane',
    organizationName: 'Acme',
  },
});
{ acknowledged: true, status: 'processed', transactionId: '...' }
  • workflowId — the workflow's trigger identifier.
  • to — the recipient. Pass a subscriberId (Novu upserts the subscriber) plus any channel credentials it needs (email, phone, etc.). You can also pass an array to trigger many recipients, or a topic key for broadcast.
  • payload — arbitrary JSON your templates reference (e.g. {{firstName}}).

4.2 Trigger with a raw HTTP request

The SDK is a thin wrapper over the REST API. Any HTTP client works:

curl -X POST https://api.novu.co/v1/events/trigger \
  -H "Authorization: ApiKey $NOVU_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "welcome-onboarding-email",
    "to": { "subscriberId": "user_123", "email": "[email removed]" },
    "payload": { "firstName": "Jane" }
  }'

Important

Novu authenticates server requests with the header Authorization: ApiKey <YOUR_SECRET_KEY>. This exact scheme is used by the SDKs and the CLI. (Self-hosted users substitute their own API base URL.)

4.3 Verifying delivery

  • In the dashboard → Activity Feed, every trigger appears with its per-step execution status (sent, failed, delayed, digested).
  • For in-app notifications, they appear in the <Inbox /> instantly via the websocket service.
  • Failed steps show the provider error message and are retried by the worker according to the channel's retry policy.

5. Building Workflows in Code (@novu/framework)

You can author workflows as code with @novu/framework (the "Bridge" / code-first approach). Your workflows live in your repository, are type-safe, and are served from an endpoint Novu calls during execution. This keeps templates, conditions, and payload schemas versioned alongside your app.

5.1 Define a workflow

import { workflow } from '@novu/framework';
import { z } from 'zod';

export const welcomeWorkflow = workflow(
  'welcome-onboarding-email',
  async ({ step, payload }) => {
    await step.email('send-email', async () => ({
      subject: `Welcome, ${payload.firstName}!`,
      body: `Thanks for joining ${payload.organizationName}.`,
    }));

    await step.inApp('notify-inbox', async () => ({
      body: `Welcome aboard, ${payload.firstName} 🎉`,
    }));
  },
  {
    payloadSchema: z.object({
      firstName: z.string(),
      organizationName: z.string().default('our app'),
    }),
  }
);
  • The first argument is the trigger identifier — the same workflowId you pass when triggering.
  • Each step.<channel>() call is a step. The callback returns that channel's content.
  • A payloadSchema (Zod or JSON Schema) validates the trigger payload and generates a test-data form in the dashboard.

Note

Step types map to channels: step.email, step.sms, step.push, step.chat, step.inApp, plus flow-control steps step.digest, step.delay, and step.custom. The exact options for each step are documented at docs.novu.co/workflows.

5.2 Serve your workflows

Expose your workflows from a framework endpoint (Next.js, Express, Remix, SvelteKit, H3, Nuxt, NestJS, and AWS Lambda servers are supported by @novu/framework):

// app/api/novu/route.ts (Next.js App Router)
import { serve } from '@novu/framework/next';
import { welcomeWorkflow } from '../../../novu/workflows';

export const { GET, POST, OPTIONS } = serve({
  workflows: [welcomeWorkflow],
});

5.3 Test locally, then sync

While developing, run the Dev Studio so Novu can reach your local endpoint through a tunnel:

npx novu@latest dev --port 4000 --route /api/novu

When you are ready to push your code-defined workflows to your cloud or self-hosted environment, run sync:

npx novu@latest sync \
  --bridge-url https://your-app.com/api/novu \
  --secret-key $NOVU_SECRET_KEY \
  --api-url https://api.novu.co

Under the hood, sync sends your Bridge URL to POST /v1/bridge/sync?source=cli with an Authorization: ApiKey <secret-key> header; Novu discovers your workflows (and any agents) from the Bridge and registers them.

Tip

Add novu sync to your CI/CD pipeline so every deploy registers the latest workflows. The CLI auto-detects common CI environments (GitHub Actions, GitLab CI, CircleCI, Travis, Jenkins, Buildkite, Drone) and switches to non-interactive logging.


6. The novu CLI Reference

Run any command with npx novu@latest <command>. The CLI is the novu package.

Command Purpose
novu init Scaffold a starter app from a template.
novu dev Start the local Dev Studio + Bridge tunnel for local workflow development.
novu sync Register your code-defined workflows (Bridge URL) with a Novu environment.
novu connect Connect an existing AI agent to a channel (Slack, Telegram, Email) — see ACI.
novu wizard Interactive setup wizard (full
novu translations pull / push Download or upload translation files for localized content.
novu step publish Bundle and deploy code-defined step handlers.

6.1 novu dev

novu dev [options]
Option Description
-p, --port <port> The local Bridge endpoint port.
-r, --route <route> The Bridge endpoint route (e.g. /api/novu).
-o, --origin <origin> The Bridge endpoint origin.
-d, --dashboard-url <url> The Novu Cloud Dashboard URL.
-sp, --studio-port <port> The local Studio server port.
-sh, --studio-host <host> The local Studio server host.
-t, --tunnel <url> Use a self-hosted tunnel (e.g. an ngrok URL).
-H, --headless Run without opening the browser.
--no-studio Skip starting the local Studio server.
--run <command> Spawn a local app server before opening the tunnel.

6.2 novu sync

novu sync [options]
Option Description
--bridge-url <url> Your deployed Bridge endpoint URL. Required.
-s, --secret-key <key> Your Novu Secret Key. Required.
-a, --api-url <url> The Novu API URL (defaults to Novu Cloud).

Caution

novu sync fails fast if --bridge-url or --secret-key is missing, printing A bridge URL is required for the sync command… or A secret key is required for the sync command…. Supply both.

6.3 novu init

Option Description
-a, --api-url <url> The Novu Cloud API URL.
-t, --template <name> The template to use (notifications or agent).
--agent-identifier <id> Agent identifier to use in a scaffolded agent template.

6.4 novu translations

# Download translation files from a Novu environment
npx novu@latest translations pull --secret-key $KEY --directory ./translations

# Upload local translation files
npx novu@latest translations push --secret-key $KEY --directory ./translations

Note

Set NOVU_CLI_DEBUG=true to see verbose CLI request logging. CLI analytics can be disabled with ANALYTICS_ENABLED=false.


7. Embedding the Inbox

The Inbox is a real-time, embeddable notification center for your app's in-app channel. You drop in one component and get a bell, an unread count, a notification list, actions, and a preferences panel — all powered by the In-App channel and the websocket service.

7.1 React

import { Inbox } from '@novu/react';

export function NotificationsBell() {
  return (
    <Inbox
      applicationIdentifier={process.env.NEXT_PUBLIC_NOVU_APP_ID!}
      subscriberId="user_123"
    />
  );
}
  • applicationIdentifier — your public Application Identifier.
  • subscriberId — the current user's identifier (the same one you trigger to).

7.2 Next.js

'use client';
import { Inbox } from '@novu/nextjs';

export function Bell() {
  return <Inbox applicationIdentifier={process.env.NEXT_PUBLIC_NOVU_APP_ID!} subscriberId="user_123" />;
}

7.3 Self-hosted: point the Inbox at your instance

When self-hosting, tell the Inbox where your API and websocket services live:

<Inbox
  applicationIdentifier="<your-app-id>"
  subscriberId="user_123"
  backendUrl="https://novu-api.yourcompany.com"
  socketUrl="https://novu-ws.yourcompany.com"
/>

Tip

The Inbox is fully themeable and supports custom rendering of notification items, tabs/filters, and a built-in preferences view so users manage their own channel settings without you building UI. See docs.novu.co/platform/inbox.

7.4 Securing the Inbox with HMAC

For production, enable HMAC subscriber verification so a user can only read their own feed. You compute an HMAC hash of the subscriberId on your server (using your Secret Key) and pass it to the Inbox as subscriberHash. Enable HMAC for the In-App integration in the dashboard first.

Warning

Without HMAC verification, a subscriberId is a guessable identifier. Always enable HMAC in production so notifications cannot be read by spoofing another user's ID.


8. Subscribers & Preferences

8.1 Managing subscribers

Subscribers are upserted automatically when you trigger with a to object, but you can also manage them explicitly:

import { Novu } from '@novu/api';
const novu = new Novu({ secretKey: process.env.NOVU_SECRET_KEY });

await novu.subscribers.create({
  subscriberId: 'user_123',
  email: '[email removed]',
  phone: '+15555550123',
  firstName: 'Jane',
  locale: 'en_US',
});

Channel credentials (push device tokens, chat webhook URLs, Slack access tokens) are attached per subscriber so the right provider can reach them.

8.2 The three levels of preferences

Novu resolves whether a given channel fires for a given subscriber by combining three layers:

Level Set by Scope
Workflow channel preferences You (workflow author) Defaults and which channels are user-editable.
Subscriber preferences per workflow The end user "Mute SMS for the weekly-digest workflow."
Subscriber global preferences The end user "Turn off all SMS everywhere."

Users manage levels 2 and 3 directly inside the <Inbox /> preferences panel, or you build your own UI on the preferences API.

Note

A critical workflow can be marked so that it ignores subscriber preferences (e.g. security alerts that must always send). Configure this on the workflow.


9. Digest, Delay & Scheduling

These flow-control steps shape when and how often messages go out.

9.1 Digest

The digest engine collects multiple trigger events for the same subscriber over a window, aggregates them, and sends a single combined message.

Example: a user gets 100 events in a few minutes, but you only want to notify them once per hour.

await step.digest('batch', async () => ({
  amount: 1,
  unit: 'hours', // batch events for one hour
}));

await step.inApp('summary', async (controls, { events }) => ({
  body: `You have ${events.length} new updates`,
}));

9.2 Delay / Schedule

The delay step waits a specified amount of time before continuing to the next steps. Common uses:

  • Send a follow-up email 24 hours after registration.
  • Trigger a reminder if the user hasn't completed an action.
  • Give the user a grace period to cancel an action.
  • Schedule a notification for a specific date.
await step.delay('wait-a-day', async () => ({
  amount: 24,
  unit: 'hours',
}));

Tip

Delays and digests are durable: the worker persists the job and resumes it when the timer fires, so they survive restarts. Long delays don't hold a connection open.


10. Channels & Providers

Novu speaks to each channel through a provider. You configure providers (and their credentials) once as integrations in the dashboard; workflows then deliver through whatever provider is active for each channel and environment.

10.1 Supported providers

<details> <summary><strong>Email (19 providers)</strong></summary>

Amazon SES · Braze · Brevo · Custom SMTP (Nodemailer) · Email Webhook · Email.js · Infobip · MailerSend · Mailgun · Mailjet · Mailtrap · Mandrill · Netcore · Outlook 365 · Plunk · Postmark · Resend · SendGrid · SparkPost

</details>

<details> <summary><strong>SMS (37 providers)</strong></summary>

46elks · Africa's Talking · Afro SMS · Amazon SNS · Azure SMS · Bandwidth · Brevo SMS · Bulk SMS · Burst SMS · Clickatell · ClickSend · CM Telecom · Eazy SMS · Firetext · Generic SMS · Gupshup · iMedia · Infobip · iSend SMS · iSendPro SMS · Kannel · Maqsam · MessageBird · Mobishastra · Plivo · RingCentral · Sendchamp · SimpleTexting · Sinch · SMS Central · SMS77 · SMSMode · Telnyx · Termii · Twilio · Unifonic · Vonage (Nexmo)

</details>

<details> <summary><strong>Push (8 providers)</strong></summary>

APNS · App.io · Expo · FCM (Firebase Cloud Messaging) · OneSignal · Push Webhook · Pusher Beams · Pushpad

</details>

<details> <summary><strong>Chat (12 providers)</strong></summary>

Chat Webhook · Discord · GetStream · Grafana OnCall · Mattermost · Microsoft Teams · Rocket.Chat · Ryver · Slack · Telegram · WhatsApp Business · Zulip

</details>

<details> <summary><strong>In-App (1 provider)</strong></summary>

Novu Inbox (the built-in <Inbox /> channel)

</details>

10.2 Configuring a provider

  1. In the dashboard, go to Integrations → Add Integration.
  2. Pick the channel and provider (e.g. Email → Resend).
  3. Enter the provider credentials (API key, sender address, region, etc.).
  4. Set it as the active integration for that channel in the environment.

Note

Each channel can have one active provider per environment. You configure different credentials in Development vs. Production environments — see Section 13.

10.3 Provider-specific notes

  • Custom SMTP uses the Nodemailer provider — point it at any SMTP server.
  • Email Webhook / Chat Webhook / Push Webhook let you deliver to a service Novu doesn't have a native provider for by POSTing a normalized payload to your own endpoint.
  • FCM push expects valid FCM credentials; an invalid config raises Config is not valid for fcm. Likewise APNS raises Config is not valid for apns.

11. Agent Communication Infrastructure (ACI)

ACI lets an AI agent you've already built talk to users on real channels — Slack, Microsoft Teams, Telegram, WhatsApp, Email, and an in-app Inbox — through one unified conversation model. Novu handles inbound message normalization, threading, reactions, and channel-aware formatting in both directions; your agent logic stays yours.

You build the agent. Novu gives it a voice.

11.1 Connect an agent in minutes

npx novu@latest connect

This interactive flow creates an agent, lets you describe it, and connects a channel. Useful options:

Option Description
-s, --secret-key <key> Use this Secret Key and skip browser auth.
--prompt <text> Pre-fill the agent description.
--anthropic-api-key <key> Anthropic API key for non-interactive claude runtime runs.
--skip-slack Create the agent and exit without connecting a channel.
--ci Force non-interactive mode (no TUI).

Tip

ACI works with whatever stack you've built — Claude Managed Agents, the AI SDK, LangGraph, or a custom runtime. Novu connects the agent to the world; it is not the agent itself. Try the live demo at novu.co/connect.

11.2 How inbound works

When a user replies in Slack/Telegram/Email, Novu receives the platform webhook, normalizes it into the unified conversation model, and routes it to your agent's Bridge endpoint. Your agent's response is sent back out through the same channel — so you integrate once instead of maintaining a webhook handler per platform.


12. Translations & Layouts

12.1 Translations

Localize notification content per subscriber locale. Manage translation files from the CLI:

npx novu@latest translations pull --secret-key $KEY --directory ./translations
# edit files...
npx novu@latest translations push --secret-key $KEY --directory ./translations

Set each subscriber's locale (e.g. en_US, fr_FR) so Novu renders the matching translation at send time.

Note

Advanced translation management is part of Novu's enterprise edition. The community edition supports per-locale content; see the Admin Guide for the open-core boundary.

12.2 Layouts

A layout is a reusable wrapper (header/footer/branding) applied around email content so every email shares a consistent look. Create layouts in the dashboard and reference them from email steps. The no-code email editor (Maily) lets you build rich, branded emails visually.


13. Environments & Promotion

Every Novu account has at least Development and Production environments. Each environment has its own API keys, integrations (provider credentials), and subscribers.

Typical flow:

  1. Build and test workflows in Development (with novu dev and test triggers).
  2. Promote / sync them to Production.
  3. Production uses production provider credentials and real subscribers.

Important

API keys are environment-scoped. A Development Secret Key cannot trigger Production workflows and vice-versa. Keep them in separate secrets in your deployment.


14. Common Tasks (Recipes)

14.1 Trigger to many users at once

await novu.trigger({
  workflowId: 'product-update',
  to: [
    { subscriberId: 'user_1', email: '[email removed]' },
    { subscriberId: 'user_2', email: '[email removed]' },
  ],
  payload: { version: '2.0' },
});

14.2 Broadcast to a topic

Group subscribers under a topic key (e.g. team:acme) and trigger the topic to reach all of them:

await novu.trigger({
  workflowId: 'team-announcement',
  to: [{ type: 'Topic', topicKey: 'team:acme' }],
  payload: { message: 'Maintenance tonight' },
});

14.3 Cancel a delayed/scheduled notification

If a workflow is waiting on a delay or digest, cancel it by its transactionId:

curl -X DELETE https://api.novu.co/v1/events/trigger/<transactionId> \
  -H "Authorization: ApiKey $NOVU_SECRET_KEY"

14.4 Add the Inbox to an existing React app fast

npx novu-add-inbox --appId <APP_ID> --subscriberId <SUBSCRIBER_ID>

The add-inbox CLI scaffolds the Inbox into your project. Options include --region <eu|us>, --backendUrl <url>, and --socketUrl <url> for self-hosted instances.

14.5 Send a test notification from the dashboard

In the workflow editor, use Test Workflow with sample payload data (generated from your payloadSchema) to send a one-off to yourself — no code needed.


15. Troubleshooting

Format: the exact error, its cause, the fix, and how to prevent it.

Error: A bridge URL is required for the sync command, please supply it when running the command

  • Cause: novu sync was run without --bridge-url.
  • Solution: Pass your deployed Bridge endpoint, e.g. --bridge-url https://your-app.com/api/novu.
  • Prevention: Store the Bridge URL in CI as an environment variable and reference it in your sync step.

Error: A secret key is required for the sync command, please supply it when running the command

  • Cause: novu sync ran without --secret-key.
  • Solution: Pass --secret-key $NOVU_SECRET_KEY (environment-scoped key).
  • Prevention: Keep the Secret Key in a CI secret; never hardcode it.

Error: Config is not valid for fcm (or Config is not valid for apns)

  • Cause: The push provider integration is missing or has malformed credentials.
  • Solution: Re-enter the FCM service-account JSON / APNS key in Integrations, and confirm the subscriber has a registered device token for that provider.
  • Prevention: Validate provider credentials right after configuring, using a test trigger to one device.

Error: notifications never appear in the <Inbox />

  • Cause: Wrong applicationIdentifier, mismatched subscriberId, or (self-hosted) the Inbox can't reach the websocket service.
  • Solution: Confirm the applicationIdentifier matches the environment you triggered in, the subscriberId matches the to you triggered, and (self-hosted) backendUrl/socketUrl point at your API/WS services.
  • Prevention: Use the same env-scoped Application Identifier on both the trigger side and the Inbox.

Error: ws@3.x crashes on connection … reading subscriber.contextKeys.length (GitHub #10124)

  • Cause: A version-specific bug in the websocket service when a subscriber lacks contextKeys.
  • Solution: Upgrade @novu/js/@novu/react and the self-hosted ws image to the latest version.
  • Prevention: Keep client SDK and server images on matching, current versions.

Error: SsrfBlockedError: BLOCKED_HOSTNAME / INVALID_URL / CREDENTIALS_IN_URL

  • Cause: A Bridge URL, webhook URL, or provider endpoint resolves to a blocked/internal address or is malformed. Novu blocks outbound requests to private ranges to prevent SSRF.
  • Solution: Use a publicly reachable HTTPS URL with no embedded credentials. For local development use the tunnel that novu dev provides.
  • Prevention: Host your Bridge endpoint on a public domain; don't put user:pass@ in URLs.

Error: DataFilterValidationError / TagsFilterValidationError

  • Cause: A workflow step condition (data filter or tags filter) is malformed — too many groups/values, wrong types, or both AND and OR set.
  • Solution: Simplify the filter; ensure values are scalars (string/number/boolean/null), tags are strings, and you use either AND or OR (not both) at a level.
  • Prevention: Build conditions in the dashboard's condition editor, which enforces the limits.

Error: trigger returns success but no email is sent

  • Cause: No active Email integration in the triggered environment, the subscriber has no email, or the channel is disabled by preferences.
  • Solution: Check the Activity Feed for the per-step status; configure an active Email provider; ensure the to object includes email; verify the subscriber hasn't muted the channel.
  • Prevention: Mark must-send workflows as critical to bypass preference opt-outs.

Error: NOVU_MANAGED_CLAUDE_API_KEY is not configured (agent runs)

  • Cause: A managed-agent feature needs an Anthropic key that isn't set.
  • Solution: Provide --anthropic-api-key to novu connect, or set the key in your environment for non-interactive runs.
  • Prevention: Configure the agent runtime credentials before running agent flows in CI.

Error: self-hosted dashboard loads but API calls fail

  • Cause: VITE_API_HOSTNAME / VITE_WEBSOCKET_HOSTNAME (dashboard) don't match where the API/WS are reachable from the browser.
  • Solution: Set these to the externally reachable URLs of your API (:3000) and WS (:3002) services.
  • Prevention: See the Admin Guide environment-variable reference.

Error: workflows defined in code don't show up after deploy

  • Cause: novu sync wasn't run, or it pointed at the wrong environment.
  • Solution: Run novu sync --bridge-url <prod-bridge> --secret-key <prod-key> against the right environment.
  • Prevention: Make sync a required CI step gated on a successful deploy.

16. FAQ

Q: Do I have to use Novu Cloud? No. Novu is fully open source (MIT, with an enterprise edition under a commercial license). You can self-host the entire stack with Docker — see Section 3 and the Admin Guide.

Q: What's the difference between a workflow built in the dashboard vs. in code? Functionally similar. The dashboard's no-code editor is great for non-engineers and quick changes; @novu/framework keeps workflows in your repo, type-safe and versioned, served from your app via the Bridge. You can mix both.

Q: What is the "Bridge"? The Bridge is the HTTP endpoint in your app (served by @novu/framework) that Novu calls to discover and execute your code-defined workflows. novu dev tunnels to it locally; novu sync registers its URL.

Q: How do I identify users? With your own subscriberId — use your application's user ID. Novu upserts subscribers when you trigger with a to object containing channel credentials.

Q: Can one workflow send to multiple channels? Yes. Add multiple channel steps (email, sms, inApp, push, chat) to one workflow. Conditions and preferences decide which actually fire per subscriber.

Q: How do I batch noisy notifications? Use a digest step to aggregate events over a time window into a single message (Section 9).

Q: How do users opt out of notifications? Through the preferences panel in the <Inbox /> (or your own UI on the preferences API). They can mute per-workflow or globally per channel. Mark truly critical workflows to bypass opt-outs.

Q: Which framework can serve @novu/framework workflows? Next.js, Express, Remix, SvelteKit, Nuxt/H3, NestJS, and AWS Lambda are supported serve targets.

Q: How do I localize content? Set each subscriber's locale and manage translation files with novu translations pull/push. Advanced translation management is an enterprise feature.

Q: Is the Inbox secure? Enable HMAC subscriber verification in production so a user can only read their own feed. Without it, subscriberId is guessable.

Q: What Node version do I need? To run/self-host the platform: Node 22. The client SDKs target current LTS Node and modern browsers; React packages need React 19.

Q: Where's the full REST API reference? At docs.novu.co/api-reference. Novu generates an OpenAPI spec from the API, so the reference always matches the deployed version.

Q: How do I report a bug or request a provider? Open an issue at github.com/novuhq/novu (there are active requests for providers like WeChat, LINE, and Google Chat) or join the Discord.


17. Reference

17.1 npm packages

Package Role
novu CLI (init, dev, sync, connect, wizard, translations, step).
@novu/api Server SDK for triggering and managing resources.
@novu/framework Code-first workflow definitions + serve adapters.
@novu/js Framework-agnostic browser client for the Inbox.
@novu/react React <Inbox /> and hooks.
@novu/nextjs Next.js Inbox wrapper.
@novu/react-native React Native notification hooks.
@novu/stateless Lightweight stateless notification trigger library.
@novu/providers The provider implementations (used internally).

17.2 Key CLI commands

Command Most-used flags
npx novu@latest init `-t <notifications
npx novu@latest dev -p <port>, -r <route>, --no-studio, -H
npx novu@latest sync --bridge-url, -s <secret-key>, -a <api-url>
npx novu@latest connect --prompt, -s <secret-key>, --ci
npx novu@latest translations pull/push -s, -d <directory>

17.3 Hosted endpoints (Novu Cloud)

Service URL
API (US) https://api.novu.co
API (EU) https://eu.api.novu.co
Dashboard https://dashboard.novu.co
Docs https://docs.novu.co

17.4 Default local/self-hosted ports

Service Port
API 3000
Worker (health) 3004
WebSocket (WS) 3002
Dashboard 4000
Local Studio (dev) 2022

17.5 Useful environment variables (client/CLI)

Variable Purpose
NOVU_SECRET_KEY Server-side API key for triggering.
NOVU_API_URL / NOVU_API_KEY Base URL and key used by @novu/framework.
NEXT_PUBLIC_NOVU_APP_ID Public Application Identifier for the Inbox.
NEXT_PUBLIC_NOVU_SOCKET_URL WebSocket URL for the Inbox (self-hosted).
NOVU_CLI_DEBUG Verbose CLI logging when true.
ANALYTICS_ENABLED Toggle CLI analytics.

Note

For the full server-side environment-variable reference, deployment topology, scaling, and security hardening, see the Novu Admin Guide.