When documenting the endpoints of your API, you can mentally split the task into documenting the request part (authentication, request body, request parameters) and documenting the response part. In this guide, we'll do a deep dive into request documentation.
Automatically generated request parameters and body
The main goal of Scramble is to generate as much API documentation as possible without requiring you to write any annotations manually. Writing a PHPDoc with all parameters and the request body is a tedious task and an error-prone approach. If some detail about the request changes, you need to update the PHPDoc. Sooner or later, a correction will be missed, and the API documentation will become outdated.
If you think about it, there is already a ton of information about API requests within the codebase! Validation rules, route path parameters, and method calls on $request
— all of this data describes the requests of API endpoints.
Scramble uses this information to automatically generate a basic request documentation that describes the data types that can be sent to the API.
When model binding is used, Scramble documents path parameters according to the model key type. As expected, integer keys are documented as integers, and
uuid
keys are documented as strings with the uuid
format:
Add descriptions and examples to parameters
On top of Scramble-generated request structure and parameters, you can add descriptions, examples, and defaults. You can also add other parameters in case Scramble misses something or change a parameter type.
The easiest way to do that is to use attributes:
#[BodyParameter('name', 'The name of the company')]public function store(Request $request){ $request->validate([ 'name' => ['required', 'string'], ]); ...}
You can also add descriptions to parameters using PHPDoc comments on the rules.
public function store(Request $request){ $request->validate([ // The name of the company. 'name' => ['required', 'string'], ]); ...}
Add parameters to a single endpoint manually
Using the source code for request API documentation, Scramble will cover most cases. However, it doesn't automatically document request headers or cookies.
You can do that using attributes. For example, let's say you retrieve a header value in your controller like so:
$request->header('X-Header-Name');
This can be documented using the #[HeaderParameter]
attribute:
#[HeaderParameter('X-Header-Name', 'The name of the header.', type: 'string')]
If you'd like to document cookies, you can use the #[CookieParameter]
attribute.
$value = $request->cookie('name');
Document it like so:
#[CookieParameter('name', 'The cookie.', type: 'string')]
Using #[PathParameter]
, #[QueryParameter]
, and #[BodyParameter]
, you can also document the corresponding parameters of a request.
To document query parameters sent to the API in a query string, like /api/books?page=1
, use the #[QueryParameter]
attribute:
#[QueryParameter('page', 'The page number.', type: 'int')]
Using #[PathParameter]
, you can document path parameters that are part of the route. For example, there is a book
path parameter in the route GET /api/book/{book}
.
#[PathParameter('book', 'The book to show')]
If you need to add a request body parameter, use the #[BodyParameter]
attribute.
#[BodyParameter('project_id', type: 'int')
You can even use dots like you would in validation rules to create deep structures:
#[BodyParameter('projects.*.id', 'The ID of the project', type: 'int')]#[BodyParameter('projects.*.name', 'The name of the project', type: 'string')]
By default, attributes "attach" information to parameters inferred automatically from the codebase. To ignore automatically inferred parameter information, pass infer: false
to the attribute. This will keep only manually provided parameter information:
#[QueryParameter('page', 'The page number.', type: 'int', infer: false)]
Add parameters documentation to multiple endpoints
Often, headers and cookies are retrieved in middleware, making them applicable to all endpoints. Scramble gives you full control over the resulting OpenAPI document using transformers.
Operation transformers allow you to add additional documentation information to all endpoints. You can also inspect the middleware and apply the documentation if a specific middleware exists on a route.
Consider this example. We have a global middleware that logs the request ID taken from the headers. This middleware runs whenever any API route is hit, so we want to document it for all routes.
<?php namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class LogRequestId{ public function handle(Request $request, Closure $next): Response { if ($id = $request->header('X-Request-ID')) { info("Request ID: $id (url: {$request->url()}"); } return $next($request); }}
Now, we can add this header to all routes using an operation transformer in the boot
method of a service provider:
public function boot(): void{ Scramble::configure() ->withOperationTransformers(function (Operation $operation) { $operation->parameters[] = (new Parameter('X-Request-ID', 'header')) ->description('The ID of the request for better request visibility.') ->setSchema(Schema::fromType(new StringType)); });}
And now, the X-Request-ID
header is added to all API routes.
Add endpoint's title and description
To provide more context for an endpoint, you can add a title and description to its documentation. This can be done simply by adding a PHPDoc comment. The first line is treated as the endpoint title, while the lines after that are treated as the description. You can use CommonMark Markdown formatting for the description.
Document authentication
If your API requires authentication, you can document it using a document transformer and specifying the default authentication mechanism of your API.
Document transformers are defined in the boot
method of a service provider:
public function boot(){ Scramble::configure() ->withDocumentTransformers(function (OpenApi $openApi) { $openApi->secure( SecurityScheme::http('bearer') ); });}
If an endpoint is public (for example, user registration), you can mark that endpoint as not requiring authentication:
/** * @unauthenticated */public function store(Request $request){ ...}
By using operation transformers, you can even inspect the middleware on a route and automatically remove the authentication requirement for endpoints that do not have the auth
middleware:
public function boot(){ Scramble::configure() ->withOperationTransformers(function (Operation $operation, RouteInfo $routeInfo) { $routeMiddleware = $routeInfo->route->gatherMiddleware(); $hasAuthMiddleware = collect($routeMiddleware)->contains( fn ($m) => Str::startsWith($m, 'auth:') ); if (! $hasAuthMiddleware) { $operation->security = []; } })}
Group endpoints and sort groups
To group endpoints, you can use the #[Group]
attribute on a controller (which will group all endpoints of that controller) and on a controller's method.
#[Group('Companies API')]class CompaniesController {...}
You can sort the groups by providing a weight
argument to the #[Group]
attribute:
#[Group('Domains API', weight: 2)]class DomainsController {...}
Conclusion
Using Scramble, you can generate up-to-date API documentation based on your source code. This saves time and ensures that your API documentation remains accurate. Additionally, you can enhance the documentation by adding parameter descriptions, titles, examples, and default values, allowing you to document all the details of your API.
Give Scramble a try if you haven't already: https://scramble.dedoc.co
Also, check out the demo documentation generated by Scramble: https://scramble.dedoc.co/demo/scramble. You will find “Go to GitHub” links in the documentation, allowing you to quickly jump to the source code from which each documentation piece was generated.

Working on https://scramble.dedoc.co – Modern Laravel OpenAPI (Swagger) documentation generator.