Guides · Free check · $9 fix pack

Guides

Stripe webhook on Supabase Edge Functions: fixing 401s and signature errors

Many apps built with Lovable or Bolt run their backend on Supabase. Two Supabase-specific settings break Stripe webhooks.

401 Unauthorized: JWT verification is on

By default, Edge Functions expect a Supabase JWT. Stripe can't send one. Supabase's config docs show disabling it for the webhook function in supabase/config.toml:

[functions.stripe-webhook]
verify_jwt = false

(Supabase docs: function configuration). Supabase warns this lets anyone call the function, which is why the next step is not optional.

Verify the signature the Deno way

Supabase's Stripe example reads the raw body with await req.text() and verifies with stripe.webhooks.constructEventAsync(body, signature, secret, undefined, cryptoProvider), where cryptoProvider = Stripe.createSubtleCryptoProvider() (Supabase docs: Stripe webhooks). Using the sync constructEvent or parsing JSON first fails.

Secrets: set the right whsec_ for the right mode

Store the endpoint's signing secret as a function secret. Test and live endpoints have different secrets (Stripe docs), so update it when you go live.

Prompt for your AI builder

In my Supabase Edge Function for Stripe webhooks: 1) set verify_jwt = false for this function only; 2) read the body with await req.text(); 3) verify with stripe.webhooks.constructEventAsync using Stripe.createSubtleCryptoProvider(); 4) return 400 if verification fails; 5) handle checkout.session.completed and checkout.session.async_payment_succeeded by granting access idempotently (skip if this session was already fulfilled); 6) return 200 quickly.
Check yours in 10 seconds (free).

Paste your webhook URL. WebhookProof sends 3 harmless test requests and tells you whether Stripe can reach it and whether it rejects unsigned events.

Run the free check

FAQ

Why does my Supabase Stripe webhook return 401?

Edge Functions verify a Supabase JWT by default and Stripe cannot send one. Set verify_jwt = false for that function and rely on Stripe signature verification instead.

Which Stripe verify function works in Deno / Supabase?

Supabase's example uses stripe.webhooks.constructEventAsync with Stripe.createSubtleCryptoProvider() and the raw body from req.text().

Is it safe to turn off JWT verification?

Only if the function verifies the Stripe signature and rejects anything that fails. Otherwise anyone can call it.

More guides

Stripe webhook not working? Check these 7 things in order · A customer paid but didn't get access. What went wrong? · Stripe webhook signature verification failed · Stripe webhook getting a 307 or 308 redirect

Last reviewed 2026-10-18. WebhookProof is an independent tool, not affiliated with Stripe, Inc. Quotes are from the linked documentation.