Incoming vs outgoing webhooks, with Slack, Teams, Discord and Google Chat
An incoming webhook is a URL an app like Slack or Discord gives you so your code can post messages into it; an outgoing webhook is the app sending a request to your URL when something happens. Slack wants an answer within 3 seconds, Teams outgoing webhooks within 5.
An incoming webhook is a URL that an app such as Slack, Discord or Google Chat gives you so your code can post messages into it, and an outgoing webhook is the reverse, the app sending an HTTP request to your URL when something happens in it. The names are from the app's point of view, so a Stripe or GitHub webhook is outgoing for them and incoming for your server (see what a webhook is if you want the basics). Below are incoming webhooks in 4 chat apps with their URL formats and limits, the Microsoft Teams change, outgoing webhooks and what they expect back, and how to test both directions with a free bin.
Incoming webhooks: you post into the app
You create an incoming webhook in the app's settings, get a secret URL tied to one channel or space, and send it a JSON POST - there's no bot user or sign-in flow in your code. They only go one way: Google Chat calls them asynchronous, one-way notifications that users can't interact with.
The URL itself is the credential, so keep it out of public repositories. Slack actively searches for leaked webhook URLs and revokes them. You can try Slack's own {"text": "Hello, world."} request in the commands later on this page.
| App | URL looks like | What you send | Limits |
|---|---|---|---|
| Slack | https://hooks.slack.com/services/T.../B.../... | JSON with text | One user and one channel per URL; up to 100 attachments |
| Discord | https://discord.com/api/webhooks/<id>/<token> | JSON with content, embeds, files or a poll | content up to 2,000 characters; up to 10 embeds |
| Google Chat | https://chat.googleapis.com/v1/spaces/<SPACE_ID>/messages?key=...&token=... | JSON with text | 1 request per second per space; Business or Enterprise Workspace |
| Microsoft Teams | The URL a Workflows flow gives you | Adaptive Card or MessageCard JSON | 28 KB per message; throttled above 4 requests a second |
Microsoft Teams: connectors retired, Workflows instead
Office 365 Connectors in Teams, including connector-based incoming webhooks, were retired in May 2026. To post into Microsoft Teams from code now, create a workflow in the Workflows app with the When a Teams webhook request is received trigger and send JSON to the URL it gives you.
Workflows webhooks accept Adaptive Card and MessageCard payloads (MessageCard has no interactive HTTP POST action buttons), work in private channels, cap messages at 28 KB, throttle above 4 requests a second. The catch is that a workflow belongs to a user, not to the channel, so add co-owners or it can become an orphan flow when that person leaves.
Outgoing webhooks: the app posts to you
With an outgoing webhook, you give the app an HTTPS URL and it sends a POST when something happens. Your endpoint has to answer fast, and some apps test your endpoint before they send anything real.
Verify the signature on every request (each app names its own header, like X-Slack-Signature or Discord's X-Signature-Ed25519 and X-Signature-Timestamp) and answer before doing slow work. Teams also posts your reply back into the conversation, in the same reply chain as the original message.
| App | Fires when | What it expects back | Signature |
|---|---|---|---|
| Slack Events API | A subscribed event, such as reaction_added | The url_verification challenge once, then a 2xx within 3 seconds | X-Slack-Signature |
| Microsoft Teams outgoing webhook | Someone @mentions it in a public channel | A reply within 5 seconds, posted in the same thread | HMAC in the Authorization header |
| Discord webhook events | App events such as APPLICATION_AUTHORIZED | A 204 with no body to the PING, then to each event within 3 seconds | X-Signature-Ed25519 |
| Twilio Messaging | Your number receives an SMS | TwiML instructions | X-Twilio-Signature |
Test both directions with a free bin
For the incoming direction, before posting to a real channel, swap the Slack, Discord, Teams or Google Chat URL in your code for a bin's ingest URL from webhooks.sh and run it. The viewer shows the exact method, headers and JSON your code sends, so you catch a broken payload without spamming a channel.
For the outgoing direction, paste the bin URL where the app asks for a Request URL or Callback URL. Slack's url_verification challenge is answered automatically, so Slack accepts the bin and events arrive live, and Twilio and Teams requests show up too.
What a free bin can't do:
- It always answers
200with its own small JSON ({"ok":true,"delivery_id":"..."}), so it can't return TwiML for Twilio or post a reply into a Teams thread. - It can't be your Discord Webhook Events URL, because Discord wants a
204with an empty body to itsPINGand checks that bad signatures get a401. - Header names that contain
authorization,cookie,key,tokenorsecretare redacted in the viewer, so you see that Teams sent anAuthorizationheader, not its HMAC value. - A free bin lasts 48 hours and takes 100 requests a day (bodies up to 100KB); claim it with a free Google sign-in to keep the same URL and hold new requests for 30 days.
# 1. Create a free bin (or open view.webhooks.page)
curl -X POST https://webhooks.sh/v1/bins
# 2. Send the bin what your code would send to Slack
curl -X POST https://<bin>.webhooks.page/slack \
-H "Content-type: application/json" \
-d '{"text": "Hello, world."}'
Which one do you need?
- Alerts from your own system into a channel: use an incoming webhook in Slack, Discord, Google Chat, or a Teams Workflows webhook.
- Your code reacting when people do something in the app: use an outgoing webhook or events API (Slack Events API, a Teams outgoing webhook, Discord webhook events).
- Two-way conversations with buttons and replies: build a proper bot or app, since Google Chat webhooks are one-way and Teams MessageCard payloads don't support interactive buttons.
FAQ
What is an incoming webhook?
It's a URL from Slack, Discord, Google Chat or a Teams workflow that you POST JSON to so a message appears in a channel or space.
What is an outgoing webhook?
It's when the app sends an HTTP POST to your URL when something happens, like a Teams @mention in a public channel or a Slack event_callback event, and your endpoint answers within seconds.
Do Microsoft Teams incoming webhooks still work?
Connector-based incoming webhooks were retired in May 2026. Create a Workflows webhook with the When a Teams webhook request is received trigger instead.
How do I test a Slack incoming webhook without posting to a channel?
Point your code at a free bin URL instead of your https://hooks.slack.com/services/... URL and read the exact JSON and headers it sends in the viewer.
Can an incoming webhook read messages from a channel?
No, it only posts messages in. To receive messages or events from the app, use its outgoing webhooks or events API.
Is a Stripe or GitHub webhook incoming or outgoing?
It's outgoing from Stripe or GitHub and incoming to your server: their app sends the POST, and your endpoint receives it.
Last updated
Try it in 10 seconds.
Create a free bin at view.webhooks.page — no signup, no install. Point your sender at the URL and watch requests land live. Bins expire after 48 hours.