Reach your users in Microsoft Teams, from the same Notifly workflow.
There are two ways in. The quick one is an incoming webhook: Notifly posts the chat step to a Teams channel's webhook URL, with no credentials at all. The full one is your own Azure bot: your customers' admins consent once per tenant, and Notifly messages users and channels as your bot through the Bot Framework.
Either way, Notifly runs the workflow around the message: one trigger that can also reach in-app, email, SMS and push, digest, delay and throttle steps, subscriber preferences checked before each send, and an activity feed that records what Teams answered.
What you need from Azure
These are the fields the dashboard asks for when you connect MSTeams, quoted from the create form. All four are optional, and the form says why: “These credentials are only required for Bot App authentication and are not needed for incoming webhook functionality.”
| Field | Required | Stored | Notes |
|---|---|---|---|
| Microsoft App ID | Optional | As entered | From Azure Bot resource → Configuration, or App Registration → Overview (Application client ID) |
| Client Secret | Optional | Encrypted at rest | Secret value from App Registration → Certificates & secrets → New client secret |
| Directory (tenant) ID | Optional | As entered | From App Registration → Overview (Directory tenant ID) |
| Redirect URL | Optional | As entered | Redirect after Teams OAuth flow finished (default behaviour will close the tab) |
- For a webhook only. Leave all four empty and save each subscriber's webhook URL instead.
- For your bot. Fill in the Microsoft App ID, Client Secret and Directory (tenant) ID, and add
https://api.notifly.io/v1/integrations/chat/oauth/callbackas a redirect URI on the Azure app registration. - Redirect URL in Notifly. Optional: where users land after connecting. Left empty, Notifly shows its own confirmation page.
Connect Microsoft Teams in the dashboard
- Sign in at app.notifly.io, open Integration Store in the sidebar and choose Connect Provider.
- In the Connect Integration sheet, open the Chat tab (or search across channels), find MSTeams and choose Connect.
- Pick the environment the integration belongs to. Development and Production keep separate integrations, so you can point each at a different MSTeams account or key.
- Fill in Delivery Provider Credentials with the fields in the table above, then choose Create Integration.
Connect a user, then trigger
Save a webhook URL or send the user through a connect link once; after that a trigger only names the subscriber, and Notifly works out where in Teams the message goes.
// npm install @notiflyio/api@0.1.26
import { Notifly } from "@notiflyio/api";
const notifly = new Notifly({ security: { secretKey: process.env.NOTIFLY_SECRET_KEY } });
// Option A: an incoming webhook URL your user created in Teams. No bot needed.
await notifly.subscribers.credentials.update(
{ providerId: "msteams", credentials: { webhookUrl: teamsWebhookUrl } },
"user_123",
);
// Option B: your own bot. A connect link (valid for 5 minutes) asks the user's tenant admin
// for consent; autoLinkUser then signs the user in and installs your bot for them.
const { result } = await notifly.integrations.generateConnectOAuthUrl({
integrationIdentifier: "msteams-bot", // the Identifier of your MSTeams integration
subscriberId: "user_123",
autoLinkUser: true,
});
// Redirect the user to result.url.
// Either way, workflows with a chat step now reach them in Teams.
await notifly.trigger({
workflowId: "incident-opened",
to: "user_123",
payload: { service: "billing-api", severity: "high" },
});Prefer plain HTTP? The same trigger is POST https://api.notifly.io/v1/events/trigger with an Authorization: ApiKey header and a body of { "name", "to", "payload" }.
What reaches Teams
- A webhook post. The chat step's content, sent as is when it is JSON and as
{ "text" }when it is not, after a safety check on the address. - Workflows webhooks. Microsoft 365 Connectors are nearing deprecation, and Microsoft points to webhooks created with the Teams Workflows app instead (Microsoft Learn). Their trigger takes Adaptive Cards or a Message Card (Microsoft Learn), so for a Workflows webhook URL write the chat step's content as Adaptive Card JSON: a
messagewithapplication/vnd.microsoft.card.adaptiveattachments, which Notifly posts as is. - Or a bot message. For a linked user or a channel, a Bot Framework message sent with an app-only token Notifly requests with your App ID and client secret.
- Teams' answer. A refusal fails the step with a named MSTEAMS error or Teams' own, recorded in the activity feed.
What Notifly adds on top of Teams
Workflows around the send
One trigger runs a workflow: this provider’s step can sit beside in-app, email, SMS, push and chat steps, behind digest, delay and throttle steps.
Digest notifications →Subscriber preferences, enforced at send
Before each step runs, the subscriber’s workflow and channel preferences are checked; an opted-out step is skipped and the reason is recorded.
An in-app Inbox next to it
The same workflow can write to the Notifly Inbox, a real-time in-app feed you embed with the React component or the JavaScript SDK.
React notification inbox →Per-trigger provider parameters
Anything the trigger passes under overrides.providers.<provider id> is merged into the request Notifly sends to the provider, per workflow or per step.
Activity you can debug
Every message gets execution details in the activity feed, including the response or error the provider returned.
Secrets encrypted at rest
API keys, tokens and service accounts are stored encrypted with AES-256; new and re-saved credentials use authenticated AES-256-GCM. The table above marks which of this provider’s fields that covers.
Go deeper in the docs
Frequently asked questions
Do I need an Azure bot to post to Teams?
No. To post through a Teams incoming webhook, save its URL on the subscriber with subscribers.credentials.update, providerId msteams and credentials.webhookUrl, and leave the integration's fields empty: as the dashboard says, they are only required for Bot App authentication. Notifly checks the URL is a safe public address before posting to it.
What does the bot option need from Azure?
Your app registration's Microsoft App ID, a client secret and its Directory (tenant) ID; the connect flow stops with an error when any of the three is missing, and the client secret is stored encrypted at rest. Add https://api.notifly.io/v1/integrations/chat/oauth/callback as a redirect URI on the app registration. To message a user, Notifly reads your Teams app from the organization's app catalog and installs it for them through Microsoft Graph, so the Teams app must be published to that catalog and the app registration needs the AppCatalog.Read.All and TeamsAppInstallation.ReadWriteSelfForUser.All application permissions.
How does a customer's Microsoft 365 tenant connect?
Through a connect link from integrations.generateConnectOAuthUrl. It takes a tenant admin to Microsoft's admin consent page; once they grant consent, Notifly stores the tenant as a connection, with no user tokens kept, and requests app-only tokens from Microsoft when it sends. With autoLinkUser: true the same link then signs the user in and links their Teams account. The link expires after five minutes.
What happens when the bot cannot reach someone?
The step fails with a named error in the activity feed: MSTEAMS_BOT_NOT_INSTALLED when your bot is not installed for that team, channel or user, MSTEAMS_CHANNEL_NOT_FOUND when Teams does not know the channel or user, MSTEAMS_INVALID_CREDENTIALS when the bot token is refused, and MSTEAMS_INSUFFICIENT_PERMISSIONS when the send is not allowed.
Where does the user land after connecting?
At the Redirect URL you set on the integration, if any. Left empty, Notifly shows its own page saying Microsoft Teams is connected and ready to use, which the user can close.
Bring your provider account. Keep your sender reputation.
One POST /v1/events/trigger — email, SMS, push, in-app, and chat. 10,000 events a month, free.