The jargon-free explainer for people who've heard the word "webhook" and smiled politely.
Don't worry — you won't write any webhook code by hand. Your AI tool handles all the technical parts. This guide helps you understand the concepts so you can describe what you want.
Imagine you're expecting a package. You have two ways to know when it's arrived:
The annoying way
Walk to the front door every five minutes and check. Exhausting. Almost always a waste of time. Your app shouldn't do this, and neither should you.
The webhook way
The delivery person rings the doorbell. You only get up when there's actually something to deal with. That ring is a webhook.
A webhook is just a doorbell between two apps. When something happens in one app, it rings the doorbell of another app so that app knows to do something about it.
You probably need a webhook anytime your app cares about something happening in another service. Some real examples:
Stripe
Rings when: Someone paid, a card was declined, someone cancelled
So your app can: Mark them as a paying customer (or remove their access)
GitHub
Rings when: You pushed new code
So your app can: Automatically deploy your updated site
Resend (email)
Rings when: An email was opened, bounced, or clicked
So your app can: Track who's engaged and who isn't
Clerk / Auth
Rings when: A new person signed up
So your app can: Add them to your own database and send a welcome email
Calendly
Rings when: Someone booked a meeting with you
So your app can: Add it to your CRM and notify your team on Slack
Typeform
Rings when: Someone filled out your form
So your app can: Save their answers and trigger a follow-up
You don't need to know how to write a webhook — you just need to know how to ask for one. A good prompt tells your AI tool three things:
Which service should ring the doorbell (Stripe, GitHub, etc.)
Which events you care about (payments? cancellations? new users?)
What your app should do when it hears the doorbell
SET UP A STRIPE WEBHOOK
"Set up a Stripe webhook for my app. I want to be notified whenever a subscription starts, changes, is cancelled, or when a payment succeeds or fails. When any of those things happen, update the matching customer in my database so I know who is currently a paying customer. Make sure the webhook is verified so no one can fake a message. Walk me through, step by step, where to find the webhook secret in the Stripe dashboard and where to save it safely in my project."
Your webhook URL is a public door on the internet. Anyone could send a fake message to it pretending to be Stripe. Without verification, they could trigger a "payment succeeded" event for themselves and unlock paid features for free.
To prevent that, Stripe sends a special header called stripe-signaturewith every webhook. Your app re-creates that signature using a shared secret only you and Stripe know. If they match, it's real. If not, your app rejects it with a 400.
The flow
⚠️ The raw body trap: Signature checking only works on the raw, untouched request body. If your framework parses the JSON before you verify, the signature will fail every time. In Next.js App Router this means using await request.text() (not request.json()) inside the route. Tell your AI tool: "use the raw body for signature verification" and it'll set this up correctly.
While your app is still on your laptop (not live on the internet yet), Stripe can't reach it to ring the doorbell. There's a free tool called the Stripe CLIthat builds a little tunnel so Stripe can still send fake test messages to your app while you're building.
You don't need to memorize any commands. Just ask your AI tool to walk you through it:
HELP ME TEST MY WEBHOOK
"I want to test my Stripe webhook on my laptop before deploying. Walk me through installing the Stripe CLI step by step — tell me exactly what to type in the terminal, what each command does, and how I'll know it's working. Then show me how to fire a fake "payment succeeded" message at my app so I can see my code react to it."
My webhook worked on my laptop but broke when I launched
Your live website uses a different secret password than your laptop. In the Stripe dashboard, create a new webhook for your live site and copy the new secret into your live environment settings. Ask your AI tool "help me set up my production webhook secret on Vercel."
The same event seems to happen twice
Stripe retries any webhook that doesn't return a 2xx status quickly enough — sometimes for several days. The fix is to make your handler "idempotent": store every event.id Stripe sends in a webhook_events table, and skip events you've already processed. One prompt to your AI tool covers it.
Stripe says my webhook is failing but I can't tell why
Open the Stripe dashboard, go to Developers → Webhooks, and click on your endpoint. You'll see every message Stripe tried to send and the exact error. Copy the error and paste it into your AI tool — it'll tell you what's wrong.
My webhook is slow and Stripe gives up
Stripe expects a 2xx response within ~5 seconds. If your handler does a lot of work (sending emails, calling other APIs), it can time out. The fix: respond with 200 immediately, then push the actual work to a background queue or a separate worker. Ask your AI tool to "return 200 right away and process the event in the background."
You want your website to automatically update itself every time you save changes to GitHub. If you're using Vercel, this already happens for free. But if you're somewhere else, a webhook can do it: GitHub rings your app's doorbell whenever you push, and your app kicks off a fresh deploy.
Build this with AI
"Set up a GitHub webhook for my app. Whenever I push new code to the main branch, the webhook should trigger a fresh deploy on my hosting provider. Make sure the webhook is verified so only real GitHub messages count. Ignore other branches and pull requests. When a deploy starts, send me a message on Slack with who pushed it and what they changed."
LOG EVERY WEBHOOK FOR DEBUGGING
"Keep a simple log of every webhook my app receives from any service. For each one, save the service name, what happened, when, and whether it was verified successfully. Build me a hidden /admin/webhooks page where I can see the list and click any one to see the details. This will help me figure out what's going wrong when something breaks."
STOP DUPLICATE PROCESSING
"My webhook is sometimes doing the same thing twice because Stripe retries. Make my webhook smart enough to recognize when it's seen a message before and skip it. Explain what you changed in plain English so I understand."
MAKE MY WEBHOOK FASTER
"My webhook is taking too long to respond and Stripe is giving up on it. Change it so my app says "got it!" to Stripe immediately, then does the actual work in the background. Walk me through what you changed."