raditzfarhan / laravel-api-response
Laravel API response formatter
Package info
github.com/raditzfarhan/laravel-api-response
Type:laravel-package
pkg:composer/raditzfarhan/laravel-api-response
Requires
- php: ^8.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^5.0|^6.0|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0|^11.0
README
Laravel API Response
A fluent API response formatter for Laravel. Returns consistent JSON responses across your application with minimal boilerplate.
Requirements
- PHP ^8.0
- Laravel 9, 10, 11, 12 or 13
Installation
composer require raditzfarhan/laravel-api-response
The service provider is auto-discovered. No manual registration needed.
Basic Usage
Two styles are available — use whichever fits your preference:
// Via the response() helper macro (auto-registered) return response()->api()->success(); return response()->api()->failed(); // Via the facade return ApiResponse::success(); return ApiResponse::failed();
Both return an Illuminate\Http\JsonResponse instance.
Success response:
{
"status": true,
"http_code": 200,
"message": "Success."
}
Failed response:
{
"status": false,
"http_code": 500,
"message": "Failed."
}
Chaining
Build your response by chaining any combination of these methods before calling success() or failed():
| Method | Description |
|---|---|
httpCode(int $code) |
Set the HTTP status code |
message(string $message) |
Set the response message |
data(mixed $data) |
Set the response data |
errors(array $errors) |
Set validation/error details |
meta(array $meta) |
Set metadata |
links(array $links) |
Set pagination links |
code(int|string $code) |
Set an application-level error/status code |
headers(array $headers) |
Set custom HTTP response headers |
return ApiResponse::httpCode(201) ->message('User created successfully.') ->data(['id' => 1, 'name' => 'Raditz Farhan']) ->success();
{
"status": true,
"http_code": 201,
"message": "User created successfully.",
"data": {
"id": 1,
"name": "Raditz Farhan"
}
}
Application-Level Error Codes
Use code() to attach an application-specific error or status code alongside the HTTP status code:
return ApiResponse::code(40401)->notFound();
{
"status": false,
"http_code": 404,
"code": 40401,
"message": "Not found."
}
The code field only appears when set. Manage your own code definitions using constants or enums in your application.
Custom HTTP Headers
Use headers() to attach custom HTTP response headers. Headers are sent with the response but never appear in the JSON body:
return ApiResponse::headers([ 'X-Request-Id' => (string) Str::uuid(), 'X-Version' => '1.0', ])->success();
Shorthand Methods
Common HTTP responses have dedicated shorthand methods. All accept an optional $message parameter:
// 2xx return ApiResponse::created($data); // 201 return ApiResponse::collection($paginator); // 200 with meta & links // 4xx return ApiResponse::badRequest(); // 400 return ApiResponse::unauthorized(); // 401 return ApiResponse::forbidden(); // 403 return ApiResponse::notFound(); // 404 return ApiResponse::methodNotAllowed(); // 405 return ApiResponse::notAcceptable(); // 406 return ApiResponse::requestTimeout(); // 408 return ApiResponse::conflict(); // 409 return ApiResponse::gone(); // 410 return ApiResponse::validationError(); // 422 return ApiResponse::tooManyRequests(); // 429 // 5xx return ApiResponse::internalServerError(); // 500 return ApiResponse::notImplemented(); // 501 return ApiResponse::badGateway(); // 502 return ApiResponse::serviceUnavailable(); // 503 return ApiResponse::gatewayTimeout(); // 504
Pass a custom message to any of them:
return ApiResponse::conflict('A record with this email already exists.');
Validation Errors
return ApiResponse::validationError($validator->errors()->toArray());
{
"status": false,
"http_code": 422,
"message": "Validation error.",
"errors": {
"email": ["The email field is required."]
}
}
Paginated Collections
Pass a LengthAwarePaginator or AnonymousResourceCollection to collection():
return ApiResponse::collection(Post::paginate(25));
{
"status": true,
"http_code": 200,
"message": "Success.",
"data": [ ... ],
"meta": {
"current_page": 1,
"last_page": 3,
"from": 1,
"to": 25,
"per_page": 25,
"total": 60,
"has_more_pages": true
},
"links": {
"first": "https://example.com/posts?page=1",
"last": "https://example.com/posts?page=3",
"prev": null,
"next": "https://example.com/posts?page=2"
}
}
Exception Handling
To ensure all API error responses — including Laravel's built-in exceptions — follow the same structure, register custom renderers in your exception handler.
Laravel 11+ (bootstrap/app.php):
use Illuminate\Auth\AuthenticationException; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use RaditzFarhan\ApiResponse\Facades\ApiResponse; ->withExceptions(function (Exceptions $exceptions) { $exceptions->render(function (ValidationException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::validationError($e->errors(), $e->getMessage()); } }); $exceptions->render(function (AuthenticationException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::unauthorized(); } }); $exceptions->render(function (NotFoundHttpException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::notFound(); } }); })
Laravel 9 / 10 (app/Exceptions/Handler.php):
use Illuminate\Auth\AuthenticationException; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use RaditzFarhan\ApiResponse\Facades\ApiResponse; public function register(): void { $this->renderable(function (ValidationException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::validationError($e->errors(), $e->getMessage()); } }); $this->renderable(function (AuthenticationException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::unauthorized(); } }); $this->renderable(function (NotFoundHttpException $e, Request $request) { if ($request->expectsJson()) { return ApiResponse::notFound(); } }); }
The $request->expectsJson() guard ensures non-API routes (web, Blade) are unaffected and still render the default HTML error pages.
Configuration
Publish the config file to customise key names and add global fields:
php artisan vendor:publish --provider="RaditzFarhan\ApiResponse\ApiResponseServiceProvider"
This creates config/laravel-api-response.php.
Rename Response Keys
Rename any of the default JSON keys globally without changing your application code:
'keys' => [ 'status' => 'success', // "status" → "success" 'http_code' => 'code', // "http_code" → "code" 'message' => 'message', 'data' => 'data', 'errors' => 'errors', 'meta' => 'meta', 'links' => 'links', 'code' => 'error_code', ],
Global Fields
Append fields to every response automatically. Supports static values and closures:
'global_fields' => [ 'version' => '1.0', 'request_id' => fn() => request()->header('X-Request-Id'), ],
Every response will then include:
{
"status": true,
"http_code": 200,
"message": "Success.",
"version": "1.0",
"request_id": "abc-123"
}
IDE Support
All chainable and shorthand methods are annotated with @method PHPDoc on both the ApiResponse class and the facade, giving full autocomplete in PhpStorm, VS Code, and other IDEs.
Change log
Please see the changelog for more information on what has changed recently.
Credits
License
MIT. Please see the license file for more information.