DEV Community

Cover image for Auto-Generate Swagger Docs in Laravel — Zero Annotations, Zero Config
Aliza Ali
Aliza Ali

Posted on

Auto-Generate Swagger Docs in Laravel — Zero Annotations, Zero Config

Writing Swagger Annotations Is Pain. What If You Didn't Have To?

Be honest — how many times have you:

  • Skipped API documentation because @OA\Get annotations are a nightmare?
  • Spent more time writing Swagger comments than actual business logic?
  • Shipped an API with zero docs because "we'll add them later" (you didn't)?
  • Manually maintained a Postman collection that's always 3 endpoints behind?

What if your Laravel app could scan your controllers, read your FormRequest rules, and generate a complete Swagger UI automatically?

No @OA\ annotations. No YAML files. No config. Just your existing code.


Introducing: Laravel API Response Builder

composer require stackmasteraliza/laravel-api-response
Enter fullscreen mode Exit fullscreen mode

v4.7.0 | Laravel 10, 11 & 12 | PHP 8.1+ | MIT License
GitHub | Packagist

The all-in-one Laravel API toolkit:

  • Auto-generated Swagger/OpenAPI docs — no annotations
  • One-click export to Postman & Insomnia
  • Standardized JSON responses
  • WebSocket testing built-in
  • API versioning out of the box

Zero configuration required.


Installation (30 Seconds)

composer require stackmasteraliza/laravel-api-response
Enter fullscreen mode Exit fullscreen mode

That's it. No config publishing. No migrations. No setup wizards.

Your Swagger docs are already live at /api-docs.


Auto-Generated Swagger Docs (The Main Event)

This is why you're here. You don't write a single @OA\ annotation.

The package scans your controllers, detects response methods like ApiResponse::success() and ApiResponse::created(), reads your FormRequest validation rules, and generates a complete OpenAPI 3.0 specification — automatically.

Visit /api-docs and you get:

  • Beautiful, modern Swagger UI with dark/light theme toggle
  • Every endpoint documented with correct HTTP methods
  • Request body schemas auto-generated from your FormRequest rules
  • Response schemas matching your actual response structure
  • Try-it-out functionality — test endpoints right from the browser

How It Detects Everything

// The package sees this in your controller...
public function store(StoreUserRequest $request)
{
    $user = User::create($request->validated());
    return ApiResponse::created($user, 'User created');
}
Enter fullscreen mode Exit fullscreen mode
// ...reads your FormRequest rules...
class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8',
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

Result: A fully documented POST endpoint in Swagger with request body schema, required fields, validation types, and a 201 Created response — all without you writing a single doc comment.

Want Even More Control? Use PHP Attributes

use Stackmasteraliza\ApiResponse\Attributes\ApiEndpoint;
use Stackmasteraliza\ApiResponse\Attributes\ApiRequestBody;

#[ApiEndpoint(
    summary: 'Create a new user',
    description: 'Register a new user account',
    tags: ['Users']
)]
#[ApiRequestBody(
    properties: ['name' => 'string', 'email' => 'string', 'password' => 'string'],
    required: ['name', 'email', 'password']
)]
public function store(StoreUserRequest $request): JsonResponse
{
    $user = User::create($request->validated());
    return ApiResponse::created($user, 'User created');
}
Enter fullscreen mode Exit fullscreen mode

Attributes are optional — use them only when you want to add summaries, descriptions, or override auto-detected schemas.


Export to Postman & Insomnia (One Click)

From the Swagger UI, export your entire API documentation:

Format Use Case
Postman Import directly into Postman
Insomnia Import directly into Insomnia
JSON CI/CD pipelines, SDK generation
YAML Human-readable specs

Your Postman collection is always in sync with your code. No manual maintenance.


API Versioning in Swagger UI

API_DOCS_VERSIONING=true
Enter fullscreen mode Exit fullscreen mode

The package auto-detects api/v1/*, api/v2/* patterns and adds a version switcher in the Swagger UI. Each version gets its own OpenAPI spec. Your frontend team can browse docs for any version.


WebSocket Testing (Yes, In Swagger)

Test WebSocket connections directly from the Swagger UI. Send messages, subscribe to channels, see real-time responses — with pre-built templates for Subscribe, Unsubscribe, Ping, and Client Events.

No Postman. No wscat. Just click and test.


But Wait — It's Also a Complete Response Builder

The Facade Way

use Stackmasteraliza\ApiResponse\Facades\ApiResponse;

class UserController extends Controller
{
    public function index()
    {
        $users = User::paginate(15);
        return ApiResponse::success($users, 'Users retrieved');
    }

    public function store(StoreUserRequest $request)
    {
        $user = User::create($request->validated());
        return ApiResponse::created($user, 'User created');
    }

    public function destroy(User $user)
    {
        $user->delete();
        return ApiResponse::noContent();
    }
}
Enter fullscreen mode Exit fullscreen mode

Or Use the Trait

use Stackmasteraliza\ApiResponse\Traits\HasApiResponse;

class UserController extends Controller
{
    use HasApiResponse;

    public function index()
    {
        return $this->success(User::paginate(15), 'Users retrieved');
    }
}
Enter fullscreen mode Exit fullscreen mode

Both give you perfectly consistent responses:

{
    "status_code": 200,
    "success": true,
    "message": "Users retrieved",
    "data": [
        { "id": 1, "name": "John Doe" },
        { "id": 2, "name": "Jane Doe" }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 15,
        "total": 50,
        "last_page": 4,
        "from": 1,
        "to": 15,
        "links": {
            "first": "http://example.com/api/users?page=1",
            "next": "http://example.com/api/users?page=2"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Pagination metadata is automatically detected and included. No extra code.


Every Error Response You'll Ever Need

ApiResponse::badRequest('Invalid input');           // 400
ApiResponse::unauthorized('Token expired');          // 401
ApiResponse::forbidden('Admin only');                // 403
ApiResponse::notFound('User not found');             // 404
ApiResponse::conflict('Email already exists');       // 409
ApiResponse::validationError($errors);               // 422
ApiResponse::tooManyRequests('Slow down', 60);       // 429
ApiResponse::serverError('Something broke');          // 500
ApiResponse::serviceUnavailable('Back soon');         // 503
Enter fullscreen mode Exit fullscreen mode

Consistent structure every time:

{
    "status_code": 422,
    "success": false,
    "message": "Validation failed",
    "errors": {
        "email": ["The email field is required."],
        "password": ["The password must be at least 8 characters."]
    }
}
Enter fullscreen mode Exit fullscreen mode

Exception Handling That Just Works

Drop this into your bootstrap/app.php (Laravel 11+):

use Stackmasteraliza\ApiResponse\Exceptions\ApiExceptionHandler;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (Throwable $e, Request $request) {
        return (new ApiExceptionHandler())->handle($e, $request);
    });
})
Enter fullscreen mode Exit fullscreen mode

Now every exception — ValidationException, ModelNotFoundException, AuthenticationException — returns a clean, consistent JSON response. No more HTML error pages in your API.


Testing Helpers

Write expressive API tests:

$response = $this->getJson('/api/users');

$response->assertApiSuccess()
         ->assertApiStatusCode(200)
         ->assertApiMessage('Users retrieved')
         ->assertApiHasData()
         ->assertApiPaginated();
Enter fullscreen mode Exit fullscreen mode

Customize Everything

Publish the config and make it yours:

php artisan vendor:publish --tag=api-response-config
Enter fullscreen mode Exit fullscreen mode

Change response keys, pagination keys, default messages, theme colors, branding — everything is configurable.

// config/api-response.php
'keys' => [
    'success'     => 'success',
    'message'     => 'message',
    'data'        => 'data',
    'errors'      => 'errors',
    'meta'        => 'meta',
    'status_code' => 'status_code',
],
Enter fullscreen mode Exit fullscreen mode

Extend With Custom Macros

Need custom response types? The package is macroable:

ApiResponse::macro('banned', function (string $reason = 'Account suspended') {
    return $this->error($reason, 403);
});

// Then use it anywhere
return ApiResponse::banned('Your account has been suspended');
Enter fullscreen mode Exit fullscreen mode

Why Developers Are Switching

Before After
Writing @OA\ annotations for hours Auto-generated Swagger docs from code
Postman collections always outdated One-click Postman/Insomnia export
No WebSocket documentation Built-in WebSocket tester in Swagger
Inconsistent response formats One standardized JSON structure
Custom exception handlers Built-in error handling
Copy-paste response code One-liner fluent methods

Quick Start Recap

# 1. Install
composer require stackmasteraliza/laravel-api-response

# 2. Use in controllers
# (Facade or Trait — your choice)

# 3. Visit /api-docs
# Your documentation is already there
Enter fullscreen mode Exit fullscreen mode

Supports Laravel 10, 11, and 12 | PHP 8.1+


Links


Let's Connect

If this package saves you time, give it a star on GitHub and share it with your team.

Got questions, ideas, or feature requests? Drop a comment below or open an issue on GitHub.

Follow me for more Laravel packages and PHP tips:

Happy coding!
Aliza Ali (@stackmasteraliza)

Top comments (2)

Collapse
 
tuba_tahir_24e32d0802eeec profile image
Tuba Tahir

So insightful✨️

Collapse
 
stackmasteraliza profile image
Aliza Ali

Thank u