title: Stripe webhook needs different json body than standard api requests
body: <p>I can have a stripe webhook in my typescript backend, or I can have the stripe API - but not both...</p>
  <p>I have router setup so any url with &quot;/payment/&quot; calls on my stripe handlers in the paymentActions.tsx</p>
  <p><strong>Here is the app.ts:</strong></p>
  <pre><code>// app.ts
  
  import bodyParser from &quot;body-parser&quot;;
  import express from &quot;express&quot;;
  
  import { paymentActions } from &quot;../controllers/paymentActions&quot;;
  
  const app = express();
  
  app.use(express.static(&quot;public&quot;));
  app.use(express.urlencoded({ extended: true }));
  
  // IF I DISABLE THIS app.use THE STRIPE WEBHOOK WORKS
  app.use(
    bodyParser.json({
      // Because Stripe needs the raw body, we compute it but only when hitting the Stripe callback URL.
      verify: function (req, res, buf) {
        var url = req.url;
        //@ts-ignore
        req.rawBody = buf.toString();
      },
    })
  );
  
  // APIs
  app.use(&quot;/payment&quot;, paymentActions);
  
  export default app;
  </code></pre>
  <p>In paymentActions.tsx I have three endpoints. The two GET requests handle the stripe API to create and update payment intents. This works perfectly.</p>
  <p>The third endpoint is a stripe webhook that returns a 400 response. If I disable the app.use(bodyparser...) in app.ts above, the webhook now works (response 200) but the other two GET requests throw errors because the json body contains &quot;amount is NaN&quot;.</p>
  <p>Any ideas how I can fix this? Thanks!</p>
  <pre><code>// paymentActions.tsx
  
  import express from &quot;express&quot;;
  import * as stripe from &quot;../clients/stripe&quot;;
      
  export const paymentActions = express.Router();
  
  // Get payment intent
  paymentActions.get&lt;{}&gt;(&quot;/intent&quot;, async (req, res) =&gt; {
    const { amount } = req.body;
  
    try {
      const paymentIntent = await stripe.createPaymentIntent(amount);
      return res.status(200).json(paymentIntent);
    } catch (err) {
      res.status(400).send(`Webhook Error: ${err.message}`);
      return;
    }
  });
  
  // Update payment intent
  paymentActions.get&lt;{}&gt;(&quot;/updatedIntent&quot;, async (req, res) =&gt; {
    const { intentId, amount, metadata } = req.body;
  
    try {
      const paymentIntent = await stripe.updatePaymentIntent(intentId, amount, metadata);
      return res.status(200).json(paymentIntent);
    } catch (err) {
      res.status(400).send(`Webhook Error: ${err.message}`);
      return;
    }
  });
  
  
  // Stripe payment webhook
  paymentActions.post(
    &quot;/webhook&quot;,
    express.raw({ type: &quot;application/json&quot; }),
    (request, response) =&gt; {
      const stripe = require(&quot;stripe&quot;);
      const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
  
      let event = request.body;
      // Only verify the event if you have an endpoint secret defined.
      // Otherwise use the basic event deserialized with JSON.parse
      if (endpointSecret) {
        // Get the signature sent by Stripe
        const signature = request.headers[&quot;stripe-signature&quot;];
        try {
          event = stripe.webhooks.constructEvent(
            request.body,
            signature,
            endpointSecret
          );
        } catch (err) {
          console.log(`⚠️  Webhook signature verification failed.`, err.message);
          return response.sendStatus(400);
        }
      }
  
      // Handle the event
      switch (event.type) {
        case &quot;payment_intent.succeeded&quot;:
          // Handle payment intent
          break;
        default:
          // Unexpected event type
      }
  
      // Return a 200 response to acknowledge receipt of the event
      response.send();
    }
  );
  </code></pre>