Skip to main content
RapidDev - Software Development Agency
flutterflow-integrationsFlutterFlow API Call

Microsoft Teams

Connect FlutterFlow to Microsoft Teams by creating a Workflows-based channel webhook in Teams and POSTing an Adaptive Card from a FlutterFlow API Call. No authentication header is needed — the webhook URL is the credential. For richer features like DMing users or posting to any channel, use Microsoft Graph via a Cloud Function proxy to keep the client secret off the device.

What you'll learn

  • How to create a Workflows-based webhook in a Teams channel
  • How to configure a FlutterFlow API Call to POST Adaptive Card JSON to Teams
  • How to trigger Teams notifications from app events like new signups or alerts
  • When and how to upgrade to Microsoft Graph for richer Teams functionality
  • How to protect the webhook URL in consumer-facing apps using a Cloud Function
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner14 min read20 minutesCommunicationLast updated July 2026RapidDev Engineering Team
TL;DR

Connect FlutterFlow to Microsoft Teams by creating a Workflows-based channel webhook in Teams and POSTing an Adaptive Card from a FlutterFlow API Call. No authentication header is needed — the webhook URL is the credential. For richer features like DMing users or posting to any channel, use Microsoft Graph via a Cloud Function proxy to keep the client secret off the device.

Quick facts about this guide
FactValue
ToolMicrosoft Teams
CategoryCommunication
MethodFlutterFlow API Call
DifficultyBeginner
Time required20 minutes
Last updatedJuly 2026

Send Real-Time Alerts to Microsoft Teams from Your FlutterFlow App

Microsoft Teams is the central hub for many operations teams, and pushing app events directly into a Teams channel keeps your team informed without anyone having to check a separate dashboard. FlutterFlow makes this surprisingly approachable through Teams' Workflows webhook: a single URL that accepts a structured JSON Adaptive Card payload, no auth headers needed. This is the fastest notification integration you can build in FlutterFlow — a single API Call and you're done.

Teams offers two integration paths and FlutterFlow makes the choice clear. The simple path — the one 90% of FlutterFlow builders actually need — is the channel webhook created via the Teams 'Workflows' app (which replaced the now-deprecated Incoming Webhook connector). The URL itself is the credential, and your FlutterFlow API Call posts a JSON message body directly to it. The rich path is Microsoft Graph, which lets you post to any channel, send direct messages, and manage Teams programmatically. Graph requires Azure AD OAuth with a client secret, which must never live in a compiled Flutter app — that path needs a Firebase Cloud Function or Supabase Edge Function proxy.

Both paths are free with a Microsoft 365 or Teams account. The webhook-based approach is best for operations alerts (new user signup, order placed, error spike) sent to an internal channel. The Graph path is for applications where the teams and recipients are dynamic or user-driven. This page walks through the webhook path completely and outlines the Graph upgrade when you need it.

Integration method

FlutterFlow API Call

FlutterFlow sends a POST request to a Teams Workflows webhook URL with an Adaptive Card JSON body. No authentication header is required — the secret is the URL itself, making this the easiest notification integration in FlutterFlow. For advanced use cases like messaging specific users or posting to private channels, the Microsoft Graph API requires a Cloud Function proxy to protect the Azure AD client secret.

Prerequisites

  • A Microsoft Teams workspace with a channel where you want to receive notifications
  • Owner or member access to the Teams channel to create a Workflows webhook
  • A FlutterFlow project (free tier or above)
  • For the Graph path: access to the Azure Portal to register an Azure AD app
  • For the Graph path: a Firebase project or Supabase project for the Cloud Function proxy

Step-by-step guide

1

Create a Workflows Webhook in Your Teams Channel

Open Microsoft Teams and navigate to the channel where you want to receive notifications — for example, #ops-alerts or #new-signups. Hover over the channel name, click the three-dot (⋯) menu, and select 'Workflows'. In the Workflows dialog, search for 'Post to a channel when a webhook request is received' and click Add. Give the workflow a name like 'FlutterFlow Notifications', confirm the team and channel, and click Add workflow. Teams will generate a webhook URL — it looks like `https://prod-xx.<region>.logic.azure.com:443/workflows/.../triggers/manual/paths/invoke?...`. Copy this URL and save it somewhere safe. This URL is the only credential you need: whoever knows it can post to your channel. Do not publish it in public repositories or embed it in a consumer-facing app without a proxy layer. Note: the older 'Incoming Webhook' connectors are being phased out by Microsoft — always use the Workflows-based webhook for new integrations. If you see a dead webhook URL inherited from an old setup, recreate it through the Workflows app to get a fresh, supported URL.

Pro tip: Test the webhook immediately by pasting the URL into a tool like Postman or using a browser curl shortcut. POST `{"text": "Hello from FlutterFlow"}` and confirm the message appears in Teams before wiring up FlutterFlow.

Expected result: A webhook URL is generated and visible in the Teams Workflows dialog. A test message appears in the target channel.

2

Add a Microsoft Teams API Group in FlutterFlow

In your FlutterFlow project, click 'API Calls' in the left navigation panel. Click '+ Add' and select 'Create API Group'. Name the group 'MicrosoftTeams'. For the base URL, enter the first part of your webhook URL up through the domain — however, because Teams Workflows webhook URLs are full paths (not base + path), the cleanest approach for a single webhook is to leave the base URL as `https://prod-xx.<region>.logic.azure.com` and put the rest of the path in the individual API Call below. Alternatively, paste the entire webhook URL as the base URL and leave the endpoint path empty. Either approach works; keep it simple by treating the full webhook URL as the single endpoint. In the Headers section, you do not need to add any Authorization header — the webhook URL itself is the credential. Set the 'Content-Type' header to `application/json` so Teams parses the JSON body correctly. Click 'Save' to create the group. You now have an API Group ready to accept calls pointing at your Teams channel.

typescript
1// API Group config (reference, not a file to copy)
2// Group name: MicrosoftTeams
3// Base URL: https://prod-xx.<region>.logic.azure.com
4// Headers:
5// Content-Type: application/json
6// (No Authorization header needed)

Pro tip: If you have multiple Teams channels (e.g., #ops, #sales, #support), create separate API Calls within the same group, each with its own full webhook URL stored as a variable — this lets you choose the destination channel at call time.

Expected result: The MicrosoftTeams API Group appears in your API Calls panel with Content-Type set and no auth header.

3

Create the 'Send Teams Message' API Call with an Adaptive Card Body

Inside the MicrosoftTeams API Group, click '+ Add API Call'. Name it 'sendChannelMessage'. Set the method to POST. In the endpoint path field, paste the full webhook URL path (everything after the domain). Open the Variables tab and add any variables you want to inject into the message — for example: `message_title` (String), `message_body` (String), `user_email` (String). These become `{{ variable_name }}` placeholders in your request body. Switch to the Body tab, set the body type to 'JSON', and paste an Adaptive Card payload. A simple MessageCard body works for most channel webhooks. Click 'Response & Test', paste a sample response (Teams returns `1` on success), and click 'Test API Call' to confirm the message arrives in your Teams channel. If you receive a 400 Bad Request, the most common cause is a malformed JSON body — verify your Adaptive Card structure is valid. Once the test succeeds, save the API Call.

teams_message_card.json
1{
2 "@type": "MessageCard",
3 "@context": "http://schema.org/extensions",
4 "themeColor": "0076D7",
5 "summary": "{{ message_title }}",
6 "sections": [
7 {
8 "activityTitle": "{{ message_title }}",
9 "activityText": "{{ message_body }}",
10 "facts": [
11 {
12 "name": "User",
13 "value": "{{ user_email }}"
14 }
15 ],
16 "markdown": true
17 }
18 ]
19}

Pro tip: The `@type` and `@context` fields are required for MessageCard format — omitting either one causes a 400 error. For richer layouts, search 'Adaptive Card Designer' in your browser to build and preview cards visually before pasting.

Expected result: The test API Call sends a formatted card to the Teams channel. The channel shows the message with the title, body text, and user email fact row.

4

Trigger the Teams Notification from an App Action

Now connect the API Call to an action in your FlutterFlow app. Find the widget that should trigger the notification — for example, a 'Sign Up' button, a form submission confirmation widget, or a backend trigger. Click the widget to open its properties, then click '+ Add Action' in the Actions panel on the right side. Choose 'Backend/API Call' from the action types. Select your 'MicrosoftTeams' group and the 'sendChannelMessage' call. Map the variables: set `message_title` to a static string like 'New User Registered', set `message_body` to a text field value or a combination of widget state values, and set `user_email` to the current user's email from your auth provider (e.g., `currentUserEmail` from Supabase or Firebase Auth). You can also trigger this notification from a backend trigger or from the Action Flow Editor after a Supabase/Firestore write succeeds — chain it after the data-write action so the notification only fires when the save succeeds. If you want to include dynamic data like a formatted timestamp or a Firestore document field, use a Custom Function to build the string before passing it to the API Call variable.

Pro tip: Use FlutterFlow's 'Conditional Action' to only fire the Teams notification under certain conditions — for example, only if the user's subscription plan is 'Enterprise', or only if the order total exceeds $500.

Expected result: Tapping the trigger widget in Run Mode or on a real device sends the Adaptive Card to the Teams channel within a few seconds.

5

(Optional) Upgrade to Microsoft Graph for Rich Teams Access

If you need to post to channels dynamically (not a fixed webhook), send direct messages to specific users, or manage Teams programmatically, you must use the Microsoft Graph API. This requires Azure AD app registration and a client secret — credentials that cannot live in a FlutterFlow client app because they compile into the app bundle and can be extracted. The correct pattern is a Firebase Cloud Function that performs the client-credentials OAuth flow, mints a short-lived access token, and makes the Graph call. Here is how to set it up: In the Azure Portal, go to Azure Active Directory → App registrations → New registration. Give it a name, select 'Accounts in this organizational directory only', and register. In the app's API permissions, add 'ChannelMessage.Send' (Application permission) and grant admin consent. Copy the Application (client) ID, Tenant ID, and create a Client Secret under Certificates & secrets. Store all three in your Firebase Cloud Function's environment config or Secret Manager — never in FlutterFlow. Deploy the Cloud Function below. In FlutterFlow, add a new API Call to your MicrosoftTeams group pointing at your Cloud Function URL, passing message params as body variables. FlutterFlow never touches Azure credentials directly.

index.js
1// Firebase Cloud Function — Microsoft Graph proxy (index.js)
2const functions = require('firebase-functions');
3const fetch = require('node-fetch');
4
5const TENANT_ID = functions.config().teams.tenant_id;
6const CLIENT_ID = functions.config().teams.client_id;
7const CLIENT_SECRET = functions.config().teams.client_secret;
8const TEAM_ID = functions.config().teams.team_id;
9const CHANNEL_ID = functions.config().teams.channel_id;
10
11async function getGraphToken() {
12 const res = await fetch(
13 `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`,
14 {
15 method: 'POST',
16 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
17 body: new URLSearchParams({
18 grant_type: 'client_credentials',
19 client_id: CLIENT_ID,
20 client_secret: CLIENT_SECRET,
21 scope: 'https://graph.microsoft.com/.default',
22 }),
23 }
24 );
25 const data = await res.json();
26 return data.access_token;
27}
28
29exports.sendTeamsMessage = functions.https.onRequest(async (req, res) => {
30 res.set('Access-Control-Allow-Origin', '*');
31 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
32 try {
33 const { content } = req.body;
34 const token = await getGraphToken();
35 const graphRes = await fetch(
36 `https://graph.microsoft.com/v1.0/teams/${TEAM_ID}/channels/${CHANNEL_ID}/messages`,
37 {
38 method: 'POST',
39 headers: {
40 Authorization: `Bearer ${token}`,
41 'Content-Type': 'application/json',
42 },
43 body: JSON.stringify({ body: { content } }),
44 }
45 );
46 const data = await graphRes.json();
47 res.status(200).json({ success: true, id: data.id });
48 } catch (err) {
49 res.status(500).json({ error: err.message });
50 }
51});

Pro tip: If you'd rather skip the Cloud Function setup entirely, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

Expected result: The Cloud Function is deployed. A FlutterFlow API Call to the function URL posts a message to the Teams channel via Graph without any Azure credentials in the client app.

Common use cases

SaaS app that notifies the ops channel on new signups

When a new user completes registration in your FlutterFlow app, an API Call fires to the Teams webhook and posts an Adaptive Card showing the user's name, email, and plan tier to the #new-signups channel. The ops team gets instant visibility without checking a backend dashboard.

FlutterFlow Prompt

Post a Teams notification with the new user's name, email, and subscription plan every time a registration is completed in the app.

Copy this prompt to try it in FlutterFlow

Field service app that escalates job alerts to a dispatcher channel

A FlutterFlow field-service app lets technicians flag critical job issues. Tapping 'Escalate' triggers an Adaptive Card to the #dispatch Teams channel with the job ID, technician name, location, and issue description, so the dispatcher can act immediately.

FlutterFlow Prompt

When a technician taps the escalate button, send a Teams card to the dispatch channel with the job details, technician name, and GPS location.

Copy this prompt to try it in FlutterFlow

E-commerce app that posts order summaries to a fulfillment channel

When an order is placed in a FlutterFlow shopping app, a Teams message appears in the #fulfillment channel showing the order number, items, total, and shipping address. The warehouse team can pick and pack without waiting for email.

FlutterFlow Prompt

Every time an order is confirmed, post an Adaptive Card to Teams showing the order number, product list, total amount, and delivery address.

Copy this prompt to try it in FlutterFlow

Troubleshooting

400 Bad Request when POSTing to the Teams webhook

Cause: The Adaptive Card or MessageCard JSON is malformed — most commonly a missing `@type` or `@context` field, or an invalid JSON structure in the body.

Solution: Copy the exact MessageCard body from the step above and validate it with a JSON linter. Confirm that `@type` is `"MessageCard"` and `@context` is `"http://schema.org/extensions"`. Test in Postman before using FlutterFlow to isolate whether the issue is the payload or the FlutterFlow variable interpolation.

Webhook URL returns 404 or the channel stops receiving messages

Cause: The Teams channel webhook was created with the deprecated 'Incoming Webhook' connector, which Microsoft is retiring. The old connector URL no longer functions.

Solution: Recreate the webhook using the Teams 'Workflows' app: channel ⋯ → Workflows → 'Post to a channel when a webhook request is received'. Update the URL in your FlutterFlow API Call to the new Workflows URL.

Messages arrive in the wrong Teams channel

Cause: The webhook URL was generated for a different channel than intended, or you copied the wrong URL from Teams.

Solution: Open the Teams Workflows app and verify which channel each webhook is bound to. Create a separate webhook per channel and store each URL as a distinct variable in FlutterFlow so you can route messages to the right channel at call time.

403 Forbidden when calling Microsoft Graph from the Cloud Function

Cause: The Azure AD app registration is missing the `ChannelMessage.Send` Application permission, or admin consent has not been granted.

Solution: In the Azure Portal, go to your app registration → API permissions → Add permission → Microsoft Graph → Application permissions → search for `ChannelMessage.Send`. Click 'Grant admin consent for [your tenant]'. Redeploy the Cloud Function and retry.

XMLHttpRequest error when calling the Teams webhook from the FlutterFlow web preview

Cause: Teams webhook endpoints block cross-origin requests from browser origins (CORS), which only affects the web build in FlutterFlow's Run Mode preview.

Solution: This CORS block only impacts the web preview, not native iOS/Android builds. Test the API Call on a real device (use FlutterFlow Test Mode on device) or test the webhook endpoint directly in Postman. Alternatively, route even the simple webhook through a Cloud Function proxy, which removes the CORS issue for web builds.

Best practices

  • Use the Workflows-based webhook (not the deprecated Incoming Webhook connector) for all new Teams integrations — the legacy connector is being retired by Microsoft.
  • Never embed the webhook URL in a public consumer-facing app — proxy it through a Firebase Cloud Function so the URL cannot be scraped and abused to spam your channel.
  • Store the webhook URL in FlutterFlow's App Settings → App Values (constants) rather than hardcoding it in the API Call endpoint field, so you can update it without republishing.
  • Build your Adaptive Card JSON in the Adaptive Card Designer (adaptivecards.io) and validate it before pasting into FlutterFlow — malformed JSON is the most common source of 400 errors.
  • For the Microsoft Graph path, cache the access token in Cloud Function memory (invalidate after 55 minutes) rather than re-minting it on every call — token exchange counts against Azure AD rate limits.
  • Use FlutterFlow's Conditional Action to guard the Teams notification so it fires only on meaningful events, not on every tap — noisy channels reduce team attention.
  • Test your API Call using FlutterFlow's 'Response & Test' panel with a live webhook URL before wiring it to a widget action — this isolates configuration issues from UI logic issues.

Alternatives

Frequently asked questions

Do I need a paid Microsoft 365 subscription to use Teams webhooks?

Teams is available on a free tier that includes channels and the Workflows app needed to create webhooks. The free Teams plan is sufficient for webhook-based notifications from FlutterFlow. Microsoft 365 business plans add features like unlimited message history and larger meeting sizes, but are not required for this integration.

Can my FlutterFlow app receive messages FROM Teams?

No — FlutterFlow is a compiled client app and cannot host an HTTP endpoint. To receive Teams messages or events in your FlutterFlow app, you need to deploy a Cloud Function (Firebase or Supabase) that handles Teams' event subscription or webhook callbacks and writes incoming data to Firestore or a Supabase table. Your FlutterFlow app then reads and displays that data.

Is the Teams Incoming Webhook connector still supported?

Microsoft is deprecating the classic Incoming Webhook connectors and recommending the Workflows-based webhook as the replacement. If your existing webhook URL stops working, recreate it through Teams → channel ⋯ → Workflows → 'Post to a channel when a webhook request is received'. The Workflows webhook URL format is different from the old connector URL.

What is the difference between posting to a channel webhook vs using Microsoft Graph?

The channel webhook only posts to one specific channel and requires no authentication header beyond knowing the URL. Microsoft Graph lets you post to any channel, send direct messages, list team members, and manage Teams programmatically — but requires Azure AD app registration with a client secret that must be kept in a server-side Cloud Function. Start with the webhook for simple notifications and add Graph when you need dynamic channel selection or DMs.

Will the Teams message look the same on mobile and desktop Teams apps?

Adaptive Card and MessageCard rendering is consistent across the Teams desktop app and the Teams mobile app. Some advanced Adaptive Card features (like certain input types) have limited mobile support — verify your card layout in the Adaptive Card Designer's mobile preview before deploying.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire FlutterFlow integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.