Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Api Docs Laravel Package

dedoc/laravel-api-docs

Generate OpenAPI documentation directly from your Laravel routes and code with a built-in UI for browsing endpoints. Keeps API docs in sync and reduces manual spec maintenance.

View on GitHub
Deep Wiki
Context7

Getting Started

Scramble generates OpenAPI documentation from your existing Laravel code — validation rules, form requests, API Resources, return types, and route definitions — so there is nothing to annotate to get a first draft.

Minimal setup:

composer require dedoc/scramble
php artisan vendor:publish --provider="Dedoc\Scramble\ScrambleServiceProvider"

Then visit /docs/api for the UI and /docs/api.json for the raw OpenAPI document. Restrict access before shipping:

// config/scramble.php
'middleware' => ['web', 'auth'],

Where to look first, in order:

  1. config/scramble.php — document info, servers, security schemes, export targets.
  2. Scramble::configure() in a service provider — the fluent extension API (document transformers, route grouping, withTags()).
  3. Your existing FormRequest classes and JsonResource classes — these are the primary source of truth for request/response schemas. If your docs look empty, it is almost always because the controller action does not typehint a FormRequest or return a typed Resource.

First use case: point Scramble at a single route group, confirm inference works on one well-typed controller (FormRequest in, PostResource::collection() out), then widen coverage. Do not start by annotating — start by fixing return types and request classes, and let inference do the work.

Implementation Patterns

Infer from the type system, annotate only as a fallback. Scramble reads the method signature. The highest-leverage refactor is making controllers honest:

public function store(StorePostRequest $request): PostResource
{
    return new PostResource(Post::create($request->validated()));
}

StorePostRequest supplies the request body schema from rules(), PostResource::toArray() supplies the response schema. @response / @body PHPDoc annotations exist for cases where this isn't feasible, but they drift.

Group and tag centrally with withTags() (new in v0.13.48). Rather than sprinkling @tags across dozens of controllers, declare tag hierarchy once and let routes inherit:

Scramble::configure()
    ->withTags([
        'Posts' => 'Blog content management',
        'Posts.Comments' => 'Nested comment threads',
    ]);

In OpenAPI 3.2 these map to the Tag Object's hierarchical fields; in 3.1 they are flattened to names + descriptions. Centralising tags pays off immediately in the docs UI ordering.

Version the document explicitly. Set info.version in config and treat it as a real release artefact — clients generate SDKs from it. Pair it with php artisan scramble:export in CI so the OpenAPI JSON is a reviewed, diffed file rather than a runtime-only endpoint:

'exports' => [
    'openapi' => storage_path('api/openapi.json'),
    // 'postman' => storage_path('api/postman.json'),
],

Run the export in a pipeline step and fail the build if the diff is unexpected — this catches accidental public-API changes the same way schema-migration checks catch DB drift.

Reuse security schemes. Declare sanctum / bearer once under security in config and apply it via middleware-aware route grouping, rather than annotating each endpoint. Scramble respects actual route middleware, so keep authorization in middleware and let it be inferred.

Customise the document at the edges with transformers. For things inference can't know (servers per environment, vendor extensions, examples), use document transformers in Scramble::configure() rather than editing generated output. Keep transformers tiny and single-purpose.

Let redirect responses document themselves (improved in v0.13.49). Controllers that return redirect()->route(...), redirect()->to(...), or an explicit RedirectResponse now produce documented responses with the correct status code (302/303/307/308 as applicable) instead of an opaque or missing response. If you maintain auth flows, OAuth callbacks, or legacy form-post endpoints that redirect, check the generated document before hand-writing @response annotations — the inference is now reliable enough to delete those annotations and stop maintaining them.

Exclude rather than hide. Internal/admin routes should be excluded at the route level (config api_path or explicit route filtering) so they never enter the document. Relying on @hide annotations leaves them one typo away from being published.

Gotchas and Tips

The v0.13.48 breaking change is real but narrow — and still the main thing to audit. Serialisation of OpenAPI objects in the Generator namespace no longer calls toArray(); it calls serializeAs31() (and the 3.2 equivalent). toArray is retained for backward compatibility but is dead code at serialisation time. If you extended a Generator object and overrode toArray() to inject fields, examples, or fix a version string, your change has silently stopped applying. Audit for extends on Generator classes and move logic to serializeAs31 — or, preferably, to a document transformer so you are not pinned to internal method names.

OpenAPI 3.2 is opt-in, and default output changed too. 3.1 is still the default, but the emitted version is now 3.1.2 (3.2 emits 3.2.1). Tools that pin on an exact version string, or snapshot tests asserting "openapi": "3.1.0", will break. If you have downstream codegen, verify the 3.2 flag against your generator before flipping it — hierarchical tags and the newer schema keywords are not universally supported yet.

Hierarchical tags depend on the spec version. Declaring Posts.Comments style nesting is only fully expressed under 3.2; on 3.1 you get flat names. Don't design a tag taxonomy that only makes sense in 3.2 unless you've opted in.

Self-returning Responsable is no longer an infinite loop (fixed in v0.13.49). A Responsable whose toResponse() returns itself — usually a mis-wired response object or a decorator that forgot to unwrap — previously sent Scramble into infinite recursion, hanging docs generation. It is now handled gracefully. Practical takeaway: docs generation hanging or blowing the stack on a single route is now a genuinely rare failure mode, so if you still see it, suspect a Macroable/Jsonable wrapper or a transformer that rebuilds the same node rather than the Responsable path. It also means you can safely point Scramble at a broader route list without pre-auditing response classes — useful when widening coverage incrementally.

Redirect endpoints have no body schema by design. Now that redirects are documented, generated clients will see a response with a status code and headers but no content schema. If your SDK generator insists every 3xx has an object schema, configure the generator, not Scramble — don't annotate a fake @response body onto a redirect just to silence codegen.

Inference failures are now quieter. v0.13.48 silences form-evaluation diagnostics when node evaluation succeeds. Net effect: fewer spurious errors, but also fewer breadcrumbs when a schema comes out as a bare {} or object. When a request body looks empty, debug bottom-up: does the controller typehint a FormRequest? Does rules() return anything for that field? Is the field conditional (sometimes, exclude_if) in a way that yields no static schema? Temporarily lowering the log level or dumping the generated JSON is faster than guessing.

Array rules no longer require listed keys. Previously, 'items.*.id' => 'required' implied the key id was mandatory in the object schema; now it isn't. If you relied on that implication to mark properties as required, your generated schemas may be more permissive than intended. Add explicit required-ness at the parent level or annotate.

Validation rules are a documentation language — write them that way. integer|min:1 documents as an integer with a minimum; string alone documents as a bare string. Vague rules produce vague docs. Also watch inference on Rule::in, enums (backed enums document well), and nullable — these are the common sources of "the schema doesn't match reality."

Route model binding and implicit types. Scramble infers path parameters from route parameters; if you change {post} to {post_id} the parameter name in the document changes, breaking generated clients. Treat route parameter names as part of your public API contract.

Don't serve the document unauthenticated. api_path defaults to something predictable and is registered outside your api middleware group in many setups. Confirm both the UI route and the .json route are behind the right middleware in production — this is the single most common Scramble misconfiguration.

Docs endpoints can be slow on large apps. Scramble analyses routes and reflection on every request. v0.13.48 includes another round of self-out performance work, but for anything sizeable, cache the export and serve the static file in production instead of generating per request.

Extension points to prefer, in order of stability: document transformers → config values → PHPDoc annotations → subclassing Generator objects. The v0.13.48 change is a good reminder that the bottom of that list is internal API, not public API.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core