OpenAPI

"org.julienrf" %% "endpoints-openapi" % "0.15.0"

API documentation

This family of interpreters produces static documentation for endpoint definitions, in the form of an OpenAPI document.

Endpoints

The Endpoints interpreter provides an openApi method that takes as parameter a sequence of endpoints for which to generate an OpenAPI document.

Given the following endpoint definition:

import endpoints.algebra

trait DocumentedEndpoints extends algebra.Endpoints {

  val someDocumentedResource: Endpoint[Int, String] =
    endpoint(
      get(path / "some-resource" / segment[Int]("id")),
      ok(textResponse, docs = Some("The content of the resource"))
    )

}

It can be documented as follows:

import endpoints.openapi
import endpoints.openapi.model.{Info, OpenApi}

object EndpointsDocs extends DocumentedEndpoints with openapi.Endpoints {

  val api: OpenApi =
    openApi(Info(title = "API to get some resource", version = "1.0"))(
      someDocumentedResource
    )

}

The value returned by the openApi method has type endpoints.openapi.models.OpenApi, which is an abstract model for OpenAPI documents. You can encode it into JSON by using the OpenApi.stringEncoder encoder.

val apiJson: String = OpenApi.stringEncoder.encode(api)

In case the endpoint that serves the documentation is itself defined using endpoints, you can use the JsonEntitiesFromEncoderAndDecoder interpreter to define an endpoint returning the OpenApi document as a JSON entity. Here is an example using Akka HTTP:

import endpoints.openapi.model.OpenApi
import endpoints.akkahttp.server

object DocumentationServer
    extends server.Endpoints
    with server.JsonEntitiesFromEncodersAndDecoders {

  val routes =
    endpoint(get(path / "documentation.json"), ok(jsonResponse[OpenApi]))
      .implementedBy(_ => CounterDocumentation.api)

}

Finally, the apiJson value contains the following JSON document:

{
  "openapi" : "3.0.0",
  "info" : {
    "title" : "API to get some resource",
    "version" : "1.0"
  },
  "paths" : {
    "/some-resource/{id}" : {
      "get" : {
        "parameters" : [
          {
            "name" : "id",
            "in" : "path",
            "schema" : {
              "type" : "integer"
            },
            "required" : true
          }
        ],
        "responses" : {
          "200" : {
            "description" : "The content of the resource",
            "content" : {
              "text/plain" : {
                "schema" : {
                  "type" : "string"
                }
              }
            }
          }
        }
      }
    }
  }
}

JSON entities

To properly document the underlying JSON schema of your JSON entities, you have to define these schemas by using the JsonEntitiesFromSchemas algebra (and its corresponding interpreter).