In this article I want to explain how to generate a Swagger file in a Laravel project. Swagger lets you describe the structure of your APIs via the OpenAPI Specification and gives you an interactive UI for your API documentation.

The first step is installing the L5 Swagger extension via Composer:

composer require "darkaonline/l5-swagger"

and publishing its vendor assets:

php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

Now we configure the extension by editing the config/l5-swagger.php file:

// config/l5-swagger.php

'api' => [
    'title' => 'Foo Bar Project',
],

'routes' => [
    'api' => 'api/docs',
],

'paths' => [
    'docs' => public_path('api-docs'),
],

'docs_json' => 'swagger.json',
'docs_yaml' => 'swagger.yaml',

If you are using Sanctum to secure your APIs, uncomment the Auth/Sanctum section.

Then add this annotation to the app/Http/Controllers/Controller.php file:

/**
 * @OA\Info(
 *     version="1.0",
 *     title="Foo Bar Project",
 *     description="API Documentation for Foo Bar Project"
 * )
 */

If you are using Sanctum, add this annotation snippet too:

/**
 * @OA\SecurityScheme(
 *     securityScheme="sanctum",
 *     type="http",
 *     scheme="sanctum"
 * )
 */

Use annotations to describe every API endpoint, on your controller methods:

/**
 * @OA\Get(
 *     path="/api/users",
 *     summary="Users List",
 *     tags={"Users"},
 *     description="Users List Endpoint.",
 *     @OA\Parameter(in="header", required=false, name="application_id", @OA\Schema(type="integer")),
 *     @OA\Parameter(in="path", required=false, name="group", @OA\Schema(type="string")),
 *     @OA\Parameter(in="query", required=false, name="search", @OA\Schema(type="string")),
 *     @OA\Response(response=200, description="Successful request"),
 *     @OA\Response(response=422, description="Invalid payload"),
 *     @OA\Response(response=401, description="Unauthorized")
 * )
 */
public function index(Request $request)
{

If you are using Sanctum, add this line inside the annotation:

security={{"sanctum": {}}},

To describe your APIs, use the OpenAPI and L5 Swagger documentation:

The following snippets are examples:

/**
 * @OA\Post(
 *     path="/api/users",
 *     summary="Users Store",
 *     tags={"Users"},
 *     description="Create User Endpoint",
 *     @OA\RequestBody(
 *         required=true,
 *         @OA\MediaType(
 *             mediaType="multipart/form-data",
 *             @OA\Schema(
 *                 @OA\Property(property="name", type="string"),
 *                 @OA\Property(property="email", type="string"),
 *                 @OA\Property(property="password", type="string"),
 *                 required={"email", "password"}
 *             )
 *         )
 *     ),
 *     @OA\Response(response=201, description="Successful Created"),
 *     @OA\Response(response=422, description="Invalid payload")
 * )
 */
public function store(Request $request)
{
/**
 * @OA\Put(
 *     path="/api/users",
 *     summary="Users Update",
 *     tags={"Manager", "User"},
 *     @OA\RequestBody(
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="email", type="string"),
 *             @OA\Property(property="password", type="string"),
 *         )
 *     ),
 *     @OA\Response(response=200, description="Successful request"),
 *     @OA\Response(response=422, description="Invalid payload"),
 *     @OA\Response(response=401, description="Unauthorized")
 * )
 */
public function update(Request $request)
/**
 * @OA\Schema(
 *     schema="UserRegistration",
 *     title="User Schema",
 *     @OA\Property(property="id", description="User ID", type="integer"),
 *     @OA\Property(property="team_id", description="Team ID", type="integer")
 * )
 * @OA\Post(
 *     path="/api/register",
 *     summary="Registration",
 *     tags={"Auth"},
 *     description="Registration Endpoint.",
 *     @OA\RequestBody(
 *         required=true,
 *         @OA\MediaType(
 *             mediaType="multipart/form-data",
 *             @OA\Schema(
 *                 @OA\Property(property="email", type="string", description="User email"),
 *                 @OA\Property(property="photo", type="file", description="User photo"),
 *                 required={"email"}
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Successful user registration",
 *         @OA\JsonContent(
 *             @OA\Property(property="data", type="object", ref="#/components/schemas/UserRegistration")
 *         )
 *     )
 * )
 */
public function register(AuthRegistrationRequest $request)
{

To generate the Swagger file, run:

php artisan l5-swagger:generate

Now you can visit the /api/docs URL and explore a basic Swagger UI.

You can customize your project's Swagger UI with this code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ config('l5-swagger.documentations.'.$documentation.'.api.title') }}</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.18.3/swagger-ui.css" />
    <style>
        html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
        *, *:before, *:after { box-sizing: inherit; }
        body { margin: 0; background: #fafafa; }
    </style>
</head>
<body>
    <div id="swagger-ui"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.18.3/swagger-ui-standalone-preset.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.18.3/swagger-ui-bundle.js"></script>
    <script>
    window.onload = function () {
        const ui = SwaggerUIBundle({
            requestInterceptor: function (request) {
                request.headers['accept'] = 'application/json';
                return request;
            },
            url: window.location.protocol + "//" + window.location.host + "/api-docs/swagger.json",
            dom_id: '#swagger-ui',
            deepLinking: true,
            presets: [
                SwaggerUIBundle.presets.apis,
                SwaggerUIStandalonePreset
            ],
            layout: "StandaloneLayout"
        });
        window.ui = ui;
    }
    </script>
</body>
</html>

Now it's your turn — enjoy your next project's Swagger!