Skip to content
newThe webhook.co MCP server is live — turn any webhook into an agent event. Read the docs
test locally

Test Microsoft Teams webhooks locally

Microsoft Teams has two unrelated ways to push activity at your code — Outgoing Webhooks and Microsoft Graph change notifications — with different setup, different auth, and different delivery rules. Sorting out which one you're wiring up saves an afternoon.

The loop

Create an endpoint and it prints a permanent ingest URL. Everything sent there is captured whole — headers, body, the exact bytes — before anything else happens. Stream those events to a port on your machine, and replay any one of them as often as you like while you fix the handler. Forwarding runs from your own machine, so it isn't a billable delivery.

wbhkms_teams
$ wbhk endpoints create ms_teams-dev
https://wbhk.my/whep_…
$ wbhk listen <endpoint-id> --forward http://localhost:3000/webhooks
$ wbhk replay <event-id> --forward http://localhost:3000/webhooks

What's different about Microsoft Teams

Two things about Teams Outgoing Webhooks catch developers out. First, there's no event catalogue and no subscription screen: the only documented trigger is a person @mentioning the webhook by name, and only in a public channel of the team it was created in — never in personal or private scope. Second, delivery is synchronous and reply-shaped. Teams issues an HTTP request, your code gets five seconds to respond before the connection times out, and whatever you return is posted back into the same reply chain. A handler that acknowledges and defers has nothing to say in the thread.

Where the URL goes

In the Teams client, select Teams in the left pane, pick the team, hit ••• and choose Manage team, open the Apps tab, and under Upload an app select Create an outgoing webhook. Fill in Name, Callback URL — the HTTPS endpoint that accepts JSON payloads and receives POST requests from Teams — and Description. On Create, an HMAC dialogue appears with a security token that "doesn't expire and is unique for each configuration". Copy it then.

Neither mechanism documents a test-send facility, so the first real action is the test. For an Outgoing Webhook, post a message in a public channel of that team @mentioning the webhook by name. For Microsoft Graph change notifications, the subscription request itself makes Graph POST a validationToken query to your notification URL, so the URL sees traffic before any Teams message exists.

What Microsoft Teams sends

Outgoing Webhooks have no event vocabulary at all — nothing to select, nothing to subscribe to. The identifiers below belong to Microsoft Graph change notifications: lowercase past-tense changeType verbs, comma-joined on a subscription, plus lifecycleEvent values delivered to a separate lifecycleNotificationUrl. Graph documents deleted only for chat-message subscriptions.

  • created
  • updated
  • deleted
  • reauthorizationRequired
  • subscriptionRemoved

Worth knowing first

Five seconds, and it's a reply

The how-to page gives your code five seconds to respond before the connection times out and terminates. The older webhooks-and-connectors overview says ten for the same behaviour, so the official docs disagree with themselves — build against five. Your response body appears in the same reply chain as the original message, which makes it user-visible copy, not an internal acknowledgement.

Validate the HMAC on every request

Each request carries an authorization header of the form HMAC followed by a base64 value. Compute a standard SHA256 HMAC over the UTF-8 byte array of the raw body, keyed with the base64-decoded security token from registration, and compare. The docs say your code must always validate it. Teams only makes the webhook available if the URL is valid and the server and client tokens are equal.

Scoped to one team, public channels only

Outgoing Webhooks are configured per team and visible to all that team's members, and they cannot be included as part of a normal Teams app. Users can only message one in public channels, not in personal or private scope. A webhook registered in one team does not exist anywhere else, so exercise it where you created it.

Graph validates the URL before subscribing

Creating a Microsoft Graph change-notification subscription first POSTs to your notification URL with a validationToken query parameter. You have ten seconds to reply with 200 OK, content type text/plain, and the URL-decoded token as plain text in the body. Return it still encoded and validation fails; fail validation and Graph doesn't create the subscription. The endpoint must be publicly accessible over HTTPS.

Graph marks slow endpoints, then drops

Graph counts a notification delivered only on a 2xx received within three seconds, then retries at exponential-backoff intervals for up to four hours with the per-attempt timeout extended to ten seconds. Blow the three-second allowance on more than 10% of responses in a ten-minute window and the endpoint is marked slow; blow the ten-second one on more than 15% and notifications are dropped. Microsoft suggests queueing and returning 202 Accepted.

Outgoing Webhook retries are undocumented

The how-to page describes the synchronous request and response and nothing else: no retry policy, no schedule, no success status code, no payload size cap, no ordering statement. Don't carry the Graph numbers across — they belong to a different product. Until Microsoft documents otherwise, treat a timed-out delivery as a message you will not see again.

Signature checking is handled for you once the secret is registered — you can also check a captured signature by hand in the signature verifier.

Microsoft Teams webhooks: common questions

Does Microsoft Teams have a test-send button for webhooks?

No test facility is documented for either Outgoing Webhooks or Microsoft Graph change notifications. You fire an Outgoing Webhook by @mentioning it by name in a public channel. A Graph subscription request sends a validation POST to your notification URL, which at least proves the URL is reachable.

Why does my Microsoft Teams Outgoing Webhook never fire?

Check the three conditions the docs are explicit about: someone must @mention the webhook by name, the message must be in a public channel, and the webhook only exists inside the team it was created in. Personal and private scope are not supported.

How do I verify a Microsoft Teams Outgoing Webhook signature?

Teams sends an HMAC value in the authorization header. Base64-decode the security token issued at registration, compute a standard SHA256 HMAC over the raw request body as a UTF-8 byte array, base64-encode the result, and compare. The docs say your code must always validate it.

Does Microsoft Teams retry a failed Outgoing Webhook delivery?

The documentation does not say. It describes only a synchronous request with a five-second response window, and states no retry policy, schedule, or success status code. The retry and throttling figures published for Microsoft Graph change notifications belong to a different mechanism and do not apply here.

What events can I subscribe to in Microsoft Teams?

Outgoing Webhooks have no event vocabulary — there is nothing to select. Names live in Microsoft Graph change notifications: changeType values such as created and updated, with deleted documented for chat messages, plus the lifecycle events reauthorizationRequired and subscriptionRemoved.

Point a webhook at it. Watch it land.

Start free: a permanent URL, full inspection, one-command replay — and outbound delivery, because every feature is on every plan. Move up when you need more events.