Skip to main content
Novu Framework requires a single HTTP endpoint (/api/novu or similar) to be exposed by your application. This endpoint is used to receive events from our Worker Engine. You can view the Bridge Endpoint as a webhook endpoint that Novu will call when it needs to retrieve contextual information for a given subscriber and notification. Using the npx novu init command creates a Bridge application for you with a Bridge Endpoint ready to go.

The serve function

We offer framework specific wrappers in form of an exported serve function that abstracts away:
  • Parsing the incoming request for GET, POST, PUT and OPTIONS requests
  • HMAC header authentication
  • Framework specific response and error handling
Currently, we offer serve functions for the following frameworks:

Writing a custom serve function

If we currently don’t support your framework, you can write a custom serve function like the following example:
import { type Request, type Response } from "express";
import { NovuRequestHandler, ServeHandlerOptions } from "@novu/framework";

export const serve = (options: ServeHandlerOptions): any => {
  const requestHandler = new NovuRequestHandler({
    frameworkName: "express",
    ...options,
    handler: (incomingRequest: Request, response: Response) => ({
      method: () => incomingRequest.method,
      headers: (key) => {
        const header = incomingRequest.headers[key];
        return Array.isArray(header) ? header[0] : header;
      },
      queryString: (key) => {
        const qs = incomingRequest.query[key];
        return Array.isArray(qs) ? qs[0] : qs;
      },
      body: () => incomingRequest.body,
      url: () =>
        new URL(
          incomingRequest.url,
          `https://${incomingRequest.headers.get("host") || ""}`
        ),
      transformResponse: ({ body, headers, status }) => {
        Object.entries(headers).forEach(([headerName, headerValue]) => {
          response.setHeader(headerName, headerValue);
        });

        return response.status(status).send(body);
      },
    }),
  });

  return requestHandler.createHandler();
};
The tunnel url is the url that is generated by the Studio when you run the npx novu@latest dev command. It is used to test your notifications by triggering them from the Studio UI. For local development and testing, you can use the tunnel url as bridge url. For production, you should use deployed application url with bridge endpoint as the bridge url.
Yes, the bridge url must be publicly accessible. We recommend having https enabled for the bridge url.
Yes, you can use any path you want. However, you need to make sure that the endpoint is used in the bridge url. Bridge url is made of the base url and the endpoint path. If your path is /custom-path/novu and deployed application url is https://my-app.com, then the bridge url will be https://my-app.com/custom-path/novu.