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.
On this page

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.
