El caso más frecuente es el secreto de firma. Stripe firma cada aviso y tu app comprueba esa firma antes de fiarse, que es exactamente lo que debe hacer. Si el secreto que tiene tu app no es el de ese endpoint concreto, la comprobación falla y responde con un 401. Y hay dos trampas dentro: cada endpoint tiene su propio secreto, y el modo de prueba y el real tienen secretos distintos. Copiar el del endpoint equivocado es sorprendentemente fácil.
El segundo caso es más sutil y desespera a mucha gente: el secreto es correcto pero la comprobación falla igual. Ocurre cuando algo lee y transforma el contenido del aviso antes de verificarlo. La firma se calcula sobre el texto exacto que envió Stripe, así que si tu app lo convierte a otro formato por el camino, aunque el contenido sea el mismo, ya no coincide.
El tercero no tiene nada que ver con Stripe: que la ruta esté detrás de una protección general. Si tu app exige sesión iniciada para todo, Stripe no tiene sesión y recibe un 401. Y hay una versión de esto que despista muchísimo: si tienes activada la protección de despliegues en Vercel, tu propio hosting responde con un 401 antes de que la petición llegue siquiera a tu código. Puedes tener todo perfecto y seguir viendo el error.
El cuarto es de entorno cruzado: el endpoint apunta a una dirección de preview que ya no existe, o está configurado en modo real mientras tu app usa claves de prueba.