Skip to main content


Scribe allows you to modify its behaviour in many ways. SOme ways are very obvious, like in the config file and via annotations (see the pages in the Documenting your API category in the sidebar). Others are more involved, like writing custom strategies and customising the views (the pages under Advanced Customization).

However, a useful in-between is hooks. Hooks are a way for you to run a task before or after Scribe does something. You can achieve some of that in other ways, but hooks provide a convenient point in the context of your app and allow you to harness the full power of Laravel.

Scribe currently provides two hooks:

  • beforeResponseCall() (from v3.11.0)
  • afterGenerating() (from v3.13.0)

To define a hook, you'll simply call these methods and pass in a callback where you do whatever. Typically, you'd do this in the boot() method of your AppServiceProvider.


Always wrap these method calls in an if (class_exists(\Knuckles\Scribe\Scribe::class)) statement. That way, you can push this code to production safely, even if Scribe is installed in dev only.


beforeResponseCall() allows you to run some code before a response call is dispatched. You can use this to fix authentication, add parameters, or whatever you wish,

The callback you provide will be passed the current Symfony\Component\HttpFoundation\Request instance and the details of the current endpoint being extracted. If you have database transactions configured, they will already be activated at that point, allowing you to modify your database freely, and have your changes rolled back after the request.

use Knuckles\Camel\Extraction\ExtractedEndpointData;
use Symfony\Component\HttpFoundation\Request;
use Knuckles\Scribe\Scribe;
public function boot()
if (class_exists(\Knuckles\Scribe\Scribe::class)) {
Scribe::beforeResponseCall(function (Request $request, ExtractedEndpointData $endpointData) {
// Customise the request however you want (e.g. custom authentication)
$token = User::first()->api_token;
$request->headers->add(["Authorization" => "Bearer $token"]);


afterGenerating() allows you to run some code after Scribe is done generating your docs; for instance, upload your generated docs to AWS S3, change some of the content, etc. You could do the same with a shell script, but by using afterGenerating(), you get to stay in PHP land, complete with all Laravel's goodness.

The callback you provide will be passed a map of the output paths generated.

use Knuckles\Scribe\Scribe;
public function boot()
if (class_exists(\Knuckles\Scribe\Scribe::class)) {
Scribe::afterGenerating(function (array $paths) {
// Move the files, upload to S3, etc...
rename($paths['postman'], "some/where/else");
Storage::disk('s3')->put('collection.json', file_get_contents($paths['postman']));

Here's an example of the $paths array passed to the callback.

"postman" => "C:\Users\shalvah\Projects\TheSideProjectAPI\punlic\docs\collection.json"
"openapi" => "C:\Users\shalvah\Projects\TheSideProjectAPI\punlic\docs\openapi.yaml"
"html" => "C:\Users\shalvah\Projects\TheSideProjectAPI\docs\index.html"
"blade" => null
"assets" => [
"js" => "C:\Users\shalvah\Projects\TheSideProjectAPI\docs\css"
"css" => "C:\Users\shalvah\Projects\TheSideProjectAPI\docs\js"
"images" => "C:\Users\shalvah\Projects\TheSideProjectAPI\docs\images"


  • The paths in "js", "css", and "images" paths point to the respective folders. All other paths point to specific files.
  • If you're using laravel type, "html" will be null, and "blade" will contain the index.blade.php path.
  • If you're using static type, "blade" will be null, and "html" will contain the index.html path.
  • If you disabled Postman and/or OpenAPI generation, those paths will be null.
  • Paths are generated using PHP's realpath(), so they'll use the appropriate directory separator for your platform (backslash on Windows, forwards slash on *nix).