laravel-api-responses maintained by talish
🚀 talish/laravel-api-responses
A professional, expressive Laravel API response package. Replace verbose response()->json([...]) calls with clean, consistent, and self-documenting API responses.
Before:
return response()->json([
'status' => true,
'message' => 'User created',
'data' => $user,
], 201);
After:
return api()->created($user, 'User created');
Requirements
| Package Version | Laravel | PHP |
|---|---|---|
| 1.x | 10.x | ≥ 8.1 |
| 1.x | 11.x | ≥ 8.2 |
Installation
composer require talish/laravel-api-responses
The package auto-discovers itself via Laravel's package discovery. No manual provider registration needed.
Publish Config (optional)
php artisan vendor:publish --tag=api-responses-config
This publishes config/api-responses.php where you can customise the response structure, JSON flags, and global headers.
Usage
Global Helper api()
The quickest way — available anywhere in your application:
// 200 OK
return api()->success($data);
return api()->success($data, 'Users fetched');
// 201 Created
return api()->created($user);
return api()->created($user, 'Account registered');
// 204 No Content
return api()->noContent();
// 400 Bad Request
return api()->badRequest('Invalid input');
// 401 Unauthorized
return api()->unauthorized();
return api()->unauthorized('Token has expired');
// 403 Forbidden
return api()->forbidden('You cannot access this resource');
// 404 Not Found
return api()->notFound();
return api()->notFound('Post not found');
// 422 Validation
return api()->validation($validator->errors());
return api()->validation($request->errors(), 'The form has errors');
// 429 Too Many Requests
return api()->tooManyRequests();
// 500 Server Error
return api()->error('Something went wrong');
return api()->error('Database failure', 500, ['detail' => '...']);
// 503 Service Unavailable
return api()->serviceUnavailable();
// Fully custom
return api()->custom(true, $data, 'All good', 200);
Facade ApiResponse::
use Talish\ApiResponses\Facades\ApiResponse;
return ApiResponse::success($data);
return ApiResponse::notFound('Item missing');
HasApiResponses Trait (for Controllers)
Add the trait to your base controller to call methods on $this:
use Talish\ApiResponses\Traits\HasApiResponses;
class Controller extends BaseController
{
use HasApiResponses;
}
// In any child controller:
class UserController extends Controller
{
public function index(): JsonResponse
{
$users = User::paginate(15);
return $this->success($users, 'Users fetched');
}
public function store(StoreUserRequest $request): JsonResponse
{
$user = User::create($request->validated());
return $this->created($user);
}
public function show(User $user): JsonResponse
{
return $this->success($user);
}
public function destroy(User $user): JsonResponse
{
$user->delete();
return $this->noContent();
}
}
Response JSON Structure
Every response follows this consistent shape:
{
"status": true,
"status_code": 200,
"message": "Success",
"data": { ... }
}
Error responses add an optional errors key:
{
"status": false,
"status_code": 422,
"message": "Validation failed",
"data": null,
"errors": {
"email": ["The email field is required."]
}
}
Paginated Responses
Pass a LengthAwarePaginator or ResourceCollection and pagination metadata is automatically included:
$users = User::paginate(15);
return api()->success($users);
{
"status": true,
"status_code": 200,
"message": "Success",
"data": [ ... ],
"meta": {
"current_page": 1,
"per_page": 15,
"total": 120,
"last_page": 8,
"from": 1,
"to": 15,
"path": "https://example.com/api/users"
},
"links": {
"first": "https://example.com/api/users?page=1",
"last": "https://example.com/api/users?page=8",
"prev": null,
"next": "https://example.com/api/users?page=2",
"self": "https://example.com/api/users?page=1"
}
}
Laravel API Resources
Works seamlessly with JsonResource and ResourceCollection:
return api()->success(new UserResource($user));
return api()->success(UserResource::collection($users));
Global Exception Handling
Register the included exception handler in app/Exceptions/Handler.php to automatically format all exceptions as API responses:
use Talish\ApiResponses\Exceptions\ApiExceptionHandler;
public function register(): void
{
$this->renderable(function (Throwable $e, Request $request) {
if ($request->expectsJson()) {
return (new ApiExceptionHandler)->handle($e);
}
});
}
This automatically converts:
| Exception | Response |
|---|---|
ValidationException |
422 with errors |
AuthenticationException |
401 Unauthorized |
AuthorizationException |
403 Forbidden |
ModelNotFoundException |
404 Not Found |
NotFoundHttpException |
404 Not Found |
HttpException |
Matching HTTP status |
| Everything else | 500 (with trace in debug mode) |
Configuration
After publishing, edit config/api-responses.php:
return [
// Keys and order in every response
'structure' => [
'status',
'status_code',
'message',
],
// Strip null values from response payload
'remove_null_values' => false,
// json_encode() flags
'json_options' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
// Global headers added to every response
'headers' => [
'X-API-Version' => '1.0',
],
];
Complete Controller Example
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Talish\ApiResponses\Traits\HasApiResponses;
class UserController extends Controller
{
use HasApiResponses;
public function index(): JsonResponse
{
$users = User::paginate(15);
return $this->success(UserResource::collection($users), 'Users fetched successfully');
}
public function store(StoreUserRequest $request): JsonResponse
{
$user = User::create($request->validated());
return $this->created(new UserResource($user), 'User registered');
}
public function show(User $user): JsonResponse
{
return $this->success(new UserResource($user));
}
public function update(UpdateUserRequest $request, User $user): JsonResponse
{
$user->update($request->validated());
return $this->success(new UserResource($user), 'User updated');
}
public function destroy(User $user): JsonResponse
{
$user->delete();
return $this->noContent();
}
}
Testing
composer test
Changelog
Please see CHANGELOG.md for details.
Contributing
Pull requests are welcome. Please open an issue first for major changes.
License
MIT. Please see LICENSE.md for details.