Microsoft Teams Integration
Enterprise-grade Microsoft Teams integration for OneApp — bot messaging, embedded tab apps, real-time notifications, meeting briefs, and cross-platform activity tracking.
Quick Start
Already familiar with Teams apps? Skip to Quick Start →
Why Teams integration?
Without Teams integration:
- Context switching — Users leave Teams to access OneApp, lose workflow momentum
- Manual updates — Copy-paste information between Teams and OneApp
- Missed notifications — Important canvas updates lost in email or separate apps
- Meeting prep burden — Manually gather context before meetings
- Disconnected activity — No visibility into cross-platform usage
Teams integration solves this with embedded canvas access, bot-powered messaging, real-time notifications, pre-meeting briefs, and unified activity tracking.
Production-ready with Azure AD SSO, Adaptive Cards v1.4, Graph API integration, Server-Sent Events for real-time updates, and comprehensive error handling.
Use cases
- In-Teams canvas access — View and interact with canvases without leaving Teams
- Bot conversations — Ask questions, get insights, run reports via Teams chat
- Real-time notifications — Instant alerts for mentions, approvals, canvas updates
- Meeting integration — Pre-meeting briefs with relevant canvases, post-meeting summaries
- Activity tracking — Unified view of user activity across Teams and web
- Channel integration — Link Teams channels to canvases for team collaboration
Architecture overview
┌─────────────────────────────────────────────────────────────────┐
│ Microsoft Teams │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Bot App │ │ Tab App │ │ Meeting Side Panel │ │
│ │ (Messages) │ │ (Dashboard) │ │ (Briefs/Notes) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
└─────────┼─────────────────┼─────────────────────┼───────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ OneApp Backend │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ /api/teams │ │ /teams-tab │ │ /api/teams/meetings │ │
│ │ webhooks │ │ pages │ │ integration │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Teams Service Layer │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │
│ │ │ Graph API │ │ Bot SDK │ │ Notifications SSE │ │ │
│ │ │ Client │ │ Handler │ │ Service │ │ │
│ │ └────────────┘ └────────────┘ └────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘Prerequisites
Before setting up Teams integration, ensure you have:
Bot Framework Deprecation
Microsoft Bot Framework SDK support ends December 31, 2025. New Teams apps should use the Teams AI v2 SDK. Plan migration from Bot Framework to Teams AI v2.
Azure AD App Registration
- Azure Portal access with Application Administrator role
- App Registration with the following API permissions:
User.Read— Basic user profileChannel.ReadBasic.All— Read channel infoChannelMessage.Send— Send messages to channelsTeam.ReadBasic.All— Read team infoTeamsTab.ReadWrite.All— Manage tabsOnlineMeetings.Read— Read meeting info
Teams Admin Center
- Teams admin access to upload custom apps
- Custom app policy allowing sideloaded apps (for development)
- App catalog access for organization-wide deployment
Environment Variables
# Azure AD Configuration
AZURE_AD_CLIENT_ID=your-client-id
AZURE_AD_CLIENT_SECRET=your-client-secret
AZURE_AD_TENANT_ID=your-tenant-id
# Teams Bot Configuration
TEAMS_BOT_ID=your-bot-id
TEAMS_BOT_PASSWORD=your-bot-password
# App URLs
NEXT_PUBLIC_APP_URL=https://oneapp.onedigital.com
TEAMS_WEBHOOK_URL=https://oneapp.onedigital.com/api/integrations/teams/webhooksQuick Start
1. Install dependencies
# Teams SDK and Graph API client
pnpm --filter=oneapp-onstage add @microsoft/teams-js @microsoft/microsoft-graph-client
# Bot Framework (if not installed)
pnpm --filter=oneapp-onstage add botbuilder2. Configure environment
Create or update .env.local:
AZURE_AD_CLIENT_ID=your-azure-ad-client-id
AZURE_AD_CLIENT_SECRET=your-azure-ad-client-secret
AZURE_AD_TENANT_ID=your-azure-ad-tenant-id
TEAMS_BOT_ID=your-teams-bot-id
TEAMS_BOT_PASSWORD=your-teams-bot-password3. Deploy Teams manifest
# Navigate to Teams app directory
cd platform/apps/oneapp-onstage/teams-app
# Update manifest.json with your app IDs
# Then create the app package
zip -r oneapp-teams.zip manifest.json icon-color.png icon-outline.png
# Upload to Teams Admin Center or sideload for testing4. Test the integration
- Open Microsoft Teams
- Search for "OneApp" in the app catalog
- Install the app to a team or personal scope
- Start a conversation with the bot
Features
Bot Messaging
The Teams bot enables natural language interaction with OneApp canvases.
import { handleTeamsMessage } from "#/lib/teams";
// Bot receives message and processes it
const response = await handleTeamsMessage({
userId: activity.from.id,
text: activity.text,
conversationId: activity.conversation.id
});
// Send response as Adaptive Card
await context.sendActivity({
attachments: [CardFactory.adaptiveCard(response.card)]
});Supported commands:
- Ask questions about canvas content
- Request insights and reports
- Get canvas summaries
- Search across canvases
Tab App
Embed OneApp dashboards and canvases directly in Teams.
Personal Tab — User's personal dashboard with recent canvases:
"use client";
import { useEffect, useState } from "react";
import * as microsoftTeams from "@microsoft/teams-js";
export default function TeamsTabPage() {
const [initialized, setInitialized] = useState(false);
useEffect(() => {
microsoftTeams.app.initialize().then(() => {
setInitialized(true);
});
}, []);
if (!initialized) return <div>Loading Teams context...;
return <CanvasDashboard />;
}Configurable Tab — Add canvases to channels:
export async function GET(): Promise<Response> {
const html = `
<!DOCTYPE html>
<html>
<head>
<script src="https://res.cdn.office.net/teams-js/2.47.2/js/MicrosoftTeams.min.js"></script>
</head>
<body>
<h1>Configure OneApp Tab</h1>
<select id="canvasSelect">
<option value="dashboard">Dashboard</option>
<option value="canvas">Specific Canvas</option>
</select>
<script>
microsoftTeams.app.initialize();
microsoftTeams.pages.config.registerOnSaveHandler((saveEvent) => {
microsoftTeams.pages.config.setConfig({
suggestedDisplayName: "OneApp",
contentUrl: window.location.origin + "/teams-tab",
});
saveEvent.notifySuccess();
});
</script>
</body>
</html>
`;
return new Response(html, { headers: { "Content-Type": "text/html" } });
}Real-Time Notifications
Server-Sent Events (SSE) for instant notifications in Teams.
:::warning Webhook Performance Graph webhook notifications must be processed within 10 seconds:
- If you can process within 3 seconds, return
200 OK - If processing takes longer, persist to a queue and return
202 Accepted - If you take >10 seconds, Microsoft Graph will retry or drop the notification :::
import { sendNotification, NotificationType } from "#/lib/teams/notifications";
// Send notification to user
await sendNotification({
userId: "user-123",
type: NotificationType.CANVAS_MENTION,
title: "You were mentioned",
body: "John mentioned you in Q4 Planning canvas",
data: { canvasId: "canvas-456" }
});Notification types:
MESSAGE— New messages in linked channelsAPPROVAL_REQUEST— Approval workflow requestsCANVAS_ACCESS— Canvas shared with userINSIGHT_READY— AI insight generation completeMEETING_STARTING— Linked meeting about to startMENTION— User mentioned in canvas
Configure notification preferences:
import { NotificationPreferences } from "#/components/teams/notification-preferences";
// User can configure which notifications they receive
<NotificationPreferences
userId={session.user.id}
onSave={handlePreferencesSave}
/>Meeting Integration
Pre-meeting briefs and post-meeting summaries with AI-powered insights.
import {
generatePreMeetingBrief,
generatePostMeetingSummary,
createPreMeetingBriefCard
} from "#/lib/teams/meeting-integration";
// Generate pre-meeting brief
const brief = await generatePreMeetingBrief({
meetingId: "meeting-123",
userId: "user-456",
attendees: ["user-789", "user-012"]
});
// Create Adaptive Card for Teams
const card = createPreMeetingBriefCard(brief);
// Send to meeting chat
await sendToMeetingChat(meetingId, card);Brief includes:
- Meeting agenda and context
- Relevant canvases for the meeting
- Recent activity from attendees
- AI-suggested discussion points
Post-meeting summary:
- Action items extracted from notes
- Key decisions documented
- Follow-up tasks assigned
- Canvas updates suggested
API Routes
Webhooks
Handle incoming Teams events:
POST /api/integrations/teams/webhooksProcesses bot messages, channel events, and meeting notifications.
Messages
Send messages to Teams channels:
POST /api/integrations/teams/messages// Request body
{
channelId: string;
message: string;
cardData?: AdaptiveCardData;
}Notifications
Stream endpoint (SSE):
GET /api/integrations/teams/notifications/streamPreferences endpoint:
GET/PUT /api/integrations/teams/notifications/preferencesTab Configuration
GET /api/integrations/teams/tab/configReturns HTML configuration page for Teams tab setup.
Teams Manifest
The Teams app manifest defines your app's capabilities:
{
"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
"manifestVersion": "1.16",
"version": "1.4.0",
"id": "{{TEAMS_APP_ID}}",
"packageName": "com.onedigital.oneapp.teams",
"name": {
"short": "OneApp",
"full": "OneApp - AI-Powered Canvas Platform"
},
"description": {
"short": "Access OneApp canvases in Teams",
"full": "Seamlessly access your OneApp canvases, get AI-powered insights, and collaborate with your team without leaving Microsoft Teams."
},
"developer": {
"name": "OneDigital",
"websiteUrl": "https://oneapp.onedigital.com",
"privacyUrl": "https://oneapp.onedigital.com/privacy",
"termsOfUseUrl": "https://oneapp.onedigital.com/terms"
},
"bots": [
{
"botId": "{{TEAMS_BOT_ID}}",
"scopes": ["personal", "team", "groupchat"],
"supportsFiles": false,
"isNotificationOnly": false,
"commandLists": [
{
"scopes": ["personal", "team"],
"commands": [
{ "title": "help", "description": "Get help with OneApp" },
{ "title": "search", "description": "Search your canvases" },
{ "title": "recent", "description": "View recent canvases" }
]
}
]
}
],
"staticTabs": [
{
"entityId": "oneapp-dashboard",
"name": "Dashboard",
"contentUrl": "https://oneapp.onedigital.com/teams-tab",
"scopes": ["personal"]
}
],
"configurableTabs": [
{
"configurationUrl": "https://oneapp.onedigital.com/api/integrations/teams/tab/config",
"canUpdateConfiguration": true,
"scopes": ["team", "groupchat"],
"context": ["channelTab", "privateChatTab", "meetingChatTab", "meetingSidePanel"]
}
],
"permissions": ["identity", "messageTeamMembers"],
"validDomains": ["oneapp.onedigital.com", "*.onedigital.com"]
}Mobile Compatibility
Important: Microsoft Teams mobile apps only support Adaptive Cards up to version 1.2. Cards using v1.4 or v1.5 features may not render correctly on mobile devices.
If your organization has mobile users:
- Use Adaptive Cards v1.2 or lower
- If using v1.4/1.5 features, include
fallbackTextproperty - Test on Teams mobile app (iOS/Android) before deploying
Activity Tracking
Track user activity across Teams and web for unified analytics.
import { logTeamsActivity, ActivityType } from "#/lib/teams/activity-logger";
// Log when user views canvas in Teams
await logTeamsActivity({
userId: "user-123",
activityType: ActivityType.CANVAS_VIEW,
metadata: {
canvasId: "canvas-456",
source: "teams-tab",
teamId: "team-789"
}
});Activity types:
BOT_MESSAGE— User sent message to botCANVAS_VIEW— Canvas viewed in Teams tabSSO_LOGIN— User authenticated via Teams SSOAPPROVAL_ACTION— Approval request handledREPORT_GENERATED— Report created from Teams
Testing
Local Development
-
Use ngrok for local webhook testing:
ngrok http 3000 -
Update manifest with ngrok URL:
"validDomains": ["your-ngrok-url.ngrok.io"] -
Sideload the app in Teams Developer Portal
Test Scenarios
| Scenario | Steps | Expected Result |
|---|---|---|
| Bot message | Send "help" to bot | Receive help card |
| Tab load | Open personal tab | Dashboard displays |
| Notification | Trigger canvas mention | SSE notification received |
| Meeting brief | Join meeting with linked canvas | Pre-meeting brief card appears |
Debugging
Enable debug logging:
DEBUG=teams:* pnpm devCheck Teams Developer Portal for:
- Bot message delivery status
- Tab loading errors
- Manifest validation issues
Deployment
Production Checklist
- Azure AD app configured with production redirect URIs
- Teams manifest updated with production URLs
- Environment variables set in production
- SSL certificates valid for all domains
- Rate limiting configured for webhook endpoints
- Error monitoring enabled (Sentry/LogRocket)
Teams Admin Center Deployment
-
Create app package:
cd teams-app zip -r oneapp-teams.zip manifest.json icon-*.png -
Upload to Admin Center:
- Go to Teams Admin Center → Teams apps → Manage apps
- Click "Upload" and select the zip file
- Configure app policies for your organization
-
Monitor adoption:
- Check usage analytics in Admin Center
- Review bot conversation metrics
- Track tab engagement
Troubleshooting
Common Issues
Bot not responding:
- Verify
TEAMS_BOT_IDandTEAMS_BOT_PASSWORDare correct - Check webhook URL is accessible from Teams
- Ensure bot is enabled in Azure Bot Service
Tab not loading:
- Confirm
validDomainsincludes your app URL - Check for mixed content (HTTPS required)
- Verify Teams JS SDK is initializing
SSO failures:
- Azure AD app must have Teams SSO configured
- Token audience must match your app ID
- Redirect URIs must be registered
Notifications not received:
- Check SSE connection is established
- Verify user has notifications enabled
- Confirm notification preferences allow the type
Error Codes
| Code | Description | Resolution |
|---|---|---|
TEAMS_001 | Bot authentication failed | Check bot credentials |
TEAMS_002 | Graph API permission denied | Add required permissions |
TEAMS_003 | Tab context unavailable | Ensure Teams SDK initialized |
TEAMS_004 | Meeting not found | Verify meeting ID and permissions |