When a card payment fails, Stripe can email your customer, retry the charge on a schedule and mark the invoice past due. All of that happens to the customer. To hear about it yourself while the payment can still be saved, you need Stripe's webhooks: they are where Stripe announces a failed payment the moment it happens.
This guide covers which events to watch, three ways to get them to your phone, and how to test it.
The events worth hearing about
Stripe sends hundreds of event types. A handful are money leaving or about to leave. These are the ones Acciti's Stripe connector knows, with the priority each arrives at. You choose which to turn on, and you can change any priority.
| Event | What happened | Arrives as |
|---|---|---|
invoice.payment_failed | A customer's payment failed. | High |
customer.subscription.deleted | A subscription was cancelled. | Normal |
invoice.paid | An invoice was paid. | Quiet |
checkout.session.completed | A checkout completed. | Quiet |
charge.dispute.created | A charge was disputed. | High |
invoice.payment_failed is the one to start with. It fires each time a subscription invoice can't be charged, including each of Stripe's retries, so a customer whose card expired produces one event per attempt. Each attempt is another chance to get the card updated.
charge.dispute.created deserves the same priority. A dispute comes with a deadline for your evidence, and every day before you notice it is a day lost.
The quiet events are for people who like a note when money comes in. They arrive as a banner with no sound, so a good day doesn't sound like an outage.
Three ways to get them to your phone
An automation service
Zapier and IFTTT can watch Stripe and send a text or a push. Two costs come with that: the service now holds access to your Stripe account, and depending on the plan it may check for new events on a timer rather than as they happen.
Your own webhook endpoint
You can write an endpoint that receives Stripe's events and forwards them. Stripe signs every event with the endpoint's signing secret, and the endpoint has to check that signature, or anyone who finds the URL can send you a fake payment failure. Stripe's libraries do the check:
const event = stripe.webhooks.constructEvent( rawBody, // the bytes, not parsed JSON request.headers["stripe-signature"], process.env.STRIPE_WEBHOOK_SECRET,) if (event.type === "invoice.payment_failed") { // forward it to your phone}Then the endpoint needs hosting, logs and someone to notice when it is the thing that broke. That is a lot of software to own for one alert.
A connector
Acciti's Stripe connector is that endpoint, already written. It checks Stripe's signature on every event, turns the events you picked into notifications, and refuses anything that fails the check.
Setting up the connector
- In Acciti, add a Stripe connector and copy its ingest URL.
- In the Stripe Dashboard, open Developers, then Webhooks, and add an endpoint with that URL. Select the events from the table above.
- Copy the endpoint's signing secret, which starts with
whsec_, and paste it back into the connector.
Connectors are on the Solo plan and up. Compare plans
Test it before a real card fails
Add the same endpoint in Stripe's test mode, with its own signing secret on a second connector, and fire the event from the Stripe CLI:
stripe trigger invoice.payment_failedThe CLI creates the test objects that produce a real invoice.payment_failed in test mode, and Stripe delivers it to every test-mode endpoint listening for it. Your phone shows it:
09:41
Dispute opened
now49.90 USD disputed.
Stripe · chime
Deciding what should wake you
A failed payment at 3 a.m. is rarely something you can fix at 3 a.m. High priority makes a sound and gets through Focus, but it doesn't repeat. Keep Emergency, which repeats until someone acknowledges it, for things that lose money every minute, such as checkout failing for everyone.
App Store renewals and refunds work the same way through App Store Server Notifications, and the connectors page lists every service Acciti verifies.