Turn your HTTP tests into OpenAPI, HTML docs, Postman collections, and typed TypeScript or Scala clients, for APIs you serve or consume.
Baklava is a Scala library that turns your HTTP tests — for routes you serve or third-party APIs you consume — into API documentation. Instead of maintaining docs separately, your tests become the single source of truth.
| Options | |
|---|---|
| HTTP Integration | Pekko HTTP, http4s (routes you serve), sttp (remote APIs you consume) |
| Test Frameworks | ScalaTest, Specs2, MUnit |
| Output Formats | OpenAPI (+ SwaggerUI), Simple HTML, TS-REST, oRPC, ts-fetch, sttp-client, Postman |
| Scala | 2.13, 3 (LTS) |
| JDK | 11+ |
1. Add the SBT plugin to project/plugins.sbt:
addSbtPlugin("pl.iterators" % "baklava-sbt-plugin" % "2.3.0")2. Enable the plugin in build.sbt:
enablePlugins(BaklavaSbtPlugin)3. Add dependencies (pick one from each group):
libraryDependencies ++= Seq(
// HTTP integration — choose one
"pl.iterators" %% "baklava-pekko-http" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-http4s" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-sttp" % "2.3.0" % Test, // for remote APIs you consume
// Test framework — choose one
"pl.iterators" %% "baklava-scalatest" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-specs2" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-munit" % "2.3.0" % Test,
// Output format — one or more
"pl.iterators" %% "baklava-openapi" % "2.3.0" % Test,
"pl.iterators" %% "baklava-simple" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-tsrest" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-orpc" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-tsfetch" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-postman" % "2.3.0" % Test,
// "pl.iterators" %% "baklava-sttpclient" % "2.3.0" % Test,
)4. Configure in build.sbt:
inConfig(Test)(
BaklavaSbtPlugin.settings(Test) ++ Seq(
fork := false,
baklavaGenerateConfigs := Map(
"openapi-info" ->
s"""
|openapi: 3.0.1
|info:
| title: My API
| version: 1.0.0
|""".stripMargin
)
)
)5. Write a test:
class UserSpec extends AnyFunSpec
with BaklavaPekkoHttp[Unit, Unit, ScalatestAsExecution]
with BaklavaScalatest[Route, ToEntityMarshaller, FromEntityUnmarshaller] {
// ... setup ...
path("/users/{userId}")(
supports(
GET,
pathParameters = p[Long]("userId"),
summary = "Get user by ID",
tags = Seq("Users")
)(
onRequest(pathParameters = 1L)
.respondsWith[User](OK, description = "User found")
.assert { ctx =>
val response = ctx.performRequest(routes)
response.body.name shouldBe "Alice"
},
onRequest(pathParameters = 999L)
.respondsWith[ErrorResponse](NotFound, description = "User not found")
.assert { ctx =>
ctx.performRequest(routes)
}
)
)
}6. Run tests and documentation is generated automatically:
sbt test
# Output in target/baklava/openapi/openapi.yml, target/baklava/simple/, etc.Tip
Incremental runs are fine. Captured calls are kept in a persistent store under target/baklava/store/, one directory per test suite. Every run replaces the entries of the suites that captured at least one call and keeps the rest, then regenerates the documentation from the whole store. Plain sbt test therefore produces complete documentation even on sbt 2, whose test is incremental and may run only some suites, or none. The store cannot help when sbt 2 skips a suite that has no entry in it: on a checkout without target/ on a machine whose sbt cache already holds the results (a second clone, or CI restoring ~/.cache/sbt but not target/), after baklavaClean (or clean on sbt 1, which deletes target/), or when a suite that had been removed comes back unchanged, for example after switching branches, because sbt 2 caches test results by content. Run sbt testFull once in that case, and prefer testFull over test in CI on sbt 2. Baklava prints a message when the store is empty.
Prefer to see it working first? A single scala-cli script can test the live GitHub REST API and generate an OpenAPI spec plus a typed sttp client from verified responses — no sbt project needed:
scala-cli test github-api-docs.test.scalaGrab the script from Standalone Scripts with scala-cli.
OpenAPI generates a standard openapi.yml spec. Optionally serve it via SwaggerUI with baklava-pekko-http-routes or baklava-http4s-routes.
Simple HTML generates self-contained, browsable HTML pages with no external dependencies.
TS-REST generates a TypeScript npm package with ts-rest contracts and Zod schemas for type-safe frontend API clients.
oRPC generates a TypeScript npm package with oRPC contracts (@orpc/contract + Zod), consumable from any frontend via OpenAPILink with first-class TanStack Query support.
ts-fetch generates a plain-TypeScript npm package with a typed fetch-based function per endpoint and no runtime dependencies.
sttp-client generates Scala source files with typed sttp-client4 request builders, usable with any sttp backend.
Postman generates a Postman Collection v2.1 JSON file that imports directly into Postman or Insomnia, with example values and auth blocks filled in.
All formatters are auto-discovered from the classpath. Just add the dependency and it works.
Full documentation is available at theiterators.github.io/baklava.
- Installation
- Pekko HTTP Integration
- http4s Integration
- Remote APIs (sttp)
- DSL Reference
- Examples
- Standalone Scripts (scala-cli)
- Output Formats
- Configuration
Apache 2.0 - see LICENSE for details.
Maintained by Iterators.
