Microsoft Teams Webhook Connector Guide
The Teams Webhook connector enables Tealfabric workflows to post operational messages directly into Microsoft Teams channels without implementing custom notification services. This guide helps you configure the connector correctly, choose the right message format, and keep delivery reliable in production.
Document information
| Field | Value |
|---|---|
| Canonical URL | /docs/04_connecting-systems/connectors/t/teams-webhook |
| Version (published date) | 2026-05-08 |
| Tags | connectors, reference, teams-webhook |
| Connector ID | teams-webhook-1.0.0 |
When to use this connector
Use this connector when your workflow must notify a Teams channel about deployments, incidents, approvals, or process milestones. Incoming webhooks are a practical option for one-way channel updates that do not require bot-level conversation APIs. Consistent payload formatting and clear message structure make alerts easier for recipients to act on quickly.
Prerequisites
Before creating the integration, create an Incoming Webhook in the target Teams channel and store the generated URL securely. Confirm that the channel is active and monitored by the intended audience so workflow notifications provide operational value. Performing this setup first prevents silent failures later in production.
Configuration reference
Connector settings are stored in integration configuration and reused across executions. Keep the webhook URL in secure storage and rotate it if it is exposed.
webhook_url(required fortest): Full Microsoft Teams Incoming Webhook URL for the target channel.timeout_seconds(optional): Timeout applied to webhook requests (default30).
Run test after configuration to validate webhook_url format and connectivity before sending production traffic.
Send a simple Teams notification with send
The send operation builds a default MessageCard when you provide text or message (and optional title). For richer cards with sections or custom fields, pass the full card JSON in the card field instead.
Payload aliases: message for text.
const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";
async function sendTeamsWebhook(integrationId: string) {
const response = await fetch(
`${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
{
method: "POST",
headers: {
"X-API-Key": apiKey,
"X-Tenant-ID": tenantId,
"Content-Type": "application/json",
},
body: JSON.stringify({
operation: "send",
text: "Release 2026.05.08 finished successfully.",
title: "Deployment completed",
}),
}
);
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const payload = await response.json();
return payload.data;
}{
"success": true,
"data": {
"message_count": 1,
"data": {
"status_code": 200,
"body": "1"
},
"http_status": 200
}
}
Send a MessageCard with card
Pass a pre-built MessageCard object in card when you need sections, facts, or other MessageCard fields. The connector posts the object as-is.
{
"operation": "send",
"card": {
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"summary": "Deployment notification",
"themeColor": "0078D4",
"title": "Deployment completed",
"text": "Release 2026.05.08 finished successfully.",
"sections": [
{
"facts": [
{ "name": "Environment", "value": "production" },
{ "name": "Status", "value": "success" }
]
}
]
}
}
Send adaptive card payloads with adaptive_card
For Adaptive Cards, pass the card body in adaptive_card. The connector wraps it in the Teams message attachment envelope.
{
"operation": "send",
"adaptive_card": {
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{ "type": "TextBlock", "text": "Incident resolved", "weight": "Bolder" },
{ "type": "TextBlock", "text": "All services are healthy.", "wrap": true }
]
}
}
Batch send with batch
The batch operation posts each item sequentially. Each entry may include a data object with the full webhook JSON; when data is omitted, the item object is posted directly. Batch items do not use the send MessageCard builder.
{
"operation": "batch",
"operations": [
{
"data": {
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"summary": "Alert 1",
"text": "First notification"
}
},
{
"data": {
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"summary": "Alert 2",
"text": "Second notification"
}
}
]
}
{
"success": true,
"data": {
"message_count": 2,
"total_operations": 2,
"successful_operations": 2,
"results": [
{ "index": 0, "success": true, "result": { "status_code": 200, "body": "1" } },
{ "index": 1, "success": true, "result": { "status_code": 200, "body": "1" } }
]
}
}
Unsupported operations
receive and sync are dispatched but always fail with a validation error because Teams incoming webhooks are outbound-only.
Validate connectivity with test
test validates webhook_url (required, valid URL, must contain office.com or office365.com) and posts a fixed MessageCard probe. Configuration failures return Configuration validation failed.
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
-H "X-API-Key: <API_KEY>" \
-H "X-Tenant-ID: <TENANT_ID>" \
-H "Content-Type: application/json" \
-d '{
"operation": "test"
}'
{
"success": true,
"data": {
"message": "Teams Webhook connection test successful",
"details": {
"webhook_url": "https://outlook.office.com/webhook/...",
"http_status": 200
}
}
}
Rate limiting and troubleshooting
The connector enforces a local throttle of one request per second per process (same as legacy PHP). Most delivery failures come from inactive webhook URLs, invalid card schema, or channel-side throttling. Applying controlled retry behavior and concise payloads improves delivery consistency.
Additional references
For schema details and current platform behavior, use the official documentation for Teams incoming webhooks and Adaptive Cards. Keeping payloads aligned with current schema requirements helps prevent rendering regressions over time.