diff --git a/api-builder.cabal b/api-builder.cabal
--- a/api-builder.cabal
+++ b/api-builder.cabal
@@ -1,5 +1,5 @@
 name: api-builder
-version: 0.8.0.0
+version: 0.9.0.0
 synopsis: Library for easily building REST API wrappers in Haskell
 license: BSD3
 license-file: LICENSE
@@ -18,7 +18,7 @@
 source-repository this
   type: git
   location: git://github.com/intolerable/api-builder.git
-  tag: v0.8.0.0
+  tag: v0.9.0.0
 
 library
   exposed-modules:
@@ -38,7 +38,6 @@
     attoparsec >= 0.11 && < 0.13,
     bifunctors >= 4.0 && < 6.0,
     bytestring == 0.10.*,
-    either == 4.*,
     HTTP == 4000.*,
     http-client == 0.4.7.* || == 0.4.11.*,
     http-conduit == 2.*,
diff --git a/src/Network/API/Builder/API.hs b/src/Network/API/Builder/API.hs
--- a/src/Network/API/Builder/API.hs
+++ b/src/Network/API/Builder/API.hs
@@ -10,6 +10,7 @@
   , routeResponse
   , routeRequest
   -- ** Lifting
+  , liftExcept
   , liftEither
   , liftManager
   , liftBuilder
@@ -30,7 +31,7 @@
 import Control.Exception
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Control.Monad.Trans.Class (lift)
-import Control.Monad.Trans.Either
+import Control.Monad.Trans.Except
 import Control.Monad.Trans.Reader
 import Control.Monad.Trans.State
 import Data.ByteString.Lazy (ByteString)
@@ -43,12 +44,17 @@
 
 -- | Main API transformer type. @s@ is the API's internal state, @e@ is the API's custom error type,
 --   and @a@ is the result when the API runs.
-type APIT s e m a = EitherT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a
+type APIT s e m a = ExceptT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a
 
 -- | Lifts an action that works on an @API@ to an action that works on an @API@.
 --   This function is provided solely for future-proofing in the case that more transformers
 --   need to be stacked on top - it's implemented simply as @id@ for the moment.
-liftEither :: Monad m => EitherT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a -> APIT s e m a
+liftExcept :: Monad m => ExceptT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a -> APIT s e m a
+liftExcept = id
+
+{-# DEPRECATED liftEither "Use liftExcept" #-}
+-- | Identical to 'liftExcept', provided for (almost) compatibility.
+liftEither :: Monad m => ExceptT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a -> APIT s e m a
 liftEither = id
 
 -- | Lifts an action that works on a @Manager@ to one that works on an @API@.
@@ -86,7 +92,7 @@
        -> APIT s e m a -- ^ the actual @API@ to run
        -> m (Either (APIError e) a, Builder, s) -- ^ IO action that returns either an error or the result, as well as the final states
 runAPI b m s api = do
-  ((res, b'), s') <- runStateT (runStateT (runReaderT (runEitherT api) m) b) s
+  ((res, b'), s') <- runStateT (runStateT (runReaderT (runExceptT api) m) b) s
   return (res, b', s')
 
 -- | Runs a @Route@. Infers the type to convert to from the JSON with the @a@ in @API@,
@@ -109,10 +115,10 @@
 sendRoute s r = do
   builder <- liftBuilder get
   manager <- liftManager ask
-  req <- hoistEither $ send builder r s `eitherOr` InvalidURLError
+  req <- ExceptT $ return $ send builder r s `eitherOr` InvalidURLError
   response <- liftIO $ try $ httpLbs req manager
-  res <- hoistEither $ first HTTPError response
-  hoistEither $ receive res
+  res <- ExceptT $ return $ first HTTPError response
+  ExceptT $ return $ receive res
 
 -- | Try to construct a @Request@ from a @Route@ (with the help of the @Builder@). Returns @Nothing@ if
 --   the URL is invalid or there is another error with the @Route@.
diff --git a/src/Network/API/Builder/Send.hs b/src/Network/API/Builder/Send.hs
--- a/src/Network/API/Builder/Send.hs
+++ b/src/Network/API/Builder/Send.hs
@@ -9,6 +9,8 @@
 import qualified Data.ByteString.Char8 as ByteString
 import qualified Data.Text as Text
 
+-- | Class for types that can be sent with api-builder.
+--   Given a 'Builder', a 'Route', and an instance of 'Sendable', we should be able to construct a 'Request' for the API's server. If we can't, 'send' returns 'Nothing' and 'APIT' complains about being unable to send the given data.
 class Sendable s where
   send :: Builder -> Route -> s -> Maybe Request
 
@@ -49,6 +51,7 @@
         return $ req { requestBody = RequestBodyLBS bs }
       _ -> Nothing
 
+-- | By default, the '()' instance for 'Sendable' moves the query parameters of the 'Route' into the body of the POST request. Most APIs handle both, but some will complain if they aren't sent in the actual query. If you 'send' 'PostQuery' instead of '()', the query params won't move from the actual query string when constructing the request.
 data PostQuery = PostQuery
   deriving (Show)
 
