Send Stripe Webhooks to Slack Without a Server (JavaScript Function)
Turn Stripe webhooks into Slack messages without a backend: point Stripe at a Webhook Relay endpoint, attach a 20-line JavaScript function that builds the Slack payload, and forward to the Slack incoming webhook.

Stripe webhooks can post straight into Slack if something rebuilds the payload on the way: Stripe sends an event object, Slack's incoming webhook only accepts { "text": "..." } or a blocks array. Webhook Relay does the rebuild with a small JavaScript function that runs on every request, so there is no backend to deploy. Setup takes about ten minutes.
Stripe ──▶ Webhook Relay endpoint ──▶ JavaScript function ──▶ Slack incoming webhook
(event) (permanent public URL) (event → Slack message) (message in channel)
Step 1: Get a Slack incoming webhook URL
In Slack, create an app at api.slack.com/apps, enable Incoming Webhooks, add one to the channel that should get payment notifications, and copy the URL. It looks like https://hooks.slack.com/services/T000/B000/XXXX. Full walkthrough: how to get a Slack webhook URL.
Step 2: Create the Webhook Relay endpoint
Open new public destination, paste the Slack URL as the destination, and note the input URL Webhook Relay gives you. That input URL is permanent; it is what you will hand to Stripe.
Step 3: Add the transformation function
On the output that points at Slack, choose Transform and create a function with this JavaScript:
// Stripe event → Slack message
const event = JSON.parse(r.body)
const obj = event.data && event.data.object ? event.data.object : {}
// Only forward the events we care about; drop the rest silently.
const wanted = {
"payment_intent.succeeded": "💰 Payment received",
"invoice.paid": "🧾 Invoice paid",
"invoice.payment_failed": "⚠️ Invoice payment failed",
"customer.subscription.created": "🎉 New subscription",
"customer.subscription.deleted": "👋 Subscription cancelled",
}
const headline = wanted[event.type]
if (!headline) {
r.stopForwarding()
return
}
const amount = obj.amount_paid ?? obj.amount_received ?? obj.amount ?? null
const currency = (obj.currency || "").toUpperCase()
const money = amount === null ? "" : ` — ${(amount / 100).toFixed(2)} ${currency}`
const customer = obj.customer_email || obj.customer || "unknown customer"
const mode = event.livemode ? "" : " (test mode)"
r.setBody(JSON.stringify({
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `*${headline}${money}*${mode}\n${customer} · \`${event.type}\` · <https://dashboard.stripe.com/events/${event.id}|open in Stripe>`,
},
},
],
}))
r.setHeader("Content-Type", "application/json")
r.setMethod("POST")
What it does: parses the Stripe event, drops anything not in the wanted map, formats the amount from cents, and sets the request body to a Slack Block Kit message. Webhook Relay then delivers that request to the Slack URL, retries it if Slack is briefly unavailable, and logs the delivery.
Want a different message layout? Paste a sample Stripe event into the free webhook to Slack formatter, design the message visually, and copy the generated function.
Step 4: Point Stripe at the endpoint
In the Stripe dashboard go to Developers → Webhooks → Add endpoint, paste the Webhook Relay input URL, and select the events you listed in the function (or all events; the function filters). Save, then use Send test event for payment_intent.succeeded. The message appears in Slack within a second or two. If it does not, the request log in the Webhook Relay dashboard shows exactly what Stripe sent and what Slack answered.
Optional: verify the Stripe signature
Stripe signs every webhook. To reject forged requests, store the endpoint's signing secret as a secret service connection, read the Stripe-Signature header in the function, and compare the HMAC before building the message. The webhook signature guide has the exact check; the free Stripe signature verifier helps you debug it against a captured payload.
Also deliver the event to your own app
The Slack message is usually a side channel. Add a second output on the same bucket that points at your API, a BigQuery table, or your laptop during development: every Stripe event is delivered to all of them, each with its own optional function.
Alternatives
Stripe's own Slack app posts a fixed set of notifications with no customisation. Zapier and Make offer Stripe-to-Slack templates with per-task pricing. A Lambda or Cloudflare Worker gives full control if you want to host and operate it yourself. The comparison of webhook transformation tools covers when each makes sense.
