yousef-ahmed-abdalgawad / laravel-api-responder
Unified JSON API responses for Laravel — standardized success, error, and HTTP exception handling
Package info
github.com/yousef2002307/laravel-api-responder
pkg:composer/yousef-ahmed-abdalgawad/laravel-api-responder
Requires
- php: ^8.1
- illuminate/http: ^10|^11|^12|^13
- illuminate/support: ^10|^11|^12|^13
README
A lightweight Laravel package that standardizes JSON API responses and handles HTTP exceptions automatically — so every endpoint returns a consistent, predictable structure. easy to use
Features
- ✅ Unified JSON response format across all endpoints
- ✅ Trait with helpers for every common HTTP status code
- ✅ Automatic exception handling (401, 403, 404, 405, 422, 429, 500…)
- ✅ Pagination support built-in
- ✅ Laravel auto-discovery — zero manual registration
- ✅ Supports Laravel 11, 12, and 13
Installation
composer require yousef-ahmed-abdalgawad/laravel-api-responder
The package is auto-discovered by Laravel. No need to register the service provider manually.
Usage
1. ApiResponser Trait
Use the trait in any controller to get access to all response helpers:
use YousefAhmedAbdalgawad\ApiResponder\Traits\ApiResponser; class UserController extends Controller { use ApiResponser; public function index() { $users = User::paginate(10); return $this->successResponse( $users->items(), 'Users fetched successfully', 200, [ 'total' => $users->total(), 'per_page' => $users->perPage(), 'current_page' => $users->currentPage(), 'last_page' => $users->lastPage(), ] ); } public function show(User $user) { return $this->successResponse($user, 'User found'); } public function destroy(User $user) { $user->delete(); return $this->successResponseWithoutData('User deleted successfully'); } }
2. ApiExceptionHandler
Register the package's exception handler in your bootstrap/app.php to automatically handle common HTTP exceptions with a consistent JSON format:
use YousefAhmedAbdalgawad\ApiResponder\Exceptions\ApiExceptionHandler; ->withExceptions(function (Exceptions $exceptions): void { ApiExceptionHandler::register($exceptions); })
That's it — all API exceptions will now return structured JSON responses automatically.
Available Trait Methods
Success Responses
| Method | Status | Description |
|---|---|---|
successResponse($data, $message, $statusCode, $pagination) |
200 |
Return data with optional pagination |
successResponseWithoutData($message, $statusCode) |
200 |
Return message only, no data |
Error Responses
| Method | Status | Description |
|---|---|---|
errorResponse($message, $statusCode, $errors) |
any | Generic error with optional errors array |
unauthorizedResponse($message) |
401 |
Authentication required |
forbiddenResponse($message) |
403 |
Access denied |
notFoundResponse($message) |
404 |
Resource not found |
methodNotAllowedResponse($message) |
405 |
HTTP method not allowed |
conflictResponse($message) |
409 |
Duplicate / conflict |
badRequestResponse($message) |
400 |
Bad request |
requestEntityTooLargeResponse($message) |
413 |
Payload too large |
unsupportedMediaTypeResponse($message) |
415 |
Wrong content type |
serverErrorResponse($message) |
500 |
Internal server error |
serviceUnavailableResponse($message) |
503 |
Service unavailable |
Automatic Exception Handling
When ApiExceptionHandler::register($exceptions) is called, the following exceptions are caught and formatted automatically for API requests (api/* or expectsJson()):
| Exception | Status | Message |
|---|---|---|
ValidationException |
422 |
First validation error message |
ThrottleRequestsException |
429 |
Too many requests + retry_after seconds |
AuthenticationException |
401 |
Unauthorized |
NotFoundHttpException |
404 |
Route not found |
MethodNotAllowedHttpException |
405 |
Method not allowed |
AccessDeniedHttpException |
403 |
This action is unauthorized |
ModelNotFoundException |
404 |
Resource not found |
QueryException |
409 / 500 |
Duplicate entry or database error |
Throwable (fallback) |
500 |
Unexpected error |
Response Format
All responses follow this consistent structure:
Success
{
"status": 200,
"success": true,
"message": "Users fetched successfully",
"data": [...],
"pagination": {
"total": 50,
"per_page": 10,
"current_page": 1,
"last_page": 5
}
}
Error
{
"status": 422,
"success": false,
"message": "The email field is required.",
"errors": {
"email": ["The email field is required."]
}
}
Rate Limited (429)
{
"status": 429,
"success": false,
"message": "Too many requests. Please slow down.",
"retry_after": 45
}
Overriding the Exception Handler
You can override any specific handler after calling register() — Laravel renders exceptions in registration order:
->withExceptions(function (Exceptions $exceptions): void { // Register package handlers first ApiExceptionHandler::register($exceptions); // Then override specific ones for your app $exceptions->render(function (QueryException $e, $request) { // Your custom logic here }); })
Requirements
- PHP
^8.1 - Laravel
^11 | ^12 | ^13
License
The MIT License (MIT). Please see the LICENSE file for more information.