The functional idea is the same: describe endpoints and generate servers/docs/etc.
However, the implementation is quite radically different.
endpoints library, you describe endpoints using methods available from traits that you need to mix in in order to access them. Endpoints are also defined “all at once”, that is you need to flesh out both the request method, response type etc. when creating the description.
tapir, endpoints are normal values —
case class instances — which can be freely shared, reused, copied etc. as all other Scala values. The same goes for endpoint inputs, outputs. Endpoints can be defined incrementally.
tapir's model is easier to work with, write interpreters etc. But of course it’s best to judge yourself. Definitely
tapir is also in some way inspired by
endpoints, as Julien’s library was created much earlier.
Going a bit deeper,
endpoints also has some features for authentication, which cross a bit into the logic layer of the application, but might be handy. On the other hand,
tapir is focuses only on describing the endpoints, strictly separating the description from the endpoint’s server logic.