Skip to main content
Complete Azure and bot setup first. This page covers tenant-wide admin consent and where Novu should send messages.

Let organizations connect their Microsoft 365 tenant

Each organization you notify has its own Microsoft 365 tenant. Before you can send Teams messages on their behalf, a tenant administrator from that organization must grant your app a one-time admin consent. This authorizes your bot in their tenant using application permissions (app-only / client credentials).
Tenant connect and user linking are separate steps. Admin consent connects the organization’s Microsoft 365 tenant. Linking a Novu subscriber for direct messages is a separate OAuth flow - see Link a subscriber for direct messages.

Generate a Connect Teams URL

Call this from your backend when someone starts the connect flow in your product (for example, when a tenant administrator clicks Connect Microsoft Teams).
The generated OAuth URL is valid for only 5 minutes. Do not cache it - generate a new URL each time someone starts connect.
Call POST /v1/integrations/channel-connections/oauth with the same body if you are not using the TypeScript SDK. Authenticate with your Novu secret key. Novu returns a URL pointing to Microsoft’s administrator consent endpoint (login.microsoftonline.com/organizations/v2.0/adminconsent). It includes your Client ID, redirect URI, and the https://graph.microsoft.com/.default scope. For tenant-wide admin consent, set autoLinkUser: false (or omit autoLinkUser - the API treats omitted as false). Only when autoLinkUser is explicitly true does Novu chain a second OAuth flow after admin consent to link that subscriber for DMs.
@novu/react MsTeamsConnectButton defaults autoLinkUser to true in subscriber mode. That is intended for in-app end-user connect flows. For server-side tenant admin consent (Java, REST, or @novu/api), pass autoLinkUser: false explicitly.
For a resource-specific organization connection as shown above, use a valid, stable Novu subscriberId. The subscriber can represent the organization rather than an individual person, but it must exist in the same environment as the integration. For a shared connection, omit subscriberId and provide a Context. Do not send null as the subscriber ID.
Run tenant admin consent once for each combination of environment, integration, resource, and Context. Starting the flow again for an existing connection returns 409 Conflict with A channel connection already exists. Reuse the existing connection instead of creating a duplicate. If you must reconnect after changing Azure permissions or credentials, remove the existing channel connection before starting a new consent flow.

Show it in your UI

Open the URL in a new tab or window when the tenant administrator is ready to consent:

What the tenant administrator does

The tenant administrator is someone at the connecting organization (not a Novu dashboard user). They grant consent in Microsoft - they do not need a Novu account.
1

Sign in to your product

The tenant administrator signs in to your application.
2

Click Connect Microsoft Teams

They click Connect Microsoft Teams. Your backend generates a fresh OAuth URL and opens it.
3

Review consent page

Microsoft shows a consent page listing the application permissions.
4

Accept consent

They click Accept.
Microsoft redirects to Novu with admin_consent=True and the organization’s tenant ID. Novu stores the tenant on a channel connection and the flow is complete. You do not handle the callback yourself. If you set an optional Redirect URL on the MS Teams integration in the Novu dashboard, the administrator is sent there after success; otherwise the consent window shows a success message and can be closed.

Install the app in Teams

Admin consent only authorizes your bot in the organization’s tenant. It does not add the bot to a specific team or chat. For the bot to send messages, someone must install the app where notifications should appear:
  • For channel messages: Install the app in the specific Team.
  • For direct messages: Install the app for the specific user in their personal scope.
The tenant administrator can install your app from the Teams app store or their org catalog, depending on how you published. If you requested the TeamsAppInstallation.ReadWriteSelfForTeam.All permission, your backend can programmatically install the app into a specific Team using the Microsoft Graph API.

Tell Novu where to send the messages

Decide where notifications should land in Teams, collect the required IDs, and register them as channel endpoints in Novu. You can choose between two destination types:
  • Channels: Send a message to a specific channel within a Team.
  • Users: Send a direct message to a specific user.

Sending message to channels

To send a notification to a specific channel, you must discover the Team ID and Channel ID from Microsoft, and then register them in Novu.

Find the Team and Channel IDs (Microsoft Graph)

You can discover these IDs using the Microsoft Graph API. This requires an App-Only Token (Client credentials) scoped to the customer’s tenant.
1

Get a Graph access token

The SUBSCRIBER_TENANT_ID represents the customer’s tenant ID, which Novu stored on the ChannelConnection object after completing the Admin Consent flow.
2

List Teams

3

List channels in a Team

Register the channel endpoint (Novu)

Once you have the IDs, create an ms_teams_channel endpoint in Novu. This maps a subscriber to that specific channel.
Novu stores this as ChannelEndpoint<'ms_teams_channel'>.

Send a direct message to a user

To send a direct message (DM), register an ms_teams_user channel endpoint for the subscriber. You can do this with OAuth or by supplying the Teams user ID manually. Prerequisites:
  • Admin consent has already connected the organization’s tenant (see above).
  • The subscriber exists in Novu.
  • Application permission TeamsAppInstallation.ReadWriteSelfForUser.All and delegated User.Read are configured in Azure (see Add Microsoft Graph app permissions).
Run a separate OAuth flow - do not set autoLinkUser: true on generateConnectOAuthUrl. Use generateLinkUserOAuthUrl instead:
Call POST /v1/integrations/channel-endpoints/oauth with the same body when using the REST API. This opens a Microsoft sign-in flow with delegated scopes (openid, profile, User.Read). Novu reads the user’s identity from the token, installs the bot for that user when possible, and creates an ms_teams_user channel endpoint.
The generated OAuth URL expires after 5 minutes. Generate it when the subscriber is ready to sign in.

Find the user ID manually (Bot framework)

Alternatively, discover the Teams user ID yourself and register the endpoint without OAuth. Use the Bot framework API to inspect the roster of the Team where you installed the bot.
1

Install the bot in a Team

Install the bot in at least one Team that includes the target user.
2

Get a Bot Framework token

3

Call the roster API

From the returned members, take the member’s id; this value represents the Teams user ID (29:...) you’ll use as userId.

Register the user endpoint (Novu)

Once you have the IDs, create the endpoint in Novu using the ms_teams_user type.
Novu stores this as ChannelEndpoint<'ms_teams_user'>. From here, any workflow that resolves to this endpoint can send a DM from your bot to that user.

Set up the Azure bot

Create the Entra ID app, Azure Bot, and Teams package.