Language:

Search

Laravel Scramble: documentación OpenAPI “de verdad” sin volverte loco (guía paso a paso)

  • Share this:
Laravel Scramble: documentación OpenAPI “de verdad” sin volverte loco (guía paso a paso)

Si llevas tiempo haciendo APIs en Laravel, ya sabes el dolor: documentación desactualizada, endpoints que cambian, validaciones que no se reflejan en Swagger, etc. Scramble viene a quitarte ese peso de encima generando documentación OpenAPI 3.1 a partir de tu código y convenciones de Laravel (FormRequests, Resources, rutas, modelos…).

En este artículo vamos a montarlo desde cero y dejarlo fino: instalación, publicación de configuración, seguridad de acceso, y ejemplos reales con código.


1) ¿Qué es Scramble y qué te aporta?

Scramble es un generador moderno de documentación OpenAPI para Laravel que:

Te crea el UI de docs y el JSON OpenAPI

Detecta rutas y operaciones automáticamente (por defecto, rutas bajo api/*)

Entiende muchas cosas típicas de Laravel: validaciones en FormRequest, Resources, paginación, enums, etc.

Cuando lo instalas, expone dos rutas:

/docs/api → la web para ver la doc

/docs/api.json → el JSON OpenAPI

Y detalle importante: por defecto esas rutas solo están accesibles en local


2) Requisitos

Según la doc oficial:

PHP 8.1+

Laravel 10+


3) Instalación

En tu proyecto:

composer require dedoc/scramble


Eso ya registra las rutas /docs/api y /docs/api.json.

Prueba en local:

https://tu-app.test/docs/api


4) Publicar el archivo de configuración

Scramble funciona “out of the box”, pero en cuanto quieras controlar qué documenta y cómo se ve, vas a querer el config.

php artisan vendor:publish --provider="Dedoc\Scramble\ScrambleServiceProvider" --tag="scramble-config"


Esto te crea config/scramble.php y desde ahí ajustas el comportamiento.


5) Entendiendo config/scramble.php (lo importante)

5.1 api_path: qué rutas entran en la doc

Por defecto, Scramble documenta rutas bajo api (o sea api/*). Si tu API vive en api/v1, ajusta:

// config/scramble.php
return [
    'api_path' => 'api/v1',
];


Scramble lo menciona tal cual: por defecto agrega rutas que empiezan por api, y puedes cambiarlo con scramble.api_path

5.2 api_domain: si tu API va por subdominio

Si tienes algo tipo api.tusitio.com, puedes fijarlo:

return [
    'api_domain' => 'api.tusitio.com',
];


Por defecto es null (usa el dominio actual).

5.3 info: lo que se ve en el “home” de /docs/api


La descripción soporta Markdown:

return [
    'info' => [
        'version' => env('API_VERSION', '0.0.1'),
        'description' => <<<MD
Bienvenido a la documentación de mi API.

- Autenticación: Bearer Token
- Soporte: soporte@tusitio.com
MD,
    ],
];


La doc indica que scramble.info.description se renderiza en /docs/api y soporta Markdown.

6) Seguridad: permitir acceso a /docs/api en producción (Gate)

Por defecto, solo local puede ver las docs. Si quieres habilitarlo en staging/prod, defines el Gate viewApiDocs.

// app/Providers/AppServiceProvider.php

use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('viewApiDocs', function (User $user) {
        return in_array($user->email, [
            'admin@app.com',
        ]);
    });
}

 

Esto hace que, fuera de local, solo quien pase el gate pueda acceder.


7) Control fino: decidir tú qué rutas se documentan


Además del api_path, puedes filtrar rutas con una función “resolver” en un Service Provider usando Scramble::configure()->routes(...).

Ejemplo: documentar solo api/* y excluir healthchecks:

// app/Providers/AppServiceProvider.php

use Dedoc\Scramble\Scramble;
use Illuminate\Routing\Route;
use Illuminate\Support\Str;

public function boot(): void
{
    Scramble::configure()
        ->routes(function (Route $route) {
            if (! Str::startsWith($route->uri, 'api/')) {
                return false;
            }

            // Excluye endpoints tipo /api/health
            return $route->uri !== 'api/health';
        });
}

8) Ejemplo completo: endpoint REST con FormRequest + Resource

Vamos a montar un endpoint típico de “Users” para que veas cómo Scramble saca jugo de tus convenciones.

8.1 Ruta
 

// routes/api.php

use App\Http\Controllers\Api\UserController;
use Illuminate\Support\Facades\Route;

Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
Route::get('/users/{user}', [UserController::class, 'show']);


8.2 FormRequest con validaciones (Scramble lo aprovecha)
 

// app/Http/Requests/StoreUserRequest.php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name'  => ['required', 'string', 'min:2'],
            'email' => ['required', 'email', 'unique:users,email'],
        ];
    }
}

 

8.3 API Resource para respuesta consistente
 

// app/Http/Resources/UserResource.php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

/** @mixin \App\Models\User */
class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id'    => $this->id,
            'name'  => $this->name,
            'email' => $this->email,
        ];
    }
}

 

8.4 Controller
 

// app/Http/Controllers/Api/UserController.php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\Resources\Json\ResourceCollection;

class UserController extends Controller
{
    public function index(): ResourceCollection
    {
        return UserResource::collection(
            User::query()->paginate(15)
        );
    }

    public function store(StoreUserRequest $request): UserResource
    {
        $user = User::query()->create($request->validated());

        return new UserResource($user);
    }

    public function show(User $user): UserResource
    {
        return new UserResource($user);
    }
}

 

Con esto, Scramble suele ser capaz de:

  • Detectar parámetros de path ({user})
  • Detectar estructura de respuesta (por el Resource)
  • Detectar validaciones del request (por el FormRequest)
  • Detectar paginación (cuando devuelves paginate(), según la evolución reciente del paquete)

9) Documentar autenticación (Bearer) para toda la API


OpenAPI necesita que declares los esquemas de seguridad. Scramble lo resuelve con document transformers.

Ejemplo: marcar toda la API como Bearer:

// app/Providers/AppServiceProvider.php

use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;

public function boot(): void
{
    Scramble::configure()
        ->withDocumentTransformers(function (OpenApi $openApi) {
            $openApi->secure(
                SecurityScheme::http('bearer')
            );
        });
}


Esto está tal cual en la doc de autenticación de Scramble.


10) Resultado: revisa tu documentación


Arrancas local:

php artisan serve


Visitas:

http://localhost:8000/docs/api

http://localhost:8000/docs/api.json

Y deberías ver:

  • Endpoints listados
  • Esquemas de request/response
  • Validaciones reflejadas
  • Auth marcada (si aplicaste el transformer)

Conclusión (y consejo de senior a senior)


Scramble brilla cuando te apoyas en “Laravel bien hecho”:

  • FormRequests para entrada
  • Resources para salida
  • Rutas limpias y REST
  • Paginación estándar

Así la documentación sale sola… y lo mejor: tiende a mantenerse en sync con tu código. 

Carlos Santiago

Carlos Santiago

Laravel Developer