A family of combinators for defining webservices APIs and serving them

You can learn about the basics in the tutorial.



The latest version of this document is on GitHub.


Significant changes

  • Streaming refactoring. #991 #1076 #1077

    The streaming functionality (Servant.API.Stream) is refactored to use servant’s own SourceIO type (see Servant.Types.SourceT documentation), which replaces both StreamGenerator and ResultStream types.

    New conversion type-classes are ToSourceIO and FromSourceIO (replacing ToStreamGenerator and BuildFromStream). There are instances for conduit, pipes and machines in new packages: servant-conduit servant-pipes and servant-machines respectively.

    Writing new framing strategies is simpler. Check existing strategies for examples.

    This change shouldn’t affect you, if you don’t use streaming endpoints.

  • servant-client Separate streaming client. #1066

    We now have two http-client based clients, in Servant.Client and Servant.Client.Streaming.

    Their API is the same, except for

    • Servant.Client cannot request Stream endpoints.
    • Servant.Client is run by direct runClientM :: ClientM a -> ClientEnv -> IO (Either ServantError a)
    • Servant.Client.Streaming can request Stream endpoints.
    • Servant.Client.Streaming is used by CPSised withClientM :: ClientM a -> ClientEnv -> (Either ServantError a -> IO b) -> IO b

    To access Stream endpoints use Servant.Client.Streaming with withClientM; otherwise you can continue using Servant.Client with runClientM. You can use both too, ClientEnv and BaseUrl types are same for both.

    Note: Servant.Client.Streaming doesn’t stream non-Stream endpoints. Requesting ordinary Verb endpoints (e.g. Get) will block until the whole response is received.

    There is Servant.Client.Streaming.runClientM function, but it has restricted type. NFData a constraint prevents using it with SourceT, Conduit etc. response types.

    runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ServantError a)

    This change shouldn’t affect you, if you don’t use streaming endpoints.

  • servant-client-core Related to the previous: streamingResponse is removed from RunClient. We have a new type-class:

    class RunClient m =>  RunStreamingClient m where
        withStreamingRequest :: Request -> (StreamingResponse -> IO a) ->  m a
  • Drop support for GHC older than 8.0 #1008 #1009

  • servant ComprehensiveAPI is a part of public API in Servant.Test.ComprehensiveAPI module. This API type is used to verify that libraries implement all core combinators. Now we won’t change this type between major versions. (This has been true for some time already). #1070

  • servant Remove Servant.Utils.Enter module (deprecated in servant-0.12 in favour of hoistServer) #996

  • servant-foreign Add support so HasForeign can be implemented for MultipartForm from servant-multipart #1035

Other changes


  • Merge in (and slightly refactor) servant-generic (by Patrick Chilton) into servant (Servant.API.Generic), servant-client-code (Servant.Client.Generic) and servant-server (Servant.Server.Generic).

  • Deprecate Servant.Utils.Links, use Servant.Links. #998

  • servant-server Deprecate Servant.Utils.StaticUtils, use Servant.Server.StaticUtils.


Signifacant changes

  • Stream takes a status code argument

    -Stream method        framing ctype a
    +Stream method status framing ctype a

    (#966 #972)

  • ToStreamGenerator definition changed, so it’s possible to write an instance for conduits.

    -class ToStreamGenerator f a where
    -   toStreamGenerator :: f a -> StreamGenerator a
    +class ToStreamGenerator a b | a -> b where
    +   toStreamGenerator :: a -> StreamGenerator b


  • Added NoFraming streaming strategy (#959)

  • servant-client-core Free Client implementation. Useful for testing HasClient instances. (#920)

  • servant-client-core Add hoistClient to HasClient. Just like hoistServer allows us to change the monad in which request handlers of a web application live in, we also have hoistClient for changing the monad in which client functions live. Read tutorial section for more information. (#936)

    iF you have own combinators, you’ll need to define a new method of HasClient class, for example:

    type Client m (MyCombinator :> api) = MyValue :> Client m api
    hoistClientMonad pm _ nt cl = hoistClientMonad pm (Proxy :: Proxy api) nt . cl
  • servant Add safeLink' :: (Link -> a) -> ... -> MkLink endpoint a, which allows to create helpers returning something else than Link. (#968)

  • servant-server File serving in polymorphic monad. i.e. Generalised types of serveDirectoryFileServer etc functions in Servant.Utils.StaticFiles (#953)

  • servant-server ReqBody content type check is recoverable. This allows writing APIs like:

          ReqBody '[JSON] Int      :> Post '[PlainText] Int
    :<|>  ReqBody '[PlainText] Int :> Post '[PlainText] Int

    which is useful when handlers are subtly different, for example may do less work. (#937)

  • servant-client Add more constructors to RequestBody, including RequestBodyStream. Note: we are looking for http-library agnostic API, so the might change again soon. Tell us which constructors are useful for you! (#913)

Other changes


(VIM) Regular-expression to link PR numbers: s/\v#(\d+)/[#\1](https:\/\/github.com\/haskell-servant\/servant/pull\/\1)/

  • Support base-compat-0.10


Significant changes

Other changes


Bug fixes

  • Prevent double-escaping in link segments (#835 #878)


Significant changes

  • servant-client servant-client-core Factored out of servant-client all the functionality that was independent of the http-client backend. (#803 #821)

    If you have own combinators, you’ll need to add an additional m argument in HasClient, Client and clientWithRoute:

    -class HasClient api
    -  type Client (api :: *) :: *
    -  clientWithRoute :: Proxy api -> Req -> Client api
    +class HasClient m api
    +  type Client (m :: * -> *) (api :: *) :: *
    +  clientWithRoute :: Proxy m -> Proxy api -> Request -> Client m api

    See https://github.com/haskell-servant/servant-auth/pull/67/commits/f777818e3cc0fa3ed2346baff8328e96d62b1790 for a real world example.

  • servant-server Added hoistServer member to the HasServer class, which is HasServer specific enter. (#804 #824)

    enter isn’t exported from Servant module anymore. You can change enter to hoistServer in a straight forward way. Unwrap natural transformation and add a api type Proxy:

    -server = enter (NT nt) impl
    +server = hoistServer (Proxy :: Proxy MyApi) nt impl

    If you have own combinators, you’ll need to define a new method of HasServer class, for example:

    type ServerT (MyCombinator :> api) m = MyValue -> ServerT api m
    hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s

    See https://github.com/haskell-servant/servant-auth/pull/67/commits/8ee3b6315247ac076516213fd7cfcdbfdb583ac9 for a real world example.

  • Add Description and Summary combinators (#767)

    It’s possible to annotate endpoints with free form text. This information is used by e.g. by servant-swagger, see screenshot in https://github.com/phadej/servant-swagger-ui

  • Lower :> and :<|> infix precedence to 4 and 3 respectively (#761)

    This shouldn’t affect you, except if you define your own infix operators for Servant type-level DSL.

Other changes

  • servant-foreign Derive Data for all types (#809)
  • servant-docs Add authentication lenses (#787)
  • servant-docs Generated markdown improvements (#813 #767 #790 #788)
  • Add addLinks to generate all links for unnested APIs. (#851)
  • Allow newest dependencies (#772 #842)
  • Documentation improvements and typo fixes (#757 #771 #775 #790 #791 #806)
  • Development process improvements (#764 #839)


Breaking changes

Other changes

  • Add a type representing an empty API (#753)
  • Add linkURI' and Link accessors (#745 , #717 , #715)
  • Prepare for GHC-8.2 (#722)
  • Add HasLink AuthProtect instance (#720)
  • AllCTRender [] () TypeError (use NoContent) (#671)
  • Documentation improvements and typo fixes (#702 , #709 , #716 , #725 , #727)


Breaking changes

  • Use NT from natural-transformation for Enter (#616)

  • Change to MkLink (Verb ...) = Link (previously URI). To consume Link use its ToHttpApiData instance or linkURI. (#527)

Other changes

  • Add Servant.API.TypeLevel module with type families to work with API types. (#345 , #305)

  • Default JSON content type change to application/json;charset=utf-8. (#263) Related browser bugs: Chromium and Firefox

  • Accept class may accept multiple content-types. MimeUnrender adopted as well. (#613 , #615)


  • Added ‘noHeader’ function for not adding response headers.


  • Added Eq, Show, Read, Generic and Ord instances to IsSecure
  • BACKWARDS INCOMPATIBLE: replace use of ToFromByteString with To/FromHttpApiData for GetHeaders/BuildHeadersTo
  • BACKWARDS INCOMPATIBLE: Moved From/ToFormUrlEncoded classes, which were renamed to From/ToForm to http-api-data


  • Add CaptureAll combinator. Captures all of the remaining segments in a URL.
  • Add Servant.API.TypeLevel module, with frequently used type-level functionaliy.


  • Minor fixes, documentation changes and cabal tweaks



  • Add WithNamedConfig combinator.
  • Add HttpVersion, IsSecure, RemoteHost and Vault combinators
  • Fix safeLink, so Header is not in fact required.
  • Add more instances for (:<|>)
  • Use http-api-data instead of Servant.Common.Text
  • Remove matrix params.
  • Add PlainText String MimeRender and MimeUnrender instances.
  • Add new Verbs combinator, and make all existing and new verb combinators type synonyms of it.
  • Add BasicAuth combinator to support Basic authentication
  • Add generalized authentication support


  • Fix missing cases for Patch in safeLink


  • Allow whitespace after parsing JSON
  • Stricter matching for safeLink for Capture


  • Delete now is like Get, Post, Put, and Patch and returns a response body
  • Multiple content-type/accept support for all the relevant combinators
  • Provide JSON, PlainText, OctetStream and FormUrlEncoded content types out of the box
  • Type-safe link generation to API endpoints
  • Support for the PATCH HTTP method
  • Removed the home-made QuasiQuote for writing API types in a more human-friendly format until we come up with a better design for it
  • Make most if not all of the haddock code examples run through doctest
  • Some general code cleanup
  • Add response headers