{"id":13682788,"url":"https://github.com/softwaremill/tapir","last_synced_at":"2025-05-13T20:09:28.614Z","repository":{"id":37406109,"uuid":"161060132","full_name":"softwaremill/tapir","owner":"softwaremill","description":"Rapid development of self-documenting APIs","archived":false,"fork":false,"pushed_at":"2025-05-12T10:07:38.000Z","size":20456,"stargazers_count":1406,"open_issues_count":176,"forks_count":437,"subscribers_count":42,"default_branch":"master","last_synced_at":"2025-05-12T11:26:17.491Z","etag":null,"topics":["akka","akka-http","declarative","documentation","functional-programming","http","http-client","http-requests","http-server","http4s","observability","openapi","play-framework","scala","sttp","type-safe","zio"],"latest_commit_sha":null,"homepage":"https://tapir.softwaremill.com","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softwaremill.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-12-09T16:43:49.000Z","updated_at":"2025-05-12T10:07:42.000Z","dependencies_parsed_at":"2023-10-02T12:07:11.213Z","dependency_job_id":"caef9107-ee1a-463c-8db0-1622a4d07388","html_url":"https://github.com/softwaremill/tapir","commit_stats":{"total_commits":6780,"total_committers":330,"mean_commits":"20.545454545454547","dds":0.6451327433628319,"last_synced_commit":"b9d34320266be62c47445a12f8e6f70a7bb1cd81"},"previous_names":[],"tags_count":326,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Ftapir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Ftapir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Ftapir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Ftapir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softwaremill","download_url":"https://codeload.github.com/softwaremill/tapir/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254020605,"owners_count":22000752,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["akka","akka-http","declarative","documentation","functional-programming","http","http-client","http-requests","http-server","http4s","observability","openapi","play-framework","scala","sttp","type-safe","zio"],"created_at":"2024-08-02T13:01:53.191Z","updated_at":"2025-05-13T20:09:28.608Z","avatar_url":"https://github.com/softwaremill.png","language":"Scala","readme":"![tapir](https://github.com/softwaremill/tapir/raw/master/banner.png)\n\n# Welcome!\n\n[![Ideas, suggestions, problems, questions](https://img.shields.io/badge/Discourse-ask%20question-blue)](https://softwaremill.community/c/tapir)\n[![CI](https://github.com/softwaremill/tapir/workflows/CI/badge.svg)](https://github.com/softwaremill/tapir/actions?query=workflow%3A%22CI%22)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.softwaremill.sttp.tapir/tapir-core_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.softwaremill.sttp.tapir/tapir-core_2.13)\n\n## Intro\n\nTapir is a library to describe HTTP APIs, expose them as a server, consume as a client, and automatically document\nusing open standards.\n\nTapir is fast and developer-friendly. The endpoint definition APIs are crafted with readability and discoverability in\nmind. Our Netty-based server is one of the best-performing Scala HTTP servers available.\n\n```scala\nendpoint\n  .get.in(\"hello\").in(query[String](\"name\"))\n  .out(stringBody)\n  .handleSuccess(name =\u003e s\"Hello, $name!\")\n```\n\nTapir integrates with all major Scala stacks, so you can use your favorite approach to Functional Programming, while\nleveraging all the benefits that Tapir brings!\n\nSeamless integration with the Scala and HTTP ecosystems is one of Tapir's major strengths:\n\n* all popular Scala HTTP server implementations are supported. You can define your entire API using Tapir, or expose\n  Tapir-managed routes alongside \"native\" ones. This is especially useful when gradually adopting Tapir, or using it for\n  selected use-cases.\n* the Scala ecosystem is rich with libraries leveraging its type-safety and enhancing the developer's toolbox,\n  that's why Tapir provides integrations with many of such custom type, JSON and observability libraries\n* documentation can be generated in the [OpenAPI](https://tapir.softwaremill.com/en/latest/docs/openapi.html), [AsyncAPI](https://tapir.softwaremill.com/en/latest/docs/asyncapi.html) and [JSON Schema](https://tapir.softwaremill.com/en/latest/docs/json-schema.html) formats\n\nDepending on how you'd prefer to explore Tapir, this documentation has three main sections:\n\n1. There's a number of [tutorials](https://tapir.softwaremill.com/en/latest/tutorials/01_hello_world.html), which provide a gentle introduction to the library\n2. Nothing compares to tinkering with working code, that's why we've prepared [runnable examples](https://tapir.softwaremill.com/en/latest/examples.html),\n   covering solutions to many \"everyday\" problems\n3. Finally, the reference documentation describes all of Tapir's aspects in depth - take a look at the menu on\n   the left, starting with the \"Endpoints\" section\n\n## Documentation\n\nTapir documentation is available at [tapir.softwaremill.com](http://tapir.softwaremill.com).\n\n## Why tapir?\n\n* **type-safety**: compile-time guarantees, develop-time completions, read-time information\n* **declarative**: separate the shape of the endpoint (the \"what\"), from the server logic (the \"how\")\n* **OpenAPI / Swagger integration**: generate documentation from endpoint descriptions\n* **observability**: leverage the metadata to report rich metrics and tracing information\n* **abstraction**: re-use common endpoint definitions, as well as individual inputs/outputs\n* **library, not a framework**: integrates with your stack\n\n## Adopters\n\nIs your company already using tapir? We're continually expanding the \"adopters\" section in the documentation; the more the merrier! It would be great to feature your company's logo, but in order to do that, we'll need written permission to avoid any legal misunderstandings.\n\nPlease email us at [tapir@softwaremill.com](mailto:tapir@softwaremill.com) from your company's email with a link to your logo (if we can use it, of course!) or with details who to kindly ask for permission to feature the logo in tapir's documentation. We'll handle the rest.\n\n||||\n| :---: | :---: | :---: |       \n| \u003ca href=\"https://www.adobe.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/adobe.png\" alt=\"Adobe\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://swisscom.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/swisscom.svg\" alt=\"Swisscom\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://swissborg.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/swissborg.png\" alt=\"Swissborg\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"https://kaizo.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/kaizo.png\" alt=\"Kaizo\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.process.st/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/process_street.png\" alt=\"Process Street\" width=\"100\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.tranzzo.com/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/tranzzo.svg\" alt=\"Tranzzo\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"https://www.kelkoogroup.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/kelkoogroup.png\" alt=\"Kelkoo group\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.softwaremill.com/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/softwaremill.png\" alt=\"SoftwareMill\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.carvana.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/carvana.svg\" alt=\"Carvana\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"https://www.moneyfarm.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/moneyfarm.png\" alt=\"Moneyfarm\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.ocadogroup.com/about-us/ocado-technology\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/ocado.png\" alt=\"Ocado Technology\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.wegtam.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/wegtam.svg\" alt=\"Wegtam\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"https://www.broad.app\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/broad.png\" alt=\"Broad\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.kensu.io?utm_source=github\u0026utm_campaign=tapir\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/kensu.png\" alt=\"Kensu\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.colisweb.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/colisweb.png\" alt=\"Colisweb\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"http://www.iceo.co/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/iceo.png\" alt=\"iceo\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"http://www.dpgrecruitment.nl/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/dpg-recruitment.svg\" alt=\"dpg\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.hunters.security/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/hunters.png\" alt=\"hunters\" width=\"160\"/\u003e\u003c/a\u003e | \n| \u003ca href=\"https://www.moia.io/en\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/moia.png\" alt=\"moia\" width=\"160\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.pitsdatarecovery.net\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/pits.svg\" alt=\"pits\" width=\"100\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.hootsuite.com\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/hootsuite.png\" alt=\"hootsuite\" width=\"160\"/\u003e\u003c/a\u003e |\n| \u003ca href=\"https://www.ematiq.com/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/ematiq.png\" alt=\"ematiq\" width=\"100\"/\u003e\u003c/a\u003e | \u003ca href=\"https://www.fugo.ai/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/fugo.png\" alt=\"fugo\" width=\"100\"/\u003e\u003c/a\u003e | \u003ca href=\"https://budgetbakers.com/\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/budgetbakers.svg\" alt=\"budgetbakers\" width=\"100\"/\u003e\u003c/a\u003e |\n| | \u003ca href=\"https://flo.health\"\u003e\u003cimg src=\"https://github.com/softwaremill/tapir/raw/master/doc/adopters/flo.svg\" alt=\"flo\" width=\"100\"/\u003e\u003c/a\u003e | |\n\n## Teaser\n\n```scala mdoc:compile-only\nimport sttp.tapir.*\nimport sttp.tapir.generic.auto.*\nimport sttp.tapir.json.circe.*\nimport io.circe.generic.auto.*\n\ntype Limit = Int\ntype AuthToken = String\ncase class BooksQuery(genre: String, year: Int)\ncase class Book(title: String)\n\n\n// Define an endpoint\n\nval booksListing: PublicEndpoint[(BooksQuery, Limit, AuthToken), String, List[Book], Any] = \n  endpoint\n    .get\n    .in((\"books\" / path[String](\"genre\") / path[Int](\"year\")).mapTo[BooksQuery])\n    .in(query[Limit](\"limit\").description(\"Maximum number of books to retrieve\"))\n    .in(header[AuthToken](\"X-Auth-Token\"))\n    .errorOut(stringBody)\n    .out(jsonBody[List[Book]])\n\n\n// Generate OpenAPI documentation\n\nimport sttp.apispec.openapi.circe.yaml.*\nimport sttp.tapir.docs.openapi.OpenAPIDocsInterpreter\n\nval docs = OpenAPIDocsInterpreter().toOpenAPI(booksListing, \"My Bookshop\", \"1.0\")\nprintln(docs.toYaml)\n\n\n// Convert to akka-http Route\n\nimport sttp.tapir.server.akkahttp.AkkaHttpServerInterpreter\nimport akka.http.scaladsl.server.Route\nimport scala.concurrent.Future\nimport scala.concurrent.ExecutionContext.Implicits.global\n\ndef bookListingLogic(bfy: BooksQuery,\n                     limit: Limit,\n                     at: AuthToken): Future[Either[String, List[Book]]] =\n  Future.successful(Right(List(Book(\"The Sorrows of Young Werther\"))))\n  \nval booksListingRoute: Route = AkkaHttpServerInterpreter()\n  .toRoute(booksListing.serverLogic((bookListingLogic _).tupled))\n\n\n// Convert to sttp Request\n\nimport sttp.tapir.client.sttp4.SttpClientInterpreter\nimport sttp.client4.*\n\nval booksListingRequest: Request[DecodeResult[Either[String, List[Book]]]] = \n  SttpClientInterpreter()\n    .toRequest(booksListing, Some(uri\"http://localhost:8080\"))\n    .apply((BooksQuery(\"SF\", 2016), 20, \"xyz-abc-123\"))\n```\n\n## Quickstart with sbt\n\nAdd the following dependency:\n\n```sbt\n\"com.softwaremill.sttp.tapir\" %% \"tapir-core\" % \"1.11.28\"\n```\n\nThen, import:\n\n```scala\nimport sttp.tapir._\n```\n\nAnd finally, type `endpoint.` and see where auto-complete gets you!\n\n### Scala 2.12\n\nPartial unification is now enabled by default from Scala 2.13. However, if you're using Scala 2.12 or older, then\nyou'll need partial unification enabled in the compiler (alternatively, you'll need to manually provide type\narguments in some cases):\n\n```sbt\nscalacOptions += \"-Ypartial-unification\"\n```\n\nSidenote for scala 2.12.4 and higher: if you encounter an issue with compiling your project because of \na `StackOverflowException` related to [this](https://github.com/scala/bug/issues/10604) scala bug, \nplease increase your stack memory. Example:\n\n```shell\nsbt -J-Xss4M clean compile\n```\n\n## Other sttp projects\n\nsttp is a family of Scala HTTP-related projects, and currently includes:\n\n* [sttp client](https://github.com/softwaremill/sttp): the Scala HTTP client you always wanted!\n* sttp tapir: this project\n* [sttp model](https://github.com/softwaremill/sttp-model): simple HTTP model classes (used by client \u0026 tapir)\n* [sttp shared](https://github.com/softwaremill/sttp-shared): shared web socket, FP abstractions, capabilities and streaming code.\n* [sttp apispec](https://github.com/softwaremill/sttp-apispec): OpenAPI, AsyncAPI and JSON Schema models.\n\n## Contributing\n\nAll suggestions welcome :)\n\nSee the list of [issues](https://github.com/softwaremill/tapir/issues) and pick one! Or report your own.\n\nIf you are having doubts on the _why_ or _how_ something works, don't hesitate to ask a question on\n[discourse](https://softwaremill.community/c/tapir) or via github. This probably means that the documentation, scaladocs or\ncode is unclear and be improved for the benefit of all.\nIn order to develop the documentation, you can use the `doc/watch.sh` script, which runs Sphinx using Python.\nUse `doc/requirements.txt` to set up your Python environment with `pip`. If you're using Nix, you can just run `nix develop`\nin the `doc` directory to set up a working shell with all the dependencies.\n\nThe `core` module needs to remain binary-compatible with earlier versions. To check if your changes meet this requirement,\nyou can run `core/mimaReportBinaryIssues` from the sbt console.\nHowever, be aware that tags from the repository aren’t automatically fetched during forking; hence, the command will not operate without first fetching the tags.\n\nAfter forking and cloning the repository, add the original repository as a remote:\n\n```\ngit remote add upstream git@github.com:softwaremill/tapir.git\n```\n\nFetch the tags from the upstream:\n```\ngit fetch --tags upstream\n```\n\nWhen you have a PR ready, take a look at our [\"How to prepare a good PR\" guide](https://softwaremill.community/t/how-to-prepare-a-good-pr-to-a-library/448). Thanks! :)\n\n## Scoping which projects are included by `sbt`\n\n* when `STTP_NATIVE` is set, Scala native projects are included in the build (when running `sbt`)\n* when `ALSO_LOOM` is set, projects using virtual threads and requiring Java 21 are included in the build \n* when `ONLY_LOOM` is set, only projects using virtual threads are included in the build\n\n### Testing locally\n\nThe JS tests use [Gecko instead of Chrome](https://github.com/scala-js/scala-js-env-selenium/issues/119), although this\ncauses another problem: out of memory when running JS tests for multiple modules. Work-arounds:\n\n- run only tests for a specific Scala version and platform using `testScoped 2.13 JS` (supported versions: 2.12, 2.13, 3; supported platforms: JVM, JS, Native)\n- test single JS projects\n- use CI (GitHub Actions) to test all projects - the `.github/workflows/ci.yml` enumerates them one by one\n\nYou can test only server/client/doc/other projects using `testServers`, `testClients`, `testDocs` and `testOther`.\n\nTo verify that the code snippet in docs compile, run `compileDocumentation`. A full mdoc run is done during a release\n(when the documentation is generated).\n\n### Importing into IntelliJ\n\nBy default, when importing to IntelliJ, only the Scala 3/JVM subprojects will be imported. This is controlled by the `ideSkipProject` setting in `build.sbt` (inside `commonSettings`).\n\nIf you'd like to work on a different platform or Scala version, simply change this setting temporarily so that the correct subprojects are imported. For example:\n\n```\n// import only Scala 2.13, JS projects\nideSkipProject := (scalaVersion.value != scala2_13) || !thisProjectRef.value.project.contains(\"JS\")\n\n// import only Scala 3, JVM projects\nideSkipProject := (scalaVersion.value != scala3) || thisProjectRef.value.project.contains(\"JS\") || thisProjectRef.value.project.contains(\"Native\"),\n\n// import only Scala 2.13, Native projects\nideSkipProject := (scalaVersion.value != scala2_13) || !thisProjectRef.value.project.contains(\"Native\")\n```\n\n## Commercial Support\n\nWe offer commercial support for tapir and related technologies, as well as development services. [Contact us](https://softwaremill.com) to learn more about our offer!\n\n## Copyright\n\nCopyright (C) 2018-2025 SoftwareMill [https://softwaremill.com](https://softwaremill.com).\n","funding_links":[],"categories":["Scala","\u003ca name=\"Scala\"\u003e\u003c/a\u003eScala","scala","Table of Contents"],"sub_categories":["HTTP"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Ftapir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftwaremill%2Ftapir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Ftapir/lists"}