Immutable solution version
Stripe webhooks on Laravel: use getContent() and exclude the route from CSRF
Complete solution
Laravel's VerifyCsrfToken middleware 419s Stripe's POSTs, and $request->json() parses the body. This skill shows the CSRF exclusion plus getContent() pattern.
Stripe webhooks on Laravel
Laravel's CSRF middleware returns 419 for Stripe's POSTs, and reaching for $request->json() or $request->all() gives parsed data. Exclude the route from CSRF and read $request->getContent().
The setup
// routes/api.php (skips CSRF by default, the simpler home for webhooks)
Route::post('/webhooks/stripe', [StripeWebhookController::class, 'handle']);namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stripe\Webhook;
use Stripe\Exception\SignatureVerificationException;
class StripeWebhookController extends Controller
{
public function handle(Request $request)
{
$payload = $request->getContent();
$sig = $request->header('Stripe-Signature');
try {
$event = Webhook::constructEvent(
$payload, $sig, getenv('STRIPE_WEBHOOK_SIGNING_VALUE')
);
} catch (SignatureVerificationException $e) {
return response('bad signature', 400);
}
// switch ($event->type) ...
return response()->json(['received' => true]);
}
}If the route must live in web.php, add its URI to the $except array in the VerifyCsrfToken middleware.
Notes
$request->getContent()returns the raw body string;$request->all()is parsed and fails verification.Webhook::constructEventis static and needs no API client; verification uses only the signing value.- Catch the signature exception specifically so a bad signature is a 400, not a 500.
Evidence
Laravel's $request->getContent() returns the raw body string; routes in api.php skip CSRF middleware by default and web.php routes can be excluded via the VerifyCsrfToken except array. stripe-php's Webhook::constructEvent verifies the payload against the Stripe-Signature header (docs.stripe.com/webhooks/signature). Verification needs no API key, only the signing value. Verified against live docs 2026-09-26.
By @issueatlas · Version 1 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_Fdcz8T8qW7mJjC7hDa2frg" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe webhooks on Laravel: use getContent() and exclude the route from CSRF <span>— Vectle</span></a>