#scrambledrop: Scramble 0.13.34
July 14, 2026
Automatic API authentication documentation, OpenAPI caching, Scalar UI support, plain PHP objects documentation, and continued validation and type inference improvements.
Since the 0.13.21 post, Scramble has shipped thirteen patch releases through v0.13.34. This post covers the most notable changes since v0.13.21.
Upgrade:
composer require dedoc/scramble:^0.13.34If your published config/scramble.php is older, add the new cache, renderer, renderers, and security_strategy keys from the latest config. This release series does not introduce breaking changes, but some features are opt-in.
Automatically document API authentication
Documenting authentication in OpenAPI used to mean wiring security schemes by hand — usually in Scramble::extendOpenApi() — and then remembering which endpoints are public. Easy to get wrong, easy to let drift.
v0.13.24 adds MiddlewareAuthSecurityStrategy: Scramble looks at route middleware and derives security from it. When at least one documented route uses auth / auth:*, Scramble adds a global bearer auth scheme and marks routes without matching middleware as public.
It is opt-in. In config/scramble.php, security_strategy is null by default. Uncomment or set it to enable:
'security_strategy' => \Dedoc\Scramble\SecurityDocumentation\MiddlewareAuthSecurityStrategy::class,If you already configure security manually via extendOpenApi / afterOpenApiGenerated, leave this disabled — otherwise you’ll get duplicate schemes.
Typical Sanctum API
Most Laravel APIs protect routes with auth:sanctum. That matches the default middleware pattern (auth and auth:*), so no extra config is needed beyond enabling the strategy.
// routes/api.phpuse App\Http\Controllers\AuthController;use App\Http\Controllers\ProjectController;use Illuminate\Support\Facades\Route;
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () { Route::get('/projects', [ProjectController::class, 'index']); Route::post('/projects', [ProjectController::class, 'store']);});With security_strategy enabled, Scramble produces:
- a global
httpbearer security scheme /projectsGET and POST inheriting that scheme (they haveauth:sanctum)/loginmarked public viasecurity: []
Protected operations don’t repeat security on each operation — they inherit the document-level default. Public ones explicitly set security: [], which OpenAPI tools interpret as “no auth required.”
If none of the documented routes match the configured auth middleware, Scramble does not add global security or per-route security: [] entries.
Read the authentication documentation for the full setup and customization options.
OpenAPI document caching
Generating OpenAPI means analyzing every documented route — controllers, form requests, return types, validation rules. On a large app, that takes time.
v0.13.27 adds optional caching. Cache the generated document so Scramble does not repeat that analysis on every request. The /docs/api UI route and /docs/api.json specification route use the cached document when it is available.
Cache the documentation:
php artisan scramble:cacheClear it:
php artisan scramble:clearSee caching the OpenAPI document for deployment and multi-API usage.
UI renderers: Scalar and more
Scramble has shipped with Stoplight Elements as the default docs UI. Starting in v0.13.25, the renderer is pluggable — Scalar is the first alternative.
Switching to Scalar
// config/scramble.php'renderer' => 'scalar',That’s it. /docs/api now renders via Scalar instead of Elements. The OpenAPI spec itself is unchanged — only the UI wrapper changes.
See the documentation UI renderers guide for renderer options and per-API configuration.
include / exclude filtering on scramble.api_path
By default, api_path is 'api' — Scramble documents routes under the api prefix and strips it from paths (server http://localhost/api, paths /users, /projects).
v0.13.24 extends this with include and exclude for finer control over which routes land in the spec.
'api_path' => [ 'include' => 'api', 'exclude' => ['api/internal'],],This documents routes under api while omitting the internal subset.
See route filtering for wildcard and multiple-base behavior.
Assign routes to concrete API specs with #[Api]
When you register multiple APIs with Scramble::registerApi, route resolvers and api_path filters already control which routes land in each spec. v0.13.34 adds #[Api] for assignment at the controller class, controller method, or closure level.
Routes without the attribute behave as before — if they pass the resolver and path filters, they appear in every matching API. Annotated routes are included only in the named APIs.
Same routes, different audiences
When multiple registered APIs intentionally see the same route set, use #[Api] to decide which operations appear in which spec:
use Dedoc\Scramble\Attributes\Api;use Dedoc\Scramble\Scramble;
Scramble::registerApi('public');
Scramble::registerApi('internal');
class ProjectController{ // In both specs when both resolvers match public function index() {}
#[Api('internal')] public function auditLog() {}}See assigning routes to concrete API specs for class-level assignment and filtering behavior.
Plain objects documentation
Scramble already handles Eloquent models, API resources, Laravel Data, paginators. Real codebases also return plain PHP classes — DTOs, value objects, ad-hoc shapes.
v0.13.27 adds PlainObjectToSchema: Scramble analyzes public properties (or jsonSerialize() output) and produces component schemas.
Public properties
class ProjectSummary{ public function __construct( public int $id, public string $name, public int $taskCount, ) {}}
class ProjectController{ public function summary(Project $project) { return new ProjectSummary( $project->id, $project->name, $project->tasks()->count(), ); }}Documented component schema:
{ "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "taskCount": { "type": "integer" } }, "required": ["id", "name", "taskCount"]}Protected and private properties are ignored.
jsonSerialize() objects
When a class has jsonSerialize(), Scramble follows that method and documents its return type:
class HealthStatus{ public function __construct( private string $status, private float $uptime, ) {}
public function jsonSerialize(): array { return [ 'status' => $this->status, 'uptime' => $this->uptime, ]; }}Schema comes from the inferred return type of jsonSerialize(), not from the private properties.
Property annotations
All supported PHPDoc annotations and attributes can be used on plain-object properties, just as they can elsewhere.
use Dedoc\Scramble\Attributes\Hidden;
class UserProfile{ /** The user display name. */ public string $name;
public string $email;
#[Hidden] public string $internalId;}name gets its description. internalId is omitted. email is included.
See plain PHP objects for the full response-schema behavior.
Type inference improvements
A significant portion of these releases went into making Scramble smarter at inferring types from your code.
Union types, nullsafe, and coalesce
v0.13.23 added support for method calls and property access on union types, plus improved null coalescing (??) inference. Real-time Facades are supported (#1146).
v0.13.24 extended inference to the __() translation helper, standard Facades, and array destructuring (#1167, #1172).
v0.13.31 added full nullsafe operator (?->) support and fixes for coalesce on property fetch (#1203, #1204).
Model helpers
Scramble also understands newCollection on Eloquent models, and except/only on both models and Arr helpers (#1193) — if you shape response data with these methods, the documented schema reflects the actual output.
Request documentation improvements
#[IgnoreParam] attribute
Sometimes a query parameter is useful to the application but shouldn’t appear in the API docs:
use Dedoc\Scramble\Attributes\IgnoreParam;use Illuminate\Http\Request;
class ProjectController{ #[IgnoreParam('debug')] public function index(Request $request) { $request->validate([ 'search' => ['nullable', 'string'], 'debug' => ['boolean'], ]); }}Only search appears in the documented query parameters (#1176).
See ignoring parameters for PHPDoc and attribute-based options.
New validation rules
Several validation rules gained documentation support:
acceptedrule (#1129)- Laravel’s fluent
Filevalidation rule (#1185) - Improved nullable enum rule handling (#1195)
Rule::enum()->only() and ->except() now preserve enum case names and descriptions in the documented schema (v0.13.33, #1208).
File size constraints are documented correctly: min, max, size, and between on file fields produce kilobyte size descriptions instead of incorrectly emitting minLength / maxLength on binary fields (v0.13.34, #1212).
Nested request body parameters also keep the same order as your validation rules after merging — name, status, and type stay in that order even when status.* rules are folded in (#1213).
Response and pagination improvements
#[IgnoreResponse] attribute
Sometimes a redirect is part of an endpoint’s implementation but doesn’t belong in its published API docs.
v0.13.34 adds #[IgnoreResponse]:
use Dedoc\Scramble\Attributes\IgnoreResponse;
class LoginController{ #[IgnoreResponse(302)] public function store(LoginRequest $request) { return response()->redirect('/dashboard'); }}See #1210 for details.
See ignoring inferred responses for response status matching options.
Scout pagination is now documented correctly (#1190).
v0.13.32 improves how @example annotations serialize into JSON Schema — multiple @example values are supported, and the output uses the examples keyword instead of the deprecated example field (#1205). Laravel 10.x paginator compatibility was also improved.
Other notable changes
- Improved performance for projects with many inline types (#1163)
- More reliable paginator and JSON API resource documentation (#1193, #1194)
- PHP 8.5 compatibility improvements that prevent deprecation noise during documentation generation (#1155, #1196)
- New contributors: @jcsoriano, @WendellAdriel, @dabrandstetter, @squiaios, @sanfair
Full changelog: https://scramble.dedoc.co/releases
Thanks!
Give Scramble 0.13.34 a try and let me know what you think. If you have questions, ideas, or suggestions, feel free to drop me a line at roman@dedoc.co.
