To send notifications from Lovable to Microsoft Teams, create an Incoming Webhook in your Teams channel, store the webhook URL in Cloud → Secrets, and build an Edge Function that POSTs formatted Adaptive Cards to Teams. Unlike Slack — which has a native Lovable connector — Teams requires manual Edge Function setup. This pattern works for order alerts, error notifications, and approval workflows.
Send Microsoft Teams notifications from Lovable using Incoming Webhooks
Unlike Slack, which is available as a native shared connector in Lovable's Settings → Connectors panel, Microsoft Teams requires manual setup. There is no Teams connector in Lovable's built-in library, which means you need to wire it yourself using an Edge Function. The good news is that Teams' Incoming Webhook feature makes this straightforward — a webhook URL is all you need to start posting messages, and the entire setup takes about 25 minutes.
Teams supports two integration approaches. The simpler approach uses Incoming Webhooks: you create a webhook directly in a Teams channel, get a URL, and POST formatted message cards to that URL from your Edge Function. No OAuth, no token refresh, no Microsoft Graph API — just a URL and a JSON payload. This is the right choice for one-way notifications from your app to your team, like new order alerts, error reports, low-inventory warnings, or deployment notifications.
The more powerful approach uses the Microsoft Graph API with OAuth2 credentials — this lets you read messages, create channels, manage teams members, and perform two-way communication. It requires registering an app in Azure Active Directory and handling token refresh. For most Lovable integrations, Incoming Webhooks are sufficient and dramatically simpler. This guide covers the webhook approach with a note on Graph API for when you need it.
Teams Adaptive Cards are the recommended message format. Unlike plain text or legacy MessageCard format, Adaptive Cards render structured, visually appealing messages with headings, facts, action buttons, and images — and they are supported across all Teams clients. Lovable's AI can generate Adaptive Card JSON payloads from natural language descriptions of what your notification should contain.
Integration method
Microsoft Teams has no native Lovable connector. Notifications are sent via Teams Incoming Webhooks or the Microsoft Graph API, both of which are called from a Lovable Edge Function. The webhook URL or Graph API credentials are stored in Cloud → Secrets, and the Edge Function constructs and POSTs Adaptive Card payloads to Teams channels.
Prerequisites
- A Lovable project with at least one deployed app (Edge Functions require Lovable Cloud)
- Microsoft Teams access with permission to add connectors to a channel (Team Owner or Member with Manage Channel permission)
- A Teams channel where you want to receive notifications (create a dedicated #alerts or #notifications channel for clarity)
- Basic understanding of what an Edge Function does in Lovable (server-side Deno function that runs on Lovable Cloud)
Step-by-step guide
Create an Incoming Webhook connector in your Teams channel
Create an Incoming Webhook connector in your Teams channel
The first step happens entirely in Microsoft Teams, not in Lovable. You need to create an Incoming Webhook in the Teams channel where you want to receive notifications. This generates a unique URL that your Edge Function will POST to. Open Microsoft Teams and navigate to the channel where you want notifications to appear. Click the three-dot menu (...) next to the channel name in the sidebar. Select 'Manage channel' from the dropdown. In the channel settings panel, find the Connectors section and click 'Edit' or look for the 'Connectors' option. If you are in newer Teams (Teams 2.0), the path may be slightly different: click the channel name → More options → Connectors. In the Connectors dialog, search for 'Incoming Webhook' in the search box. Click the 'Incoming Webhook' connector and then click 'Configure'. Give your webhook a descriptive name — something like 'Lovable App Notifications' — so your team knows what it is. Optionally, upload a small icon (your app logo works well) that will appear next to notifications posted by this webhook. Click 'Create'. Teams will generate a unique webhook URL that looks like: https://yourcompany.webhook.office.com/webhookb2/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/IncomingWebhook/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Copy this URL immediately. It is your private channel endpoint — anyone with this URL can post messages to your Teams channel, so treat it like a password. Click 'Done' to save the connector.
Pro tip: Create a dedicated Teams channel for app notifications (e.g., #app-notifications or #alerts) rather than posting to a general chat channel. This keeps your team's conversations separate from automated messages.
Expected result: A unique Incoming Webhook URL is created for your Teams channel. The channel now shows 'Incoming Webhook' in its Connectors list. Messages sent to this URL will appear as posts in the channel.
Store the Teams webhook URL in Lovable Cloud Secrets
Store the Teams webhook URL in Lovable Cloud Secrets
With the webhook URL copied, store it in Lovable's Cloud Secrets panel. The webhook URL is sensitive — it grants anyone who has it the ability to post messages to your Teams channel on behalf of your connector. Storing it as a secret ensures it stays server-side, inaccessible to your frontend JavaScript and absent from your Git repository. In your Lovable project, click the '+' icon at the top of the editor (next to the Preview label). In the Cloud panel that opens, click the 'Secrets' tab. Click 'Add new secret'. In the Name field, type TEAMS_WEBHOOK_URL exactly. In the Value field, paste the full Incoming Webhook URL you copied from Teams. Click Save. If you plan to send notifications to multiple Teams channels (for example, one channel for orders and another for errors), add each webhook as a separate secret: TEAMS_ORDERS_WEBHOOK_URL, TEAMS_ALERTS_WEBHOOK_URL, and so on. This naming convention makes it obvious in your Edge Function code which channel each notification goes to. As always with Lovable secrets: never paste the webhook URL directly into Lovable's chat prompt. Even though a webhook URL is not an API key in the traditional sense, it is still a credential that should not appear in code or chat history. The secret panel is the only appropriate storage location.
Pro tip: Teams Incoming Webhook URLs do not expire by default, but you can delete and recreate them in the Teams channel settings at any time if a URL is compromised. Treat them as you would any other credential.
Expected result: TEAMS_WEBHOOK_URL appears in your Cloud → Secrets panel with its value masked. Your Edge Function in the next step will access it via Deno.env.get('TEAMS_WEBHOOK_URL').
Create the Teams notification Edge Function
Create the Teams notification Edge Function
Now create the Edge Function that formats and sends notifications to Teams. The function will receive notification data from your frontend, construct an Adaptive Card payload, and POST it to the Teams webhook URL from Secrets. Adaptive Cards are the recommended message format for Teams. They support rich formatting: headings, fact tables, images, action buttons, and conditional visibility. The Adaptive Card format is JSON, and Teams renders it natively on all platforms (desktop, mobile, web). The code example below shows a complete Adaptive Card for a generic notification, which you can customize for your specific use case. Important: Teams Incoming Webhooks accept two payload formats. The legacy format uses 'type': 'MessageCard' — this still works but is being deprecated. The modern format uses Adaptive Card syntax wrapped in a specific Teams container. The code below uses the modern format. Some older Teams clients may fall back to a plain text summary if Adaptive Cards are not supported, which is why the payload includes a 'summary' field. The function handles CORS headers for browser calls, validates that the webhook URL is configured, and returns appropriate error messages if the Teams API rejects the request. Teams webhooks return a '1' string response on success (not a JSON object), so the success check is string-based.
Create an Edge Function called notify-teams that accepts a POST request with { title, message, severity, facts, actionUrl, actionLabel } where facts is an array of { name, value } pairs. It should retrieve TEAMS_WEBHOOK_URL from Deno environment variables and POST an Adaptive Card to Teams. Include CORS headers and handle the OPTIONS preflight. Return a success or error response.
Paste this in Lovable chat
1import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'23const corsHeaders = {4 'Access-Control-Allow-Origin': '*',5 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',6}78const severityColors: Record<string, string> = {9 info: 'Good',10 warning: 'Warning',11 high: 'Attention',12 critical: 'Attention',13}1415serve(async (req) => {16 if (req.method === 'OPTIONS') {17 return new Response('ok', { headers: corsHeaders })18 }1920 try {21 const { title, message, severity = 'info', facts = [], actionUrl, actionLabel } = await req.json()2223 const webhookUrl = Deno.env.get('TEAMS_WEBHOOK_URL')24 if (!webhookUrl) {25 throw new Error('TEAMS_WEBHOOK_URL secret is not configured')26 }2728 const adaptiveCard = {29 type: 'message',30 attachments: [31 {32 contentType: 'application/vnd.microsoft.card.adaptive',33 contentUrl: null,34 content: {35 '$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',36 type: 'AdaptiveCard',37 version: '1.5',38 body: [39 {40 type: 'TextBlock',41 text: title,42 size: 'Large',43 weight: 'Bolder',44 color: severityColors[severity] || 'Default',45 },46 {47 type: 'TextBlock',48 text: message,49 wrap: true,50 },51 ...(facts.length > 052 ? [{53 type: 'FactSet',54 facts: facts.map((f: { name: string; value: string }) => ({55 title: f.name,56 value: f.value,57 })),58 }]59 : []),60 ],61 actions: actionUrl62 ? [{63 type: 'Action.OpenUrl',64 title: actionLabel || 'View Details',65 url: actionUrl,66 }]67 : [],68 },69 },70 ],71 }7273 const response = await fetch(webhookUrl, {74 method: 'POST',75 headers: { 'Content-Type': 'application/json' },76 body: JSON.stringify(adaptiveCard),77 })7879 const responseText = await response.text()80 if (!response.ok || responseText === '0') {81 throw new Error(`Teams webhook failed: ${response.status} - ${responseText}`)82 }8384 return new Response(85 JSON.stringify({ success: true }),86 { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }87 )88 } catch (error) {89 return new Response(90 JSON.stringify({ error: error.message }),91 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }92 )93 }94})Pro tip: Teams Incoming Webhooks return the string '1' on success and '0' on failure. The code above checks for both the HTTP status and the response body to detect failures correctly.
Expected result: Lovable creates and deploys supabase/functions/notify-teams/index.ts. The function appears in Cloud → Edge Functions. It accepts POST requests with notification data and sends Adaptive Cards to your Teams channel.
Trigger Teams notifications from your app
Trigger Teams notifications from your app
With the Edge Function deployed, connect it to meaningful events in your Lovable app. Use the Supabase client's functions.invoke() to call the notification function from your React components or from other Edge Functions. The most impactful places to add Teams notifications are: after a successful payment (notify the sales team), when a user submits a support request (alert the support channel), when a scheduled task completes or fails (inform the engineering team), or when a form submission requires human review (ping the moderation team). For React component triggers, call the function in an event handler. For automated triggers based on database changes, consider adding the Teams notification call inside other Edge Functions — for example, your Stripe webhook handler can call notify-teams after processing a payment. The code example below shows how to call the notification function from a React component after a user action. The invoke() call is non-blocking — wrap it in a try-catch and do not let notification failures interrupt the user's main flow. If Teams is temporarily unavailable, your app should continue working normally.
After a user submits the contact form in my app, call the notify-teams Edge Function using supabase.functions.invoke() to send a Teams notification with the title 'New Contact Form Submission', the user's message and email as facts, and a link to the admin panel. Handle errors silently so the form submission still succeeds even if the Teams notification fails.
Paste this in Lovable chat
1import { supabase } from '@/lib/supabase'23const notifyTeams = async (params: {4 title: string5 message: string6 severity?: 'info' | 'warning' | 'high'7 facts?: Array<{ name: string; value: string }>8 actionUrl?: string9 actionLabel?: string10}) => {11 try {12 const { error } = await supabase.functions.invoke('notify-teams', {13 body: params,14 })15 if (error) console.error('Teams notification failed:', error)16 } catch (err) {17 // Silently fail — notification should not break the main flow18 console.error('Teams notification error:', err)19 }20}2122// Example usage after a form submission:23const handleContactSubmit = async (formData: ContactFormData) => {24 // 1. Save to database25 const { error } = await supabase.from('contact_submissions').insert(formData)26 if (error) throw error2728 // 2. Notify Teams (non-blocking)29 notifyTeams({30 title: 'New Contact Form Submission',31 message: formData.message.substring(0, 200),32 severity: 'info',33 facts: [34 { name: 'From', value: formData.email },35 { name: 'Subject', value: formData.subject },36 { name: 'Submitted', value: new Date().toLocaleString() },37 ],38 actionUrl: 'https://myapp.com/admin/contacts',39 actionLabel: 'View in Admin',40 })4142 // 3. Continue with success flow43 return { success: true }44}Pro tip: Create a shared notifyTeams() helper function in src/lib/notify.ts that all components and Edge Functions can import. This keeps the invoke logic in one place and makes it easy to add retry logic or additional notification channels later.
Expected result: When the triggering event occurs in your app, an Adaptive Card appears in your Teams channel within seconds. Cloud → Logs shows the notify-teams Edge Function executed successfully.
Common use cases
Send new order notifications to a sales team channel
When a customer completes a purchase in your Lovable app, post an Adaptive Card to your Teams #sales channel with the order details — customer name, items purchased, order total, and a link to the admin panel. This keeps the sales team informed in real time without checking a separate dashboard.
Create an Edge Function called notify-teams-order that accepts a POST request with { customerName, orderTotal, items, orderId } and sends an Adaptive Card to the Teams webhook URL stored as TEAMS_WEBHOOK_URL in secrets. The card should have a heading 'New Order Received', show customer name and total as facts, list the items, and include an action button linking to /admin/orders/{orderId}.
Copy this prompt to try it in Lovable
Alert a DevOps channel when an Edge Function throws an error
Add error monitoring to your Edge Functions by catching unhandled exceptions and posting them to a Teams #alerts channel. Include the function name, error message, stack trace, and timestamp so your team can respond quickly without setting up external monitoring tools.
Update my existing Edge Functions to catch any unhandled errors and send an alert to Teams using TEAMS_WEBHOOK_URL from secrets. The alert should be an Adaptive Card with severity 'High', include the function name, error message, and timestamp. Create a shared notifyTeamsError helper function that all Edge Functions can call from their catch blocks.
Copy this prompt to try it in Lovable
Post approval requests to a Teams channel for content moderation
When users submit content that needs human review (job listings, product descriptions, user profiles), post an Adaptive Card to a #moderation Teams channel. Include the content preview, submitter details, and Approve/Reject action buttons that call back to your Lovable Edge Function to update the database record.
Create a moderation workflow: when a new listing is submitted in my app, send an Adaptive Card to Teams via TEAMS_WEBHOOK_URL with the listing title, description preview, submitter name, and two action buttons — Approve and Reject. Each button should trigger a callback to my Edge Function at /functions/v1/moderate-listing with the listingId and decision.
Copy this prompt to try it in Lovable
Troubleshooting
Teams webhook returns '0' or HTTP 400 with 'Summary or Text is required'
Cause: The Adaptive Card payload is missing a required 'summary' field at the top level. Teams requires a text summary for accessibility and notification previews even when using Adaptive Cards.
Solution: Add a 'summary' field to the top-level payload object alongside the 'attachments' array. This summary text appears in Teams notification banners and activity feeds. Update the adaptiveCard object to include: { type: 'message', summary: title, attachments: [...] }.
1const adaptiveCard = {2 type: 'message',3 summary: title, // Add this line4 attachments: [5 // ... your existing attachments6 ],7}Teams posts appear but Adaptive Cards render as plain text instead of formatted cards
Cause: The Teams client version or channel type does not support Adaptive Cards, or the payload format uses the legacy MessageCard type which renders differently.
Solution: Verify you are using the modern Adaptive Card format with contentType: 'application/vnd.microsoft.card.adaptive'. Also check that the Adaptive Card version is set to '1.2' or higher — some Teams tenants may not support the latest version. Try lowering the version to '1.2' for maximum compatibility. If the issue persists, ensure the Teams channel is a standard channel (not a private channel or shared channel, which have different connector behavior).
1// Change version to 1.2 for maximum Teams client compatibility:2content: {3 '$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',4 type: 'AdaptiveCard',5 version: '1.2', // Lower version for compatibility6 // ... rest of card7}Edge Function returns 'TEAMS_WEBHOOK_URL secret is not configured' even after adding the secret
Cause: Secrets added after an Edge Function was last deployed are not automatically available — functions need to be redeployed to pick up new environment variables.
Solution: After adding the TEAMS_WEBHOOK_URL secret in Cloud → Secrets, trigger a redeployment of the Edge Function. In Lovable, the easiest way to do this is to open a chat prompt and ask Lovable to 'make a minor update to the notify-teams Edge Function to redeploy it'. Alternatively, you can add an innocuous comment line to the function code to trigger a new deployment.
Teams shows the notification but the Incoming Webhook connector was deleted from the channel
Cause: A Teams admin or channel owner removed the Incoming Webhook connector from the channel settings, invalidating the webhook URL stored in your secrets.
Solution: Go to Teams → channel → Manage channel → Connectors and check if Incoming Webhook still appears. If it was deleted, you need to create a new one following Step 1 of this guide. The new webhook will have a different URL — update the TEAMS_WEBHOOK_URL secret in Cloud → Secrets with the new URL. No code changes are required since the function reads the URL from the secret at runtime.
Best practices
- Create dedicated Teams channels for different notification categories (e.g., #app-alerts, #new-orders, #support-requests) rather than posting everything to a general channel — this prevents notification fatigue.
- Always include a 'summary' field in your Teams payload alongside the Adaptive Card attachments for accessibility and notification banner support.
- Store separate webhook URLs for different channels as separate secrets (TEAMS_ORDERS_WEBHOOK_URL, TEAMS_ALERTS_WEBHOOK_URL) rather than one URL for everything.
- Never let Teams notification failures block your main application flow — always wrap notify calls in try-catch and fail silently if Teams is temporarily unreachable.
- Use Adaptive Card severity colors (Good for info, Warning for caution, Attention for critical) consistently across all your notifications so team members can immediately gauge urgency at a glance.
- For high-volume notifications, implement rate limiting in your Edge Function — Teams Incoming Webhooks have a rate limit of roughly 4 requests per second, and exceeding it results in 429 throttling errors.
- Test your Adaptive Card designs using the Adaptive Cards Designer at adaptivecards.io/designer before implementing them in your Edge Function, to see exactly how they will render across different Teams clients.
Alternatives
Choose Slack if your team uses it instead of Teams — Slack is a native Lovable connector with simpler chat-driven setup and no manual Edge Function coding required.
Choose SendGrid if you prefer email alerts over Teams messages, especially for notifications that need to reach people outside your Teams organization.
Choose Twilio if you need SMS or WhatsApp alerts that reach team members on mobile without requiring them to be in Teams.
Frequently asked questions
Is there a native Lovable connector for Microsoft Teams?
No — as of March 2026, Microsoft Teams does not have a native Lovable shared connector. Slack is the team communication tool with a native connector in Lovable's Settings → Connectors panel. For Teams, you need to manually create an Incoming Webhook in Teams and build an Edge Function in Lovable to call it. This guide covers the complete process.
What is the difference between Teams Incoming Webhooks and the Microsoft Graph API?
Incoming Webhooks are one-way: your app can POST messages to a Teams channel but cannot read messages or take other actions. They are simple to set up (just a URL, no OAuth) and are perfect for notifications and alerts. The Microsoft Graph API supports two-way communication — reading messages, creating channels, managing team members — but requires registering an Azure AD application, handling OAuth2 flows, and managing token refresh. For most Lovable notification use cases, Incoming Webhooks are sufficient and much simpler.
Can I send Teams notifications from database triggers without user action?
Yes — the best pattern is to call the notify-teams Edge Function from within another Edge Function that processes database events. For example, your Stripe webhook handler can notify Teams after a payment. You can also create a Supabase database function trigger that calls the Edge Function when specific table rows are inserted or updated. Lovable's AI can help you set up this pattern if you describe the database event you want to monitor.
How do I add interactive Approve/Reject buttons to Teams notifications?
Add 'Action.Submit' actions to your Adaptive Card and configure them to POST data to your Edge Function's URL. Teams will send a POST request to your actionUrl when a user clicks the button, including the card data. Your Edge Function then processes the action (e.g., updates the database record and sends a confirmation message). Note that Action.Submit in Incoming Webhook messages has limitations — for full interactivity, you may need to use Azure Bot Service or Power Automate flows.
Will Teams notifications still work if my Lovable app is paused or in maintenance mode?
Teams notifications are sent by your Edge Functions, which run on Lovable Cloud infrastructure. As long as the Edge Function is deployed and Lovable Cloud is operational, notifications will be sent regardless of whether your app's frontend is being accessed. If Lovable Cloud has an outage, both your app and notifications will be unavailable until service is restored.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation