hesamrad/laravel-api-debugger
A Laravel package for debugging API requests and responses. Capture outgoing and incoming calls, inspect payloads, headers, and status codes, and trace failures quickly—so you can see exactly what your app sends and receives without extra tooling. Great for local development and staging.
Install and enable
composer require hesamrad/laravel-api-debugger --dev
The package is aimed at the local/staging loop, so install it as a dev dependency unless you have a specific reason to run it in production (see Gotchas). Laravel's package auto-discovery should register the service provider; if not, add it to bootstrap/providers.php (Laravel 11+) or config/app.php.
Publish and read the config first
php artisan vendor:publish --tag=api-debugger-config
This is the single most important step. Read the generated config/api-debugger.php end to end before touching code — it will tell you the real story about which middleware alias is registered, whether there's an enable/disable env flag, where output is written, and which paths are excluded. Do not assume defaults from the README; the config file is the source of truth for your installed version.
First use case
API_DEBUGGER_ENABLED=true) in .env.bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php:->withMiddleware(function (Middleware $middleware) {
$middleware->appendToGroup('api', [
\HesamRad\ApiDebugger\Middleware\DebugApi::class,
]);
})
php artisan serve, hit one endpoint with curl or Postman, and inspect the output channel the config points at (a log file under storage/logs, a dedicated channel, or the response body itself depending on mode).If nothing appears, the usual culprits are: the middleware isn't in the api group, the env flag isn't set, or your request short-circuits before the middleware runs (404 from a missing route, or a global middleware rejecting it first). Check php artisan route:list --path=api before blaming the package.
Scope it to the API group, not globally. Appending to web as well means you'll be logging Inertia/Livewire payloads and session cookies for no benefit, and you'll add overhead to every page load. Keep it on api (or an even narrower custom group) so the tool stays cheap.
Use it as the "what did the client actually send" tool. The most common day-to-day failure in JSON API work is a mismatch between what the mobile app/SPA thinks it sent and what Laravel's validation sees. Enable the debugger, reproduce the failing call from the real client, and read the request payload as Laravel received it — after TrimStrings/ConvertEmptyStringsToNull, after any middleware that mutates input. That resolves an entire class of "but it works in Postman" tickets in minutes.
Pair it with your test suite for regression capture. When a bug is reported against a specific endpoint, reproduce it in a feature test, dump the request/response through the debugger, and use that as the fixture for the fix. The debugger is a discovery tool; the test is what keeps the fix honest.
Ordering matters relative to auth. Place the debugger after your auth middleware (Sanctum/Passport) if you want to see authenticated user context, or before it if you're debugging 401s and need to see requests that never reach the controller. In Laravel 11's bootstrap/app.php this means using prepend vs append deliberately, not by default:
$middleware->prependToGroup('api', DebugApi::class); // catches 401s
// vs
$middleware->appendToGroup('api', DebugApi::class); // catches 200/422s
Complement rather than replace your existing stack. If you already run Telescope, Ray, or Clockwork, don't try to make this the only observability layer — use it for the narrow JSON request/response view and let Telescope keep the queries, jobs, and cache hits. Teams that try to consolidate end up turning everything off.
Enforce redaction in the config, not in code review. Any JSON API debugger is one careless commit away from logging bearer tokens and passwords into storage/logs on a shared staging box. Configure the ignore/except list for password, token, Authorization, and payment fields before the first teammate uses it, and commit that config.
Gate it per-environment, not per-developer. The cleanest workflow: enabled in local and in a dedicated staging env, hard-disabled everywhere else via the env flag, plus a config-level guard. Don't rely on each developer remembering to flip it.
.env copy or a misconfigured deploy turns your API debugger into an unauthenticated data-exfiltration channel writing credentials to disk. Add the env flag to your deploy checklist or a config assertion that throws when app()->isProduction() and the debugger is on.204 No Content don't have a JSON body to inspect. Expect either empty entries or errors in the debug output for those routes — exclude them explicitly.Terminate. If the debugger captures the response, it usually needs to run late enough to see post-controller mutations but early enough to catch validation failures. Validate this empirically: hit an endpoint with a deliberate 422 and confirm the debugger records it. If it doesn't, your ordering is wrong.daily and a retention count in config/logging.php. A debugger that fills the disk will take staging down, and it will happen on a Friday./api/health, /api/metrics, /horizon/*, /telescope/*) so health checks don't flood the log with noise.composer.json, and after any composer update that bumps Laravel, hit one API endpoint and confirm the debug output still appears before assuming it works. Its --dev placement makes this low-risk; a broken dev tool should never block a deploy.php artisan config:clear first — a cached config from before you published the file is the most common cause.How can I help you explore Laravel packages today?