Frameworks

Generate an SDK from Laravel with l5-swagger or Scribe

Laravel has no built-in OpenAPI output, and unlike some frameworks there isn't one obvious default package — you pick between two different approaches. l5-swagger wraps swagger-php and reads annotations you add to your controllers. Scribe instead extracts documentation from your actual code — FormRequests, validation rules, and real sample responses — and can export the same OpenAPI spec without annotations. Either way, a Laravel OpenAPI SDK is the same two-step problem as any other framework: get a clean spec out, then run it through a generator or a hosted pipeline like Sourced.

Option 1: l5-swagger (annotation-driven)

l5-swagger is a Laravel-friendly wrapper around zircote/swagger-php and swagger-ui. You annotate your controllers with OpenAPI attributes, and it compiles them into a spec.

Step Command / file What it does
1. Install composer require darkaonline/l5-swagger Adds the package
2. Publish config php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider" Creates config/l5-swagger.php
3. Annotate #[OA\Get(path: '/api/users', ...)]-style attributes on controller methods Describes each operation directly in code
4. Generate php artisan l5-swagger:generate Compiles annotations into an OpenAPI JSON file
5. View Visit /api/documentation Serves the generated spec through an embedded Swagger UI

Set L5_SWAGGER_GENERATE_ALWAYS=true in .env during development to regenerate on every request instead of running the artisan command manually — turn it off again before production, since it costs a full annotation scan per request.

Option 2: Scribe (extraction-driven)

Scribe takes the opposite approach: no annotations required by default. It reads your FormRequest classes and validation rules for parameters, and can safely call your API endpoints to capture real sample responses.

composer require knuckleswtf/scribe
php artisan vendor:publish --tag=scribe-config
php artisan scribe:generate

Where the output lands depends on your configured type: a static config writes a browsable docs/index.html into public/, while a laravel config serves the docs at /docs and writes the OpenAPI spec (and a Postman collection) into storage/app/scribe/. Scribe can emit either OpenAPI 3.0.3 or 3.1.0 — the spec version is a config setting, not fixed.

Pick l5-swagger if you want full manual control over every field in the spec and don't mind annotating. Pick Scribe if you'd rather derive documentation from code you're already writing — FormRequests and validation rules — with less annotation overhead.

The gotcha: annotation-driven specs are only as complete as your annotations

l5-swagger doesn't infer anything you haven't written an attribute for — an endpoint with no #[OA\...] annotation simply doesn't appear in the generated spec, and a response schema you didn't annotate explicitly has nothing backing it. A common failure mode: annotating the request body but leaving a response schema loosely typed or omitted, which generators then fill in with an anonymous, auto-named schema — the same pattern covered in fixing inline schema names like Type1 and InlineObject. Reference a named schema class in components/schemas for every response you annotate, rather than inlining the shape at the annotation site.

From a Laravel spec to hosted docs and typed SDKs

Once your l5-swagger or Scribe output has real, referenced schemas for every operation, turning it into an installable SDK is a separate step. With Sourced:

  1. Point Sourced at your repo or the generated file. Connect from GitHub, or upload the openapi.json/openapi.yaml that l5-swagger or Scribe wrote directly.
  2. Preview the TypeScript and Python SDKs. Sourced renders both before anything publishes, so an anonymous inline schema shows up in the preview, not a customer's autocomplete.
  3. Get hosted docs and an llms.txt from the same spec. No separate docs deploy — the hosted docs preview and llms.txt come from the same pass as the SDKs.
  4. Publish on your schedule. Free unlimited previews and up to 2 hosted noindex docs review sites and one hosted MCP server, no credit card, cover steps 1-3.

Comparison: l5-swagger vs. Scribe vs. a full SDK pipeline

Need l5-swagger Scribe What neither gives you
A generated OpenAPI spec Yes, from annotations Yes, from code introspection Nothing — both do this for free
Setup effort Annotate every controller method Mostly automatic from FormRequests
Interactive API browsing Swagger UI at /api/documentation Static or Laravel-served docs at /docs A hosted docs site for external customers
A typed client SDK Nothing built in Nothing built in Generated TypeScript or Python SDK
A diff before a breaking release Nothing built in Nothing built in A compatibility report
Agent-readable docs Nothing built in Nothing built in llms.txt derived from the spec

OSS generators for other languages

Sourced's generated SDKs focus on TypeScript and Python today — the two ecosystems where teams publish first, not PHP. For the SDK itself, a clean l5-swagger or Scribe spec works with the standard per-language OpenAPI Generator ecosystem — PHP itself (via OpenAPI Generator or Jane for Symfony-style output), Go, Java, Ruby, C#, Kotlin, Rust, and Swift all have their own walkthroughs. Sourced still has a role on that same spec: hosted docs, llms.txt, and validation. The five-minute generate-an-SDK guide covers running a local generator against any spec.

Other backend frameworks with their own spec-extraction paths: FastAPI, NestJS, Express, Django, Rails, Spring Boot, and .NET.

Honest scope: when l5-swagger or Scribe alone is enough

If your Laravel API only serves your own Blade frontend or a mobile app your team also owns, the Swagger UI or Scribe docs page is often enough reference documentation on its own — you don't need a codegen pipeline for a client you control end to end. Scribe in particular is worth using even if you never generate an SDK from its output, since the human-readable docs (with live "Try It Out" requests) are valuable independent of OpenAPI export. Reach for full SDK generation once you have external customers, a second language to support, or a docs site that needs to outlive whichever package generated it.

FAQ

Does Laravel generate OpenAPI automatically?

No. Laravel has no built-in OpenAPI output. You need a package — l5-swagger (annotation-driven, wraps swagger-php) or Scribe (extracts from FormRequests, validation rules, and live sample responses) are the two standard choices.

What's the artisan command to generate docs with l5-swagger?

php artisan l5-swagger:generate. It compiles the OpenAPI attributes on your controllers into a spec, served at /api/documentation by default. Set L5_SWAGGER_GENERATE_ALWAYS=true in development to skip running it manually after every change.

Does Scribe require annotations like l5-swagger?

No — that's the main difference. Scribe extracts parameter details from FormRequests and validation rules, and can call your endpoints directly to capture real sample responses, with annotations only needed to fill gaps it can't infer.

Does Scribe export OpenAPI, or just its own docs format?

Both. Scribe's own feature list confirms it generates a Postman collection and an OpenAPI spec (v3.0.3 or v3.1.0, configurable) alongside its human-readable docs page.

Where does the generated OpenAPI file end up with Scribe?

With a laravel-type config, in storage/app/scribe/ alongside the Postman collection, and the docs page itself is served at /docs. A static-type config writes a browsable docs/index.html into public/ instead.

Which should I use, l5-swagger or Scribe?

l5-swagger if you want precise, manually authored control over every field in the spec via annotations. Scribe if you'd rather derive documentation from code you're already writing, with less ongoing annotation maintenance. Both produce an OpenAPI file a generator or hosted pipeline can read.

Ship it

Once l5-swagger or Scribe produces a spec with real, referenced schemas, you have a real Laravel OpenAPI SDK source to work with. Start free on Sourced to preview a TypeScript and Python SDK plus hosted docs from that spec in one pass, or run it through the OpenAPI validator first to catch schema gaps before you generate anything.