Message
Creates a Microsoft Graph change-notification subscription at publish, renews it before its three-day expiry, and starts one run per notification.
Start a run when a message is posted, edited or deleted in a Teams channel or chat.
Connection
- Required
- Yes — the node will not save without one
- Auth type
- OAuth 2.0
- Providers
- Microsoft Teams
- Secret shape
- {"client_id", "client_secret", "refresh_token"}
- Config it needs
- tenant
- Resolved by
- config.connection_id, else node.connection_id
- Note
- The refresh token needs ChannelMessage.Read.All to watch a channel, or Chat.Read to watch a chat — Graph refuses a subscription whose credential cannot read the resource. Connect-with-Microsoft does not mint Teams connections yet, so the refresh token has to be supplied on the connection directly. Publishing also needs MANTLE_APP_PUBLIC_BASE_URL set to an https URL Graph can reach: it probes that URL before it will create the subscription.
Configuration
5 fields, none required. A dotted path is a nested object and name[] an array of objects — the editor renders the same tree.
| Field | Type | Required | Default | Constraints | Example |
|---|---|---|---|---|---|
watch Whether to watch a team channel or a 1:1/group chat. Graph needs a different resource path for each, and different ids. | string | No | channel_message | one of "channel_message", "chat_message" | — |
team_id The team whose channel to watch, as its GUID — teams.list_teams returns it. Only used when watching a channel. | string | Conditional | — | ≤ 64 characters; only with watch | fbe2bf47-16c8-47cf-b4a5-4b9b187c508b |
channel_id The channel to watch (19:…@thread.tacv2) — teams.list_channels returns it. Only used when watching a channel. | string | Conditional | — | ≤ 256 characters; only with watch | 19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2 |
chat_id The chat to watch (19:…@unq.gbl.spaces) — teams.list_chats returns it. Only used when watching a chat. | string | Conditional | — | ≤ 256 characters; only with watch | 19:8ea0e38b-efb3-4757-924a-5f94061cf8c2@unq.gbl.spaces |
change_types Which changes fire a run. 'updated' is chattier than it looks — Teams counts an edit, a reaction and a policy check as updates. | array | No | ["created"] | 1–3 characters; array of string | — |
Example configuration
Every value below is the contract’s own example or default — nothing invented.
{
"change_types": [
"created"
],
"channel_id": "19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2",
"chat_id": "19:8ea0e38b-efb3-4757-924a-5f94061cf8c2@unq.gbl.spaces",
"team_id": "fbe2bf47-16c8-47cf-b4a5-4b9b187c508b",
"watch": "channel_message"
}Output
One shape.
teams notification
The flattened Graph change notification. It carries the message's id and path, not its text — fetch the message to read it.
Extra keys beyond the ones listed can appear.
| Field | Type | Example |
|---|---|---|
change_type What happened to the message: created, updated or deleted. Branch on this when the trigger subscribes to more than one. | string | created |
subscription_id Graph's id for the subscription that delivered this. Part of the idempotency key, so a retry cannot start a second run. | string | 9f9d1ed0-c9cc-42e7-8d80-a7fc4b0cda3c |
resource Graph's path to the message that changed — pass it to a Graph read to fetch the message itself, which the notification does not carry. | string | teams('fbe2bf47-16c8-47cf-b4a5-4b9b187c508b')/channels('19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2')/messages('1612293113399') |
message_id The chatMessage's id. Teams message ids are millisecond timestamps as strings, so keep them as strings. | string | 1612293113399 |
team_id The team the message is in, lifted out of the resource path. Empty for a chat message. | string | fbe2bf47-16c8-47cf-b4a5-4b9b187c508b |
channel_id The channel the message is in. Empty for a chat message. | string | 19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2 |
chat_id The chat the message is in. Empty for a channel message. | string | — |
tenant_id The Microsoft 365 tenant the notification came from — Microsoft's tenant, not Mantle's. | string | — |
subscription_expires_at When Graph will stop delivering unless the subscription is renewed. Mantle renews it automatically; this is here for diagnosing a trigger that stopped. | string | — |
payload The change notification exactly as Graph sent it, minus clientState (the shared secret), for anything the fields above do not lift out. | object | — |
{
"change_type": "created",
"channel_id": "19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2",
"chat_id": "",
"message_id": "1612293113399",
"payload": {
"changeType": "created",
"resourceData": {
"id": "1612293113399"
}
},
"resource": "teams('fbe2bf47-16c8-47cf-b4a5-4b9b187c508b')/channels('19:4a95f7d8db4c4e7fae857bcebe0623e6@thread.tacv2')/messages('1612293113399')",
"subscription_expires_at": "2026-09-13T11:26:41.0537895Z",
"subscription_id": "9f9d1ed0-c9cc-42e7-8d80-a7fc4b0cda3c",
"team_id": "fbe2bf47-16c8-47cf-b4a5-4b9b187c508b",
"tenant_id": "84bd8158-6d4d-4958-8b9f-9d6445542f95"
}Notes
- Publishing creates the Graph subscription; unpublishing, disabling or archiving deletes it. A workflow that is off is off at Microsoft too.
- Graph subscriptions expire — three days is the ceiling for Teams messages — so Mantle renews this one automatically well before it lapses.
- The notification carries the message's id and path, not its text. Rich notifications need an encryption certificate; read the message with a Teams node instead.
- Deliveries are checked against the clientState Graph echoes back. That is a shared secret in the body, not a signature: it proves who sent the notification, not that the body is unmodified in transit.
- One run per (subscription, change type, message id) — Graph retries an undelivered notification for up to four hours and a retry cannot start a second run.
- Microsoft counts every Teams subscription in the tenant against one 10,000-subscription quota, and allows one per app-and-channel (or chat) combination; a second workflow watching the same channel is refused.
Related Microsoft Teams nodes
Templates that use Microsoft Teams
Solutions with Microsoft Teams
See Message run in a workflow.
In a technical demo we add the Microsoft Teams connection, drop the node on the canvas and let Workflow Health pre-flight it before the first real run.