Microsoft Teams
Send notifications to Microsoft Teams channels via incoming webhooks. Like Discord, Teams uses a webhook-based connection model — you create an incoming webhook in your Teams channel and register it with Zyphr.
Features
- Webhook-Based Setup - No OAuth or app registration required
- Adaptive Cards - Rich, interactive message formatting
- Theme Colors - Color-coded messages for visual categorization
- URL Validation - Verify webhook URLs before saving
- Test Messages - Send test messages to verify connectivity
- Delivery Tracking - Full message lifecycle with status updates
Quick Start
1. Create a Teams Incoming Webhook
In your Microsoft Teams channel:
- Click the ... menu on the target channel
- Select Connectors (or Manage channel > Connectors)
- Find Incoming Webhook and click Configure
- Name the webhook (e.g., "Zyphr Notifications")
- Optionally upload a custom icon
- Click Create and copy the webhook URL
2. Register the Connection
Via Dashboard
- Navigate to Integrations in the sidebar
- Click Connect Microsoft Teams
- Paste your Teams webhook URL
- Give the connection a name
- Click Create
Via API
curl -X POST https://api.zyphr.dev/v1/teams/connections \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Engineering Alerts",
"webhook_url": "https://outlook.office.com/webhook/..."
}'
3. Send a Message
curl -X POST https://api.zyphr.dev/v1/teams/send \
-H "X-API-Key: zy_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc123",
"text": "Hello from Zyphr!"
}'
await zyphr.teams.send({
connectionId: 'conn_abc123',
text: 'Hello from Zyphr!',
});
Sending Messages
Basic Text Message
curl -X POST https://api.zyphr.dev/v1/teams/send \
-H "X-API-Key: zy_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc123",
"text": "New deployment completed for production."
}'
Message Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
connection_id | string | Yes | The Teams connection to send through |
text | string | Conditional | Message text (required if no adaptive_card) |
adaptive_card | object | No | Adaptive Card JSON for rich formatting |
theme_color | string | No | Hex color for the message accent stripe |
sections | array | No | Message Card sections (legacy format) |
Themed Messages
Use theme_color to add a colored accent stripe:
curl -X POST https://api.zyphr.dev/v1/teams/send \
-H "X-API-Key: zy_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc123",
"text": "Build failed on main branch",
"theme_color": "FF0000"
}'
Theme Color Conventions
2ecc71— Green (success, deployments)e74c3c— Red (errors, failures)3498db— Blue (info, updates)f39c12— Orange (warnings)
Adaptive Cards
Adaptive Cards provide rich, interactive message layouts:
curl -X POST https://api.zyphr.dev/v1/teams/send \
-H "X-API-Key: zy_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc123",
"adaptive_card": {
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Deployment Complete",
"weight": "Bolder",
"size": "Large"
},
{
"type": "FactSet",
"facts": [
{ "title": "Environment", "value": "Production" },
{ "title": "Version", "value": "v2.4.1" },
{ "title": "Status", "value": "Success" },
{ "title": "Duration", "value": "3m 42s" }
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View Logs",
"url": "https://yourapp.com/deployments/123"
}
]
}
}'
await zyphr.teams.send({
connectionId: 'conn_abc123',
adaptiveCard: {
type: 'AdaptiveCard',
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
version: '1.4',
body: [
{
type: 'TextBlock',
text: 'Deployment Complete',
weight: 'Bolder',
size: 'Large',
},
{
type: 'FactSet',
facts: [
{ title: 'Environment', value: 'Production' },
{ title: 'Version', value: 'v2.4.1' },
],
},
],
},
});
Message Card Sections (Legacy)
For simpler formatting, use the legacy sections format:
curl -X POST https://api.zyphr.dev/v1/teams/send \
-H "X-API-Key: zy_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc123",
"text": "Daily Report",
"theme_color": "3498db",
"sections": [
{
"activityTitle": "Email Statistics",
"facts": [
{ "name": "Sent", "value": "1,234" },
{ "name": "Delivered", "value": "1,215 (98.5%)" },
{ "name": "Bounced", "value": "19 (1.5%)" }
]
}
]
}'
Managing Connections
Validate a Webhook URL
curl -X POST https://api.zyphr.dev/v1/teams/validate-webhook \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://outlook.office.com/webhook/..."
}'
List Connections
curl https://api.zyphr.dev/v1/teams/connections \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Update a Connection
curl -X PATCH https://api.zyphr.dev/v1/teams/connections/CONN_ID \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Connection Name"
}'
Send a Test Message
curl -X POST https://api.zyphr.dev/v1/teams/connections/CONN_ID/test \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Delete a Connection
curl -X DELETE https://api.zyphr.dev/v1/teams/connections/CONN_ID \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Message History
List Messages
curl "https://api.zyphr.dev/v1/teams/messages?connection_id=conn_abc123&status=sent&limit=25" \
-H "X-API-Key: zy_live_your_api_key"
Query Parameters
| Parameter | Type | Description |
|---|---|---|
connection_id | string | Filter by connection |
status | string | Filter by status: queued, sending, sent, failed |
limit | number | Results per page (default: 25, max: 100) |
offset | number | Pagination offset |
Get Message Details
curl https://api.zyphr.dev/v1/teams/messages/MSG_ID \
-H "X-API-Key: zy_live_your_api_key"
Message Lifecycle
| Status | Description |
|---|---|
queued | Message accepted and queued for delivery |
sending | Message is being sent to Teams |
sent | Message successfully delivered to Teams |
failed | Delivery failed (check error details) |
Error Handling
| Error | Cause | Resolution |
|---|---|---|
invalid_webhook_url | Webhook URL format is incorrect | Verify the URL is a valid Teams incoming webhook URL |
webhook_not_found | Webhook was removed from Teams | Create a new incoming webhook in Teams |
rate_limited | Teams connector rate limit hit | Zyphr handles retries automatically |
invalid_adaptive_card | Malformed Adaptive Card JSON | Validate with the Adaptive Cards Designer |
API Reference
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /v1/teams/connections | JWT | List connections |
POST | /v1/teams/connections | JWT | Create connection |
GET | /v1/teams/connections/:id | JWT | Get connection |
PATCH | /v1/teams/connections/:id | JWT | Update connection |
DELETE | /v1/teams/connections/:id | JWT | Delete connection |
POST | /v1/teams/connections/:id/test | JWT | Send test message |
POST | /v1/teams/validate-webhook | JWT | Validate webhook URL |
POST | /v1/teams/send | API Key | Send message |
GET | /v1/teams/messages | API Key | List messages |
GET | /v1/teams/messages/:id | API Key | Get message |
Rate Limits
Microsoft Teams enforces rate limits on incoming webhook connectors.
| Limit Type | Rate | Scope |
|---|---|---|
| Per connector | 4 requests/second | Per webhook URL |
| Burst | Short bursts tolerated | Teams may queue excess messages |
| Message size | 28 KB max | Per message payload |
How Zyphr Handles Rate Limits
- Automatic retry: When Teams returns
429, Zyphr waits for theRetry-Afterduration and retries - Queue-based delivery: Messages are naturally spaced via the delivery queue
- No message loss: Rate-limited messages are retried, not dropped
Best Practices
- Use Adaptive Cards to consolidate information — one card with a FactSet is better than multiple text messages
- Keep payloads under 28 KB — Teams rejects larger messages
- Avoid rapid-fire sends to the same connector — batch updates when possible
Next Steps
- Slack Integration - Send messages to Slack workspaces
- Discord Integration - Send messages to Discord servers
- Notification Workflows - Include Teams in multi-channel workflows