microsoft-teamsMicrosoft Teams API integration with managed OAuth. Manage teams, channels, messages, and meetings via Microsoft Graph API. Use this skill when users want to...
Install via ClawdBot CLI:
clawdbot install byungkyu/microsoft-teamsAccess the Microsoft Teams API with managed OAuth authentication via Microsoft Graph. Manage teams, channels, messages, meetings, and access recordings and transcripts.
# List user's joined teams
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/microsoft-teams/v1.0/me/joinedTeams')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://gateway.maton.ai/microsoft-teams/{native-api-path}
Replace {native-api-path} with the actual Microsoft Graph API endpoint path. The gateway proxies requests to graph.microsoft.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Microsoft Teams OAuth connections at https://ctrl.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=microsoft-teams&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'microsoft-teams'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "fb0fdc4a-0b5a-40cf-8b92-3bdae848cde3",
"status": "ACTIVE",
"creation_time": "2026-02-17T09:51:21.074601Z",
"last_updated_time": "2026-02-17T09:51:34.323814Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "microsoft-teams",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Microsoft Teams connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/microsoft-teams/v1.0/me/joinedTeams')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', 'fb0fdc4a-0b5a-40cf-8b92-3bdae848cde3')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If omitted, the gateway uses the default (oldest) active connection.
GET /microsoft-teams/v1.0/me/joinedTeams
Response:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams",
"@odata.count": 1,
"value": [
{
"id": "b643f103-870d-4f98-a23d-e6f164fae33e",
"displayName": "carvedai.com",
"description": null,
"isArchived": false,
"tenantId": "cb83c3f9-6d16-4cf3-bd8c-ab16b37932f9"
}
]
}
GET /microsoft-teams/v1.0/teams/{team-id}
GET /microsoft-teams/v1.0/teams/{team-id}/channels
Response:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams('...')/channels",
"@odata.count": 1,
"value": [
{
"id": "19:9fwtZjo3IM0D8bLdQqR-_oMFw1eUDlzWjPfIhNGhVd41@thread.tacv2",
"createdDateTime": "2026-02-16T20:09:27.254Z",
"displayName": "General",
"description": null,
"email": "carvedai.com473@carvedai.com",
"membershipType": "standard",
"isArchived": false
}
]
}
GET /microsoft-teams/v1.0/teams/{team-id}/channels?$filter=membershipType eq 'private'
GET /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}
POST /microsoft-teams/v1.0/teams/{team-id}/channels
Content-Type: application/json
{
"displayName": "New Channel",
"description": "Channel description",
"membershipType": "standard"
}
Response:
{
"id": "19:3b3361df822044558a062bb1a4ac8357@thread.tacv2",
"createdDateTime": "2026-02-17T20:24:33.9284462Z",
"displayName": "Maton Test Channel",
"description": "Channel created by Maton integration test",
"membershipType": "standard",
"isArchived": false
}
PATCH /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}
Content-Type: application/json
{
"description": "Updated description"
}
Returns 204 No Content on success. Note: The default "General" channel cannot be updated.
DELETE /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}
Returns 204 No Content on success.
GET /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/members
Response:
{
"@odata.count": 1,
"value": [
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"id": "MCMjMiMj...",
"roles": ["owner"],
"displayName": "Kevin Kim",
"userId": "5f56d55b-2ffb-448d-982a-b52547431f71",
"email": "richard@carvedai.com"
}
]
}
GET /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages
POST /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages
Content-Type: application/json
{
"body": {
"content": "Hello World"
}
}
Response:
{
"id": "1771359569239",
"replyToId": null,
"messageType": "message",
"createdDateTime": "2026-02-17T20:19:29.239Z",
"importance": "normal",
"locale": "en-us",
"from": {
"user": {
"id": "5f56d55b-2ffb-448d-982a-b52547431f71",
"displayName": "Kevin Kim",
"userIdentityType": "aadUser",
"tenantId": "cb83c3f9-6d16-4cf3-bd8c-ab16b37932f9"
}
},
"body": {
"contentType": "text",
"content": "Hello World"
},
"channelIdentity": {
"teamId": "b643f103-870d-4f98-a23d-e6f164fae33e",
"channelId": "19:9fwtZjo3IM0D8bLdQqR-_oMFw1eUDlzWjPfIhNGhVd41@thread.tacv2"
}
}
POST /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages
Content-Type: application/json
{
"body": {
"contentType": "html",
"content": "<h1>Hello</h1><p>This is <strong>formatted</strong> content.</p>"
}
}
POST /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies
Content-Type: application/json
{
"body": {
"content": "This is a reply"
}
}
GET /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages/{message-id}/replies
PATCH /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/messages/{message-id}
Content-Type: application/json
{
"body": {
"content": "Updated message content"
}
}
Returns 204 No Content on success.
GET /microsoft-teams/v1.0/teams/{team-id}/members
Response:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams('...')/members",
"@odata.count": 1,
"value": [
{
"@odata.type": "#microsoft.graph.aadUserConversationMember",
"id": "MCMjMSMj...",
"roles": ["owner"],
"displayName": "Kevin Kim",
"userId": "5f56d55b-2ffb-448d-982a-b52547431f71",
"email": "richard@carvedai.com",
"tenantId": "cb83c3f9-6d16-4cf3-bd8c-ab16b37932f9"
}
]
}
GET /microsoft-teams/v1.0/me/presence
Response:
{
"id": "5f56d55b-2ffb-448d-982a-b52547431f71",
"availability": "Offline",
"activity": "Offline",
"outOfOfficeSettings": {
"message": null,
"isOutOfOffice": false
}
}
Availability values: Available, Busy, DoNotDisturb, Away, Offline
GET /microsoft-teams/v1.0/users/{user-id}/presence
Returns presence information for a specific user by their ID.
GET /microsoft-teams/v1.0/teams/{team-id}/channels/{channel-id}/tabs
Response:
{
"@odata.count": 2,
"value": [
{
"id": "ee0b3e8b-dfc8-4945-a45d-28ceaf787d92",
"displayName": "Notes",
"webUrl": "https://teams.microsoft.com/l/entity/..."
},
{
"id": "3ed5b337-c2c9-4d5d-b7b4-84ff09a8fc1c",
"displayName": "Files",
"webUrl": "https://teams.microsoft.com/l/entity/..."
}
]
}
GET /microsoft-teams/v1.0/teams/{team-id}/installedApps
POST /microsoft-teams/v1.0/me/onlineMeetings
Content-Type: application/json
{
"subject": "Team Sync",
"startDateTime": "2026-02-18T10:00:00Z",
"endDateTime": "2026-02-18T11:00:00Z"
}
Response:
{
"id": "MSo1ZjU2ZDU1Yi0yZmZi...",
"subject": "Team Sync",
"startDateTime": "2026-02-18T10:00:00Z",
"endDateTime": "2026-02-18T11:00:00Z",
"joinUrl": "https://teams.microsoft.com/l/meetup-join/...",
"joinWebUrl": "https://teams.microsoft.com/l/meetup-join/...",
"meetingCode": "28636743235745",
"joinMeetingIdSettings": {
"joinMeetingId": "28636743235745",
"passcode": "qh37NK9V",
"isPasscodeRequired": true
},
"participants": {
"organizer": {
"upn": "richard@carvedai.com",
"role": "presenter"
}
}
}
The joinUrl can be shared with attendees to join the meeting.
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}
GET /microsoft-teams/v1.0/me/onlineMeetings?$filter=JoinWebUrl eq '{encoded-join-url}'
Note: Microsoft Graph requires a filter to query meetings. You cannot list all meetings without filtering by JoinWebUrl.
GET /microsoft-teams/v1.0/me/calendar/events?$top=10
Scheduled Teams meetings appear as calendar events with isOnlineMeeting: true.
DELETE /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}
Returns 204 No Content on success.
POST /microsoft-teams/v1.0/me/onlineMeetings
Content-Type: application/json
{
"subject": "Project Review",
"startDateTime": "2026-02-18T14:00:00Z",
"endDateTime": "2026-02-18T15:00:00Z",
"participants": {
"attendees": [
{
"upn": "attendee@example.com",
"role": "attendee"
}
]
}
}
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/recordings
Returns a list of recordings for a meeting (available after the meeting has ended and recording was enabled).
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/recordings/{recording-id}
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/transcripts
Returns a list of transcripts for a meeting (available after the meeting has ended and transcription was enabled).
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/transcripts/{transcript-id}
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/attendanceReports
Returns attendance reports for a meeting (available after the meeting has ended).
GET /microsoft-teams/v1.0/me/onlineMeetings/{meeting-id}/attendanceReports/{report-id}
GET /microsoft-teams/v1.0/me/chats
GET /microsoft-teams/v1.0/chats/{chat-id}
GET /microsoft-teams/v1.0/chats/{chat-id}/messages
POST /microsoft-teams/v1.0/chats/{chat-id}/messages
Content-Type: application/json
{
"body": {
"content": "Hello in chat"
}
}
Microsoft Graph uses OData-style pagination with @odata.nextLink:
GET /microsoft-teams/v1.0/me/joinedTeams?$top=10
Response includes pagination link when more results exist:
{
"value": [...],
"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/joinedTeams?$skiptoken=..."
}
Use the $top parameter to limit results per page.
$top=10 - Limit results$skip=20 - Skip results$select=id,displayName - Select specific fields$filter=membershipType eq 'private' - Filter results$orderby=displayName - Sort resultsconst response = await fetch(
'https://gateway.maton.ai/microsoft-teams/v1.0/me/joinedTeams',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
import os
import requests
response = requests.get(
'https://gateway.maton.ai/microsoft-teams/v1.0/me/joinedTeams',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
import os
import requests
team_id = "your-team-id"
channel_id = "your-channel-id"
response = requests.post(
f'https://gateway.maton.ai/microsoft-teams/v1.0/teams/{team_id}/channels/{channel_id}/messages',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={'body': {'content': 'Hello from Maton!'}}
)
data = response.json()
from.user field shows the actual user identityb643f103-870d-4f98-a23d-e6f164fae33e)19:9fwtZjo3IM0D8bLdQqR-_oMFw1eUDlzWjPfIhNGhVd41@thread.tacv2)1771359569239)text (default) or htmlstandard, private, sharedme endpoint is supported for listing joined teams (not arbitrary user IDs)curl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|--------|---------|
| 400 | Missing Microsoft Teams connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient permissions for the requested resource |
| 404 | Team, channel, or message not found |
| 429 | Rate limited (Microsoft Graph throttling) |
| 4xx/5xx | Passthrough error from Microsoft Graph API |
Generated Feb 23, 2026
A project manager uses the skill to automate team and channel creation for new projects, ensuring consistent setup across departments. They can list existing teams, create dedicated channels for specific tasks, and manage membership, streamlining onboarding and collaboration.
An administrative assistant schedules recurring team meetings and sends automated reminders or follow-up messages via Teams. They can access meeting recordings and transcripts to create summaries, improving productivity and documentation for remote teams.
A support team integrates the skill to send automated notifications or updates to internal channels when customer tickets are resolved. They can also create private channels for sensitive discussions, enhancing communication and response times.
An educator sets up Teams for online courses, creating channels for different subjects or student groups and sending announcements. They manage recordings of lectures and access transcripts for accessibility, supporting blended learning environments.
A sales team uses the skill to automate updates on deals and leads by posting messages to dedicated sales channels. They can schedule meetings with prospects and track interactions via transcripts, improving coordination and transparency.
A company offers this skill as part of a larger API integration platform, charging subscription fees based on usage tiers for Teams automation. It targets businesses needing streamlined collaboration tools, with revenue from monthly plans and enterprise contracts.
A consultancy firm uses the skill to provide tailored Microsoft Teams automation solutions for clients, such as custom workflows or reporting dashboards. Revenue comes from project-based fees and ongoing support contracts, focusing on specific industry needs.
A developer tool provider includes this skill in a freemium API gateway, offering basic Teams functions for free and charging for advanced features like high-volume messaging or analytics. Revenue is generated from premium upgrades and developer support services.
💬 Integration Tip
Ensure the MATON_API_KEY is securely stored and use the Maton-Connection header to manage multiple Teams accounts efficiently for scalable deployments.
iMessage/SMS CLI for listing chats, history, watch, and sending.
Use when you need to control Discord from Clawdbot via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, fetch permissions or member/role/channel info, or handle moderation actions in Discord DMs or channels.
Use when you need to control Slack from Clawdbot via the slack tool, including reacting to messages or pinning/unpinning items in Slack channels or DMs.
Send WhatsApp messages to other people or search/sync WhatsApp history via the wacli CLI (not for normal user chats).
Build or update the BlueBubbles external channel plugin for Clawdbot (extension package, REST send/probe, webhook inbound).
OpenClaw skill for designing Telegram Bot API workflows and command-driven conversations using direct HTTPS requests (no SDKs).