Paid, but never activated
Stripe shows the charge. Your database shows a user on the free plan. There is no error anywhere, until the customer writes to you.
PayHook shows you exactly what Stripe, Paddle, Lemon Squeezy, Polar, or Dodo sent, what your app did with it, and how to fix it — in plain English.
Join the waitlistPayHook is in early access: the signature-verification core is built and tested; the hosted app ships in 4–6 weeks. Pre-order now — full refund anytime, no questions asked: just email [email protected].
Stripe sent a real invoice.paid, but your handler crashed before it answered. It reads invoice.subscription.id, and on this invoice subscription is empty. The customer paid $29.00 and never got access.
# Stripe webhook invoice.paid answers 500 (POST /api/webhooks/stripe). # The handler reads invoice.subscription.id, but subscription is empty here. Find the subscription safely, grant access, and always answer 200 after it.
Polar signed order.paid with your live secret and PayHook verified it. Your app answered 401, so it checks the signature with another secret, most likely the sandbox one. Every real payment gets rejected.
# Polar webhook order.paid answers 401 (POST /api/webhooks/polar). # The event is signed with the live secret, but the app verifies it with another one. Use the live endpoint secret in production and keep the sandbox one for local runs.
Paddle sent a real transaction.completed. Your handler sends the welcome email before it answers, the email call hung, and the request timed out before access was granted.
# Paddle webhook transaction.completed times out (POST /api/webhooks/paddle). # The handler sends the welcome email before it answers. Grant access, answer 200 right away, and send the email from a background job.
The problem
Stripe shows the charge. Your database shows a user on the free plan. There is no error anywhere, until the customer writes to you.
Test secret in production, a parsed body instead of raw bytes, or a stale timestamp. The message never says which.
Each one signs, retries and times out in its own way. Stripe CLI only speaks Stripe.
Apps built on Lovable or Bolt have nothing to forward to, and every tunnel restart means a new URL in every dashboard.
Cursor and Claude Code wrote the handler, but they never see the event that broke it.
How it works
1Connect
Point Stripe, Paddle, Lemon Squeezy, Polar or Dodo at your PayHook URL. Every event still reaches your app, byte for byte.
2Check
PayHook checks each signature the way that provider signs it, and records what your endpoint answered and how long it took.
3Fix
A plain-English diagnosis names the real cause. One click copies a fix prompt with the event inside, ready for Cursor or Claude Code.
After launch
Providers
stripe-signatureHMAC-SHA256, 5-minute windowSupported at launchpaddle-signatureHMAC-SHA256, 5-second windowSupported at launchx-signatureHMAC-SHA256, no timestampSupported at launchwebhook-signatureStandard Webhooks, both key formatsSupported at launchwebhook-signatureStandard WebhooksSupported at launchPricing
$0forever
Try PayHook on one project, with every signature check included.
Join the waitlist$12per month
For builders with paying customers who need the answer fast.
Join the waitlist$99once
Everything in Pro, for life. One payment, no subscription.
Get lifetime accessPayHook is in early access: the signature-verification core is built and tested; the hosted app ships in 4–6 weeks. Pre-order now — full refund anytime, no questions asked: just email [email protected].
Prices in USD. Lifetime includes a fair-use limit on AI diagnosis, with credits beyond it.
No. You paste your PayHook URL into the provider's webhook settings, and PayHook passes every event on to your endpoint with the original body and headers. Your handler keeps checking signatures exactly as it does today.
Stripe CLI is Stripe-only, terminal-only, and doesn't explain anything. PayHook covers five providers, works even when you have no localhost (Lovable, Bolt), and tells you why activation failed.
They transport and display webhooks — great at it. PayHook is payment-specific: signature schemes per provider, expected event sequences, and activation diagnosis. We tell you what's wrong, not just what arrived.
PayHook stores each event and answers the provider right away, then delivers it to your app with retries and shows every attempt. It is best effort with visible results, not guaranteed delivery with an SLA.
Replays are re-signed with your project's webhook secret using your provider's exact signature scheme and a fresh timestamp — so they pass the same verification your production code runs. Replayed events carry an X-PayHook-Replay header (with the original event id) so your handler can tell them apart.
It's built for you. Every event comes with a plain-English explanation and a fix prompt you paste into your editor. An MCP server is coming so your agent can read events itself.
Webhook events are stored for your debugging only — you can delete them anytime. The core is going open source, so you'll be able to self-host and keep everything on your own server.
Everything in Pro for one payment of $99, for as long as PayHook runs. AI diagnosis comes with a fair monthly limit, with credits beyond it. Only the first 100 buyers get it, then the offer closes for good.
Not yet. The signature-verification core is built and mutation-tested. The hosted app ships in 4–6 weeks. You're pre-ordering early access — full refund anytime, just email [email protected].
The core opens at launch: event intake, the inspector, signature checks and the CLI. The hosted cloud and the AI diagnosis are the paid part.
A solo fullstack developer with a fintech background, building in public — follow along on X.
Early access
Payments open once our merchant verification completes (days, not weeks). Leave your email — you'll get the early-bird link first, before the public.