How to Send Slack Alerts for Subscription Payment Events
Get Slack notifications for successful payments, failed charges, and subscription changes.
What This Integration Does
Billing changes happen at all hours, and a missed failed payment is the difference between a saved customer and a churn statistic. This workflow turns every meaningful Stripe subscription event into a formatted Slack message in the right channel, with the right level of urgency.
The workflow listens for Stripe subscription webhooks, branches by event type, enriches the payload with customer details, formats a tailored message (success, failure, cancellation, upcoming renewal), and posts it to the appropriate Slack channel. Failure events also create a follow-up task so dunning doesn't fall through the cracks.
Prerequisites
- A Stripe connection. Subscribe to
invoice.payment_succeeded,invoice.payment_failed,customer.subscription.deleted, andinvoice.upcomingevents. - A Slack connection with permission to post to your billing channels.
- Two Slack channels:
#billing-success(low signal) and#billing-alerts(high signal, on-call paged).
Step 1: Stripe Webhook Trigger
Add a Trigger node set to Webhook. Register the URL in Stripe and subscribe it to the four subscription-related events above. Spojit verifies the Stripe signature, so spoofed payloads are rejected before downstream steps fire.
Step 2: Branch by Event Type
Add a Condition node that routes on {{ trigger.type }}. Each branch handles one event type so the formatting and downstream actions can be tailored: success goes to the calm channel, failure goes to the loud one, cancellation kicks off an offboarding flow, and upcoming renewals optionally ping the customer success team.
Step 3: Enrich with Customer Detail
Each Stripe event has a customer ID but no human-readable info. Add a Connector node pointing at stripe using get-customer with that ID. You can also call list-subscriptions filtered by customer to surface plan name and MRR. Save the enriched object as customer.
Step 4: Format the Message
Add a Transform node per branch that builds a Slack-friendly message string. Use emoji and structure to make scanning easy. Example for a failed payment:
:rotating_light: *Payment Failed*
Customer: {{ customer.email }} ({{ customer.name }})
Plan: {{ subscription.plan.nickname }}
Amount: {{ invoice.amount_due | currency }}
Attempt: {{ invoice.attempt_count }}
Next retry: {{ invoice.next_payment_attempt | date }}
<https://dashboard.stripe.com/customers/{{ customer.id }}|Open in Stripe>
Step 5: Post to Slack
Add a Connector node pointing at slack using send-message. Configure the channel per branch:
- Success:
#billing-success - Failure:
#billing-alertsand @here mention - Cancellation:
#billing-alertsand @cs mention - Upcoming renewal:
#billing-successwith no mention
Step 6: Optional Follow-up Actions
On the failure branch, add a follow-up Connector step or a Subworkflow that creates a task in your CRM, queues an email retry, or pages on-call after the second failure. Use a Condition on {{ invoice.attempt_count }} to escalate progressively rather than pinging on every retry.
Tips
- Format currency once in the Transform with the math connector's
currencytool so messages stay consistent. - Keep success notifications low-signal. Daily digests work better than per-event pings for the noisy events.
- Add a Slack message thread reply on retries instead of new top-level messages so the channel doesn't drown.
Common Pitfalls
- Test-mode events leaking into production channels. Branch on
livemodeat the trigger and route test events to a separate sandbox channel. - Currency formatting. Stripe amounts are integer cents in the smallest currency unit; some currencies (JPY, KRW) have zero decimals. The math
currencytool handles this if you pass the currency code. - Webhook retries. Stripe retries non-2xx responses for up to three days. Make sure the workflow finishes the upstream Slack post before failing on a downstream task creation.
Testing
Use Stripe's test-mode CLI to fire one event per branch. Confirm the right channel receives the right format, then trigger a failed-payment retry sequence to verify escalation. Only then point the production Stripe account at the same webhook.