Route Files

The Route Files and How They Are Loaded

A new Laravel 13 2,157 application has routes/web.php and routes/console.php; php artisan install:api adds routes/api.php under /api with the stateless api group, and installs Sanctum 2,988 (Sanctum Tokens). withRouting() in bootstrap/app.php (bootstrap/app.php) names each file, adds the /up health route, and runs a then: closure for extra files. Payment webhooks arrive without a CSRF token, so they get their own:

bootstrap/app.php: loading routes/webhooks.php with the api groupPHP
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        then: function () {
            Route::middleware('api')
                ->prefix('webhooks')
                ->name('webhooks.')
                ->group(base_path('routes/webhooks.php'));
        },
    )

routes/webhooks.php holds Route::post('/payments', ...)->name('payments'), which logs the event and returns response()->noContent(), served as /webhooks/payments and named webhooks.payments:

Output of 22
$ curl -i -X POST -d event=paid -d order_id=1 http://127.0.0.1:8303/webhooks/payments
HTTP/1.1 204 No Content
Cache-Control: no-cache, private

Only the web group runs sessions and the PreventRequestForgery check. A real webhook also verifies the sender's signature in a middleware (Writing a Middleware Class). Passing using: instead of web: makes your closure load every route file itself.