diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.6.1
+
+*  Export TweetMode (Extended) [#92](https://github.com/himura/twitter-conduit/pull/92)
+
 ## 0.6.0
 
 * Support extended tweets [#83](https://github.com/himura/twitter-conduit/pull/83)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -10,11 +10,6 @@
 
 Documentation is available in [hackage](http://hackage.haskell.org/package/twitter-conduit).
 
-## Usage ##
-
-    $ cabal update
-    $ cabal install twitter-conduit
-
 ## Quick Start ##
 
 For a runnable example, see [sample/simple.hs](https://github.com/himura/twitter-conduit/blob/master/sample/simple.hs).
@@ -24,19 +19,32 @@
 
 ### Build ###
 
-If you would like to use cabal sandbox, prepare sandbox as below:
+#### Building with Cabal ####
 
 ~~~~
-$ cabal sandbox init
+$ cabal v2-build all
 ~~~~
 
-and then,
+#### Building with Stack ####
 
-~~~~
-$ cabal install --only-dependencies -fbuild-samples
-$ cabal configure -fbuild-samples
-$ cabal build
-~~~~
+To build with Stack, you should create top-level `stack.yaml` file first.
+An example of `stack.yaml` is like below:
+
+```.yaml
+resolver: lts-18.12
+packages:
+- .
+- sample
+extra-deps:
+- twitter-types-0.11.0
+- twitter-types-lens-0.11.0
+```
+
+then, run stack.
+
+```
+$ stack build
+```
 
 ### Run ###
 
diff --git a/Web/Twitter/Conduit.hs b/Web/Twitter/Conduit.hs
--- a/Web/Twitter/Conduit.hs
+++ b/Web/Twitter/Conduit.hs
@@ -13,6 +13,18 @@
     -- * How to use this library
     -- $howto
 
+    -- ** Authentication
+    -- $auth
+
+    -- ** How to call API
+    -- $call
+
+    -- *** How to specify API parameters
+    -- $parameter
+
+    -- *** Conduit API: Recursive API call with changing cursor parameter
+    -- $conduit
+
     -- * Re-exports
     module Web.Twitter.Conduit.Api,
     module Web.Twitter.Conduit.Cursor,
@@ -38,6 +50,7 @@
     MediaData (..),
     UserListParam (..),
     UserParam (..),
+    TweetMode (..),
 
     -- * re-exports
     OAuth (..),
@@ -80,17 +93,22 @@
 -- and <http://hackage.haskell.org/package/conduit conduit>.
 -- All of following examples import modules as below:
 --
--- > {\-# LANGUAGE OverloadedStrings #-\}
--- >
--- > import Web.Twitter.Conduit
--- > import Web.Twitter.Types.Lens
--- > import Data.Conduit
--- > import qualified Data.Conduit.List as CL
--- > import qualified Data.Text as T
--- > import qualified Data.Text.IO as T
--- > import Control.Monad.IO.Class
--- > import Control.Lens
+-- @
+-- {\-# LANGUAGE OverloadedLabels #-\}
+-- {\-# LANGUAGE OverloadedStrings #-\}
 --
+-- import Web.Twitter.Conduit
+-- import Web.Twitter.Types.Lens
+-- import Data.Conduit
+-- import qualified Data.Conduit.List as CL
+-- import qualified Data.Text as T
+-- import qualified Data.Text.IO as T
+-- import Control.Monad.IO.Class
+-- import Control.Lens
+-- @
+
+-- $auth
+--
 -- First, you should obtain consumer token and secret from <https://apps.twitter.com/ Twitter>,
 -- and prepare 'OAuth' variables as follows:
 --
@@ -132,7 +150,11 @@
 --
 -- Or, simply as follows:
 --
--- > twInfo = setCredential tokens credential def
+-- @
+-- twInfo = 'setCredential' tokens credential 'def'
+-- @
+
+-- $call
 --
 -- Twitter API requests are performed by 'call' function.
 -- For example, <https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline GET statuses/home_timeline>
@@ -140,7 +162,7 @@
 --
 -- @
 -- mgr \<- 'newManager' 'tlsManagerSettings'
--- timeline \<- 'call' twInfo mgr 'homeTimeline'
+-- timeline \<- 'call' twInfo mgr 'statusesHomeTimeline'
 -- @
 --
 -- The response of 'call' function is wrapped by the suitable type of
@@ -153,9 +175,48 @@
 -- includes 20 tweets, and you can change the number of tweets by the /count/ parameter.
 --
 -- @
--- timeline \<- 'call' twInfo mgr '$' 'homeTimeline' '&' #count '?~' 200
+-- timeline \<- 'call' twInfo mgr '$' 'statusesHomeTimeline' '&' #count '?~' 200
 -- @
+
+-- $parameter
 --
+-- The parameters which can be specified for this API, is able to be obtained from type parameters of APIRequest.
+-- For example,
+--
+-- @
+-- 'statusesHomeTimeline' ::
+--     'APIRequest' 'StatusesHomeTimeline' ['Web.Twitter.Types.Status']
+-- @
+--
+-- - The 2nd type parameter of 'APIRequest' represents acceptable parameters in this API request.
+-- - The 3nd type parameter of 'APIRequest' denotes a return type of this API request.
+--
+-- The 2nd type parameter of 'statusesHomeTimeline' is 'StatusesHomeTimeline' defined as below:
+--
+-- @
+-- type StatusesHomeTimeline =
+--     '[ "count" ':= Integer
+--      , "since_id" ':= Integer
+--      , "max_id" ':= Integer
+--      , "trim_user" ':= Bool
+--      , "exclude_replies" ':= Bool
+--      , "contributor_details" ':= Bool
+--      , "include_entities" ':= Bool
+--      , "tweet_mode" ':= TweetMode
+--      ]
+-- @
+--
+-- Each element of list represents the name and type of API parameters.
+-- You can specify those parameter with OverloadedLabels extension.
+-- In the above example, it shows that 'statusesHomeTimeline' API supports "tweet_mode" parameter with 'TweetMode' type, so
+-- you can specify "tweet_mode" parameter as:
+--
+-- @
+-- 'statusesHomeTimeline' & #tweet_mode ?~ 'Extended'
+-- @
+
+-- $conduit
+--
 -- If you need more statuses, you can obtain those with multiple API requests.
 -- This library provides the wrapper for multiple requests with conduit interfaces.
 -- For example, if you intend to fetch the all friends information,
@@ -163,24 +224,31 @@
 -- or use the conduit wrapper 'sourceWithCursor' as below:
 --
 -- @
--- friends \<- 'sourceWithCursor' twInfo mgr ('friendsList' ('ScreenNameParam' \"thimura\") '&' #count '?~' 200) '$$' 'CL.consume'
+-- friends \<-
+--     'runConduit' $
+--         'sourceWithMaxId' twInfo mgr ('friendsList' ('ScreenNameParam' \"thimura\") '&' #count '?~' 200)
+--             '.|' 'CL.consume'
 -- @
 --
 -- Statuses APIs, for instance, 'homeTimeline', are also wrapped by 'sourceWithMaxId'.
 --
--- For example, you can print 1000 tweets from your home timeline, as below:
+-- For example, you can print 60 tweets from your home timeline, as below:
 --
 -- @
 -- main :: IO ()
 -- main = do
 --     mgr \<- 'newManager' 'tlsManagerSettings'
---     'sourceWithMaxId' twInfo mgr 'homeTimeline'
---         $= CL.isolate 60
---         $$ CL.mapM_ $ \\status -> liftIO $ do
---             T.putStrLn $ T.concat [ T.pack . show $ status ^. statusId
---                                   , \": \"
---                                   , status ^. statusUser . userScreenName
---                                   , \": \"
---                                   , status ^. statusText
---                                   ]
+--     'runConduit' $ 'sourceWithMaxId' twInfo mgr 'homeTimeline'
+--         '.|' CL.isolate 60
+--         '.|' CL.mapM_
+--             (\\status -> do
+--                  T.putStrLn $
+--                      T.concat
+--                          [ T.pack . show $ status ^. statusId
+--                          , \": \"
+--                          , status ^. statusUser . userScreenName
+--                          , \": \"
+--                          , status ^. statusText
+--                          ]
+--             )
 -- @
diff --git a/Web/Twitter/Conduit/Api.hs b/Web/Twitter/Conduit/Api.hs
--- a/Web/Twitter/Conduit/Api.hs
+++ b/Web/Twitter/Conduit/Api.hs
@@ -6,16 +6,27 @@
 
 module Web.Twitter.Conduit.Api (
     -- * Status
+    StatusesMentionsTimeline,
     statusesMentionsTimeline,
+    StatusesUserTimeline,
     statusesUserTimeline,
+    StatusesHomeTimeline,
     statusesHomeTimeline,
+    StatusesRetweetsOfMe,
     statusesRetweetsOfMe,
+    StatusesRetweetsId,
     statusesRetweetsId,
+    StatusesShowId,
     statusesShowId,
+    StatusesDestroyId,
     statusesDestroyId,
+    StatusesUpdate,
     statusesUpdate,
+    StatusesRetweetId,
     statusesRetweetId,
+    StatusesUpdateWithMedia,
     statusesUpdateWithMedia,
+    StatusesLookup,
     statusesLookup,
 
     -- * Search
@@ -165,7 +176,6 @@
 import Web.Twitter.Conduit.Parameters
 import Web.Twitter.Conduit.Request
 import Web.Twitter.Conduit.Request.Internal
-import qualified Web.Twitter.Conduit.Status as Status
 import Web.Twitter.Types
 
 import Data.Aeson
@@ -178,6 +188,280 @@
 -- >>> :set -XOverloadedStrings -XOverloadedLabels
 -- >>> import Control.Lens
 
+-- * Timelines
+
+-- | Returns query data asks the most recent mentions for the authenticating user.
+--
+-- You can perform a query using 'call':
+--
+-- @
+-- res <- 'call' 'mentionsTimeline'
+-- @
+--
+-- >>> statusesMentionsTimeline
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/mentions_timeline.json" []
+statusesMentionsTimeline :: APIRequest StatusesMentionsTimeline [Status]
+statusesMentionsTimeline = APIRequest "GET" (endpoint ++ "statuses/mentions_timeline.json") def
+
+type StatusesMentionsTimeline =
+    '[ "count" ':= Integer
+     , "since_id" ':= Integer
+     , "max_id" ':= Integer
+     , "trim_user" ':= Bool
+     , "contributor_details" ':= Bool
+     , "include_entities" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns query data asks a collection of the most recent Tweets posted by the user indicated by the screen_name or user_id parameters.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' $ 'userTimeline' ('ScreenNameParam' \"thimura\")
+-- @
+--
+-- >>> statusesUserTimeline (ScreenNameParam "thimura")
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/user_timeline.json" [("screen_name","thimura")]
+-- >>> statusesUserTimeline (ScreenNameParam "thimura") & #include_rts ?~ True & #count ?~ 200
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/user_timeline.json" [("count","200"),("include_rts","true"),("screen_name","thimura")]
+statusesUserTimeline :: UserParam -> APIRequest StatusesUserTimeline [Status]
+statusesUserTimeline q = APIRequest "GET" (endpoint ++ "statuses/user_timeline.json") (mkUserParam q)
+
+type StatusesUserTimeline =
+    '[ "count" ':= Integer
+     , "since_id" ':= Integer
+     , "max_id" ':= Integer
+     , "trim_user" ':= Bool
+     , "exclude_replies" ':= Bool
+     , "contributor_details" ':= Bool
+     , "include_rts" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns query data asks a collection of the most recentTweets and retweets posted by the authenticating user and the users they follow.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' 'homeTimeline'
+-- @
+--
+-- >>> statusesHomeTimeline
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" []
+-- >>> statusesHomeTimeline & #count ?~ 200
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" [("count","200")]
+statusesHomeTimeline :: APIRequest StatusesHomeTimeline [Status]
+statusesHomeTimeline = APIRequest "GET" (endpoint ++ "statuses/home_timeline.json") def
+
+type StatusesHomeTimeline =
+    '[ "count" ':= Integer
+     , "since_id" ':= Integer
+     , "max_id" ':= Integer
+     , "trim_user" ':= Bool
+     , "exclude_replies" ':= Bool
+     , "contributor_details" ':= Bool
+     , "include_entities" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns query data asks the most recent tweets authored by the authenticating user that have been retweeted by others.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' 'retweetsOfMe'
+-- @
+--
+-- >>> statusesRetweetsOfMe
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" []
+-- >>> statusesRetweetsOfMe & #count ?~ 100
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" [("count","100")]
+statusesRetweetsOfMe :: APIRequest StatusesRetweetsOfMe [Status]
+statusesRetweetsOfMe = APIRequest "GET" (endpoint ++ "statuses/retweets_of_me.json") def
+
+type StatusesRetweetsOfMe =
+    '[ "count" ':= Integer
+     , "since_id" ':= Integer
+     , "max_id" ':= Integer
+     , "trim_user" ':= Bool
+     , "include_entities" ':= Bool
+     , "include_user_entities" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- * Tweets
+
+-- | Returns query data that asks for the most recent retweets of the specified tweet
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'retweetsId' 1234567890
+-- @
+--
+-- >>> statusesRetweetsId 1234567890
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" []
+-- >>> statusesRetweetsId 1234567890 & #count ?~ 100
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" [("count","100")]
+statusesRetweetsId :: StatusId -> APIRequest StatusesRetweetsId [RetweetedStatus]
+statusesRetweetsId status_id = APIRequest "GET" uri def
+  where
+    uri = endpoint ++ "statuses/retweets/" ++ show status_id ++ ".json"
+
+type StatusesRetweetsId =
+    '[ "count" ':= Integer
+     , "trim_user" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns query data asks a single Tweet, specified by the id parameter.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'showId' 1234567890
+-- @
+--
+-- >>> statusesShowId 1234567890
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/show/1234567890.json" []
+-- >>> statusesShowId 1234567890 & #include_my_retweet ?~ True
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/show/1234567890.json" [("include_my_retweet","true")]
+statusesShowId :: StatusId -> APIRequest StatusesShowId Status
+statusesShowId status_id = APIRequest "GET" uri def
+  where
+    uri = endpoint ++ "statuses/show/" ++ show status_id ++ ".json"
+
+type StatusesShowId =
+    '[ "trim_user" ':= Bool
+     , "include_my_retweet" ':= Bool
+     , "include_entities" ':= Bool
+     , "include_ext_alt_text" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns post data which destroys the status specified by the require ID parameter.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'destroyId' 1234567890
+-- @
+--
+-- >>> statusesDestroyId 1234567890
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/destroy/1234567890.json" []
+statusesDestroyId :: StatusId -> APIRequest StatusesDestroyId Status
+statusesDestroyId status_id = APIRequest "POST" uri def
+  where
+    uri = endpoint ++ "statuses/destroy/" ++ show status_id ++ ".json"
+
+type StatusesDestroyId =
+    '[ "trim_user" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns post data which updates the authenticating user's current status.
+-- To upload an image to accompany the tweet, use 'updateWithMedia'.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'update' \"Hello World\"
+-- @
+--
+-- >>> statusesUpdate "Hello World"
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/update.json" [("status","Hello World")]
+-- >>> statusesUpdate "Hello World" & #in_reply_to_status_id ?~ 1234567890
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/update.json" [("in_reply_to_status_id","1234567890"),("status","Hello World")]
+statusesUpdate :: T.Text -> APIRequest StatusesUpdate Status
+statusesUpdate status = APIRequest "POST" uri [("status", PVString status)]
+  where
+    uri = endpoint ++ "statuses/update.json"
+
+type StatusesUpdate =
+    '[ "in_reply_to_status_id" ':= Integer
+     , -- , "lat_long"
+       -- , "place_id"
+       "display_coordinates" ':= Bool
+     , "trim_user" ':= Bool
+     , "media_ids" ':= [Integer]
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns post data which retweets a tweet, specified by ID.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'retweetId' 1234567890
+-- @
+--
+-- >>> statusesRetweetId 1234567890
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/retweet/1234567890.json" []
+statusesRetweetId :: StatusId -> APIRequest StatusesRetweetId RetweetedStatus
+statusesRetweetId status_id = APIRequest "POST" uri def
+  where
+    uri = endpoint ++ "statuses/retweet/" ++ show status_id ++ ".json"
+
+type StatusesRetweetId =
+    '[ "trim_user" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns post data which updates the authenticating user's current status and attaches media for upload.
+--
+-- You can perform a search query using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'updateWithMedia' \"Hello World\" ('MediaFromFile' \"/home/thimura/test.jpeg\")
+-- @
+--
+-- >>> statusesUpdateWithMedia "Hello World" (MediaFromFile "/home/fuga/test.jpeg")
+-- APIRequestMultipart "POST" "https://api.twitter.com/1.1/statuses/update_with_media.json" [("status","Hello World")]
+statusesUpdateWithMedia ::
+    T.Text ->
+    MediaData ->
+    APIRequest StatusesUpdateWithMedia Status
+statusesUpdateWithMedia tweet mediaData =
+    APIRequestMultipart "POST" uri [("status", PVString tweet)] [mediaBody mediaData]
+  where
+    uri = endpoint ++ "statuses/update_with_media.json"
+    mediaBody (MediaFromFile fp) = partFileSource "media[]" fp
+    mediaBody (MediaRequestBody filename filebody) = partFileRequestBody "media[]" filename filebody
+
+type StatusesUpdateWithMedia =
+    '[ "possibly_sensitive" ':= Bool
+     , "in_reply_to_status_id" ':= Integer
+     , -- , "lat_long"
+       -- , "place_id"
+       "display_coordinates" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
+-- | Returns fully-hydrated tweet objects for up to 100 tweets per request, as specified by comma-separated values passed to the id parameter.
+--
+-- You can perform a request using 'call':
+--
+-- @
+-- res <- 'call' twInfo mgr '$' 'lookup' [20, 432656548536401920]
+-- @
+--
+-- >>> statusesLookup [10]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10")]
+-- >>> statusesLookup [10, 432656548536401920]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10,432656548536401920")]
+-- >>> statusesLookup [10, 432656548536401920] & #include_entities ?~ True
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("include_entities","true"),("id","10,432656548536401920")]
+statusesLookup :: [StatusId] -> APIRequest StatusesLookup [Status]
+statusesLookup ids = APIRequest "GET" (endpoint ++ "statuses/lookup.json") [("id", PVIntegerArray ids)]
+
+type StatusesLookup =
+    '[ "include_entities" ':= Bool
+     , "trim_user" ':= Bool
+     , "map" ':= Bool
+     , "tweet_mode" ':= TweetMode
+     ]
+
 -- | Returns search query.
 --
 -- You can perform a search query using 'call':
@@ -1011,26 +1295,3 @@
     mediaBody (MediaRequestBody filename filebody) = partFileRequestBody "media" filename filebody
 
 type MediaUpload = EmptyParams
-
-statusesMentionsTimeline :: APIRequest Status.StatusesMentionsTimeline [Status]
-statusesMentionsTimeline = Status.mentionsTimeline
-statusesUserTimeline :: UserParam -> APIRequest Status.StatusesUserTimeline [Status]
-statusesUserTimeline = Status.userTimeline
-statusesHomeTimeline :: APIRequest Status.StatusesHomeTimeline [Status]
-statusesHomeTimeline = Status.homeTimeline
-statusesRetweetsOfMe :: APIRequest Status.StatusesRetweetsOfMe [Status]
-statusesRetweetsOfMe = Status.retweetsOfMe
-statusesRetweetsId :: StatusId -> APIRequest Status.StatusesRetweetsId [RetweetedStatus]
-statusesRetweetsId = Status.retweetsId
-statusesShowId :: StatusId -> APIRequest Status.StatusesShowId Status
-statusesShowId = Status.showId
-statusesDestroyId :: StatusId -> APIRequest Status.StatusesDestroyId Status
-statusesDestroyId = Status.destroyId
-statusesUpdate :: T.Text -> APIRequest Status.StatusesUpdate Status
-statusesUpdate = Status.update
-statusesRetweetId :: StatusId -> APIRequest Status.StatusesRetweetId RetweetedStatus
-statusesRetweetId = Status.retweetId
-statusesUpdateWithMedia :: T.Text -> MediaData -> APIRequest Status.StatusesUpdateWithMedia Status
-statusesUpdateWithMedia = Status.updateWithMedia
-statusesLookup :: [StatusId] -> APIRequest Status.StatusesLookup [Status]
-statusesLookup = Status.lookup
diff --git a/Web/Twitter/Conduit/Base.hs b/Web/Twitter/Conduit/Base.hs
--- a/Web/Twitter/Conduit/Base.hs
+++ b/Web/Twitter/Conduit/Base.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -51,15 +50,12 @@
 import qualified Data.Conduit.List as CL
 import qualified Data.Map as M
 import qualified Data.Text.Encoding as T
+import GHC.TypeLits (KnownSymbol)
 import Network.HTTP.Client.MultipartFormData
 import qualified Network.HTTP.Conduit as HTTP
 import qualified Network.HTTP.Types as HT
 import Web.Authenticate.OAuth (signOAuth)
 
-#if __GLASGOW_HASKELL__ < 804
-import Data.Monoid
-#endif
-
 makeRequest ::
     APIRequest apiName responseType ->
     IO HTTP.Request
@@ -298,7 +294,7 @@
 sourceWithCursor ::
     ( MonadIO m
     , FromJSON responseType
-    , CursorKey ck
+    , KnownSymbol ck
     , HasParam "cursor" Integer supports
     ) =>
     -- | Twitter Setting
@@ -322,7 +318,7 @@
 -- This function cooperate with instances of 'HasCursorParam'.
 sourceWithCursor' ::
     ( MonadIO m
-    , CursorKey ck
+    , KnownSymbol ck
     , HasParam "cursor" Integer supports
     ) =>
     -- | Twitter Setting
diff --git a/Web/Twitter/Conduit/Cursor.hs b/Web/Twitter/Conduit/Cursor.hs
--- a/Web/Twitter/Conduit/Cursor.hs
+++ b/Web/Twitter/Conduit/Cursor.hs
@@ -1,10 +1,13 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Web.Twitter.Conduit.Cursor (
-    CursorKey (..),
     IdsCursorKey,
     UsersCursorKey,
     ListsCursorKey,
@@ -12,79 +15,60 @@
     WithCursor (..),
 ) where
 
+import Control.DeepSeq (NFData)
 import Data.Aeson
-import Data.Text (Text)
-import Web.Twitter.Types (checkError)
+import Data.Proxy (Proxy (..))
+import Data.String
+import GHC.Generics
+import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
 
 -- $setup
+-- >>> import Data.Text
 -- >>> type UserId = Integer
 
-{- ORMOLU_DISABLE -}
-class CursorKey a where
-#if MIN_VERSION_aeson(2, 0, 0)
-    cursorKey :: a -> Key
-#else
-    cursorKey :: a -> Text
-#endif
-{- ORMOLU_ENABLE -}
-
--- | Phantom type to specify the key which point out the content in the response.
-data IdsCursorKey
-
-instance CursorKey IdsCursorKey where
-    cursorKey = const "ids"
-
--- | Phantom type to specify the key which point out the content in the response.
-data UsersCursorKey
-
-instance CursorKey UsersCursorKey where
-    cursorKey = const "users"
-
--- | Phantom type to specify the key which point out the content in the response.
-data ListsCursorKey
-
-instance CursorKey ListsCursorKey where
-    cursorKey = const "lists"
-
-data EventsCursorKey
-instance CursorKey EventsCursorKey where
-    cursorKey = const "events"
+type IdsCursorKey = "ids"
+type UsersCursorKey = "users"
+type ListsCursorKey = "lists"
+type EventsCursorKey = "events"
 
 -- | A wrapper for API responses which have "next_cursor" field.
 --
 -- The first type parameter of 'WithCursor' specifies the field name of contents.
 --
--- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 1234567890, \"ids\": [1111111111]}" :: Maybe (WithCursor Integer IdsCursorKey UserId)
+-- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 1234567890, \"ids\": [1111111111]}" :: Maybe (WithCursor Integer "ids" UserId)
 -- >>> nextCursor res
 -- Just 1234567890
 -- >>> contents res
 -- [1111111111]
 --
--- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 0, \"users\": [1000]}" :: Maybe (WithCursor Integer UsersCursorKey UserId)
+-- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 0, \"users\": [1000]}" :: Maybe (WithCursor Integer "users" UserId)
 -- >>> nextCursor res
 -- Just 0
 -- >>> contents res
 -- [1000]
 --
--- >>> let Just res = decode "{\"next_cursor\": \"hogehoge\", \"events\": [1000]}" :: Maybe (WithCursor Text EventsCursorKey UserId)
+-- >>> let Just res = decode "{\"next_cursor\": \"hogehoge\", \"events\": [1000]}" :: Maybe (WithCursor Text "events" UserId)
 -- >>> nextCursor res
 -- Just "hogehoge"
 -- >>> contents res
 -- [1000]
-data WithCursor cursorType cursorKey wrapped = WithCursor
+data WithCursor cursorType (cursorKey :: Symbol) wrapped = WithCursor
     { previousCursor :: Maybe cursorType
     , nextCursor :: Maybe cursorType
     , contents :: [wrapped]
     }
-    deriving (Show)
+    deriving (Show, Eq, Generic, Generic1, Functor, Foldable, Traversable)
 
-instance
-    (FromJSON wrapped, FromJSON ct, CursorKey c) =>
-    FromJSON (WithCursor ct c wrapped)
-    where
-    parseJSON (Object o) =
-        checkError o
-            >> WithCursor <$> o .:? "previous_cursor"
-            <*> o .:? "next_cursor"
-            <*> o .: cursorKey (undefined :: c)
-    parseJSON _ = mempty
+instance (KnownSymbol cursorKey, FromJSON cursorType) => FromJSON1 (WithCursor cursorType cursorKey) where
+    liftParseJSON _ lp =
+        withObject ("WithCursor \"" ++ cursorKeyStr ++ "\"") $ \obj ->
+            WithCursor <$> obj .:? "previous_cursor"
+                <*> obj .:? "next_cursor"
+                <*> (obj .: fromString cursorKeyStr >>= lp)
+      where
+        cursorKeyStr = symbolVal (Proxy :: Proxy cursorKey)
+
+instance (KnownSymbol cursorKey, FromJSON cursorType, FromJSON wrapped) => FromJSON (WithCursor cursorType cursorKey wrapped) where
+    parseJSON = parseJSON1
+
+instance (NFData cursorType, NFData wrapped) => NFData (WithCursor cursorType cursorKey wrapped)
diff --git a/Web/Twitter/Conduit/Lens.hs b/Web/Twitter/Conduit/Lens.hs
--- a/Web/Twitter/Conduit/Lens.hs
+++ b/Web/Twitter/Conduit/Lens.hs
@@ -20,10 +20,6 @@
 
     -- * Re-exports
     TT.TwitterError (..),
-    TT.CursorKey (..),
-    TT.IdsCursorKey,
-    TT.UsersCursorKey,
-    TT.ListsCursorKey,
 ) where
 
 import Control.Lens
diff --git a/Web/Twitter/Conduit/Request/Internal.hs b/Web/Twitter/Conduit/Request/Internal.hs
--- a/Web/Twitter/Conduit/Request/Internal.hs
+++ b/Web/Twitter/Conduit/Request/Internal.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -96,7 +95,6 @@
     replace k Nothing = dropAssoc k
     dropAssoc k = filter ((/= k) . fst)
 
-{- ORMOLU_DISABLE -}
 instance
     ( Parameters req
     , ParameterValue a
@@ -105,13 +103,8 @@
     , Functor f
     , lens ~ ((Maybe a -> f (Maybe a)) -> req -> f req)
     ) =>
-    IsLabel label lens where
-
-#if MIN_VERSION_base(4, 10, 0)
+    IsLabel label lens
+    where
     fromLabel = rawParam key
-#else
-    fromLabel _ = rawParam key
-#endif
       where
         key = S8.pack (symbolVal (Proxy :: Proxy label))
-{- ORMOLU_ENABLE -}
diff --git a/Web/Twitter/Conduit/Status.hs b/Web/Twitter/Conduit/Status.hs
--- a/Web/Twitter/Conduit/Status.hs
+++ b/Web/Twitter/Conduit/Status.hs
@@ -1,323 +1,75 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeOperators #-}
-
 module Web.Twitter.Conduit.Status (
+    -- * Notice
+    -- $notice
+
     -- * Timelines
-    StatusesMentionsTimeline,
     mentionsTimeline,
-    StatusesUserTimeline,
     userTimeline,
-    StatusesHomeTimeline,
     homeTimeline,
-    StatusesRetweetsOfMe,
     retweetsOfMe,
 
     -- * Tweets
-    StatusesRetweetsId,
     retweetsId,
-    StatusesShowId,
     showId,
-    StatusesDestroyId,
     destroyId,
-    StatusesUpdate,
     update,
-    StatusesRetweetId,
     retweetId,
-    MediaData (..),
-    StatusesUpdateWithMedia,
     updateWithMedia,
-    -- , oembed
-    -- , retweetersIds
-    StatusesLookup,
     lookup,
 ) where
 
-import Web.Twitter.Conduit.Base
+import Data.Text (Text)
+import Web.Twitter.Conduit.Api
 import Web.Twitter.Conduit.Parameters
 import Web.Twitter.Conduit.Request
-import Web.Twitter.Conduit.Request.Internal
 import Web.Twitter.Types
-import Prelude hiding (lookup)
 
-import Data.Default
-import qualified Data.Text as T
-import Network.HTTP.Client.MultipartFormData
-
--- $setup
--- >>> :set -XOverloadedStrings -XOverloadedLabels
--- >>> import Control.Lens
-
--- * Timelines
+import Prelude hiding (lookup)
 
--- | Returns query data asks the most recent mentions for the authenticating user.
---
--- You can perform a query using 'call':
---
--- @
--- res <- 'call' 'mentionsTimeline'
--- @
+-- $notice
 --
--- >>> mentionsTimeline
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/mentions_timeline.json" []
-mentionsTimeline :: APIRequest StatusesMentionsTimeline [Status]
-mentionsTimeline = APIRequest "GET" (endpoint ++ "statuses/mentions_timeline.json") def
+-- This module provides aliases of statuses API, for backward compatibility.
 
-type StatusesMentionsTimeline =
-    '[ "count" ':= Integer
-     , "since_id" ':= Integer
-     , "max_id" ':= Integer
-     , "trim_user" ':= Bool
-     , "contributor_details" ':= Bool
-     , "include_entities" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+mentionsTimeline :: APIRequest StatusesMentionsTimeline [Status]
+mentionsTimeline = statusesMentionsTimeline
+{-# DEPRECATED mentionsTimeline "Please use Web.Twitter.Conduit.API.statusesMentionsTimeline" #-}
 
--- | Returns query data asks a collection of the most recent Tweets posted by the user indicated by the screen_name or user_id parameters.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' $ 'userTimeline' ('ScreenNameParam' \"thimura\")
--- @
---
--- >>> userTimeline (ScreenNameParam "thimura")
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/user_timeline.json" [("screen_name","thimura")]
--- >>> userTimeline (ScreenNameParam "thimura") & #include_rts ?~ True & #count ?~ 200
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/user_timeline.json" [("count","200"),("include_rts","true"),("screen_name","thimura")]
 userTimeline :: UserParam -> APIRequest StatusesUserTimeline [Status]
-userTimeline q = APIRequest "GET" (endpoint ++ "statuses/user_timeline.json") (mkUserParam q)
-
-type StatusesUserTimeline =
-    '[ "count" ':= Integer
-     , "since_id" ':= Integer
-     , "max_id" ':= Integer
-     , "trim_user" ':= Bool
-     , "exclude_replies" ':= Bool
-     , "contributor_details" ':= Bool
-     , "include_rts" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+userTimeline = statusesUserTimeline
+{-# DEPRECATED userTimeline "Please use Web.Twitter.Conduit.API.statusesUserTimeline" #-}
 
--- | Returns query data asks a collection of the most recentTweets and retweets posted by the authenticating user and the users they follow.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' 'homeTimeline'
--- @
---
--- >>> homeTimeline
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" []
--- >>> homeTimeline & #count ?~ 200
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" [("count","200")]
 homeTimeline :: APIRequest StatusesHomeTimeline [Status]
-homeTimeline = APIRequest "GET" (endpoint ++ "statuses/home_timeline.json") def
-
-type StatusesHomeTimeline =
-    '[ "count" ':= Integer
-     , "since_id" ':= Integer
-     , "max_id" ':= Integer
-     , "trim_user" ':= Bool
-     , "exclude_replies" ':= Bool
-     , "contributor_details" ':= Bool
-     , "include_entities" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+homeTimeline = statusesHomeTimeline
+{-# DEPRECATED homeTimeline "Please use Web.Twitter.Conduit.API.statusesHomeTimeline" #-}
 
--- | Returns query data asks the most recent tweets authored by the authenticating user that have been retweeted by others.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' 'retweetsOfMe'
--- @
---
--- >>> retweetsOfMe
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" []
--- >>> retweetsOfMe & #count ?~ 100
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" [("count","100")]
 retweetsOfMe :: APIRequest StatusesRetweetsOfMe [Status]
-retweetsOfMe = APIRequest "GET" (endpoint ++ "statuses/retweets_of_me.json") def
-
-type StatusesRetweetsOfMe =
-    '[ "count" ':= Integer
-     , "since_id" ':= Integer
-     , "max_id" ':= Integer
-     , "trim_user" ':= Bool
-     , "include_entities" ':= Bool
-     , "include_user_entities" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
-
--- * Tweets
+retweetsOfMe = statusesRetweetsOfMe
+{-# DEPRECATED retweetsOfMe "Please use Web.Twitter.Conduit.API.statusesRetweetsOfMe" #-}
 
--- | Returns query data that asks for the most recent retweets of the specified tweet
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'retweetsId' 1234567890
--- @
---
--- >>> retweetsId 1234567890
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" []
--- >>> retweetsId 1234567890 & #count ?~ 100
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" [("count","100")]
 retweetsId :: StatusId -> APIRequest StatusesRetweetsId [RetweetedStatus]
-retweetsId status_id = APIRequest "GET" uri def
-  where
-    uri = endpoint ++ "statuses/retweets/" ++ show status_id ++ ".json"
-
-type StatusesRetweetsId =
-    '[ "count" ':= Integer
-     , "trim_user" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+retweetsId = statusesRetweetsId
+{-# DEPRECATED retweetsId "Please use Web.Twitter.Conduit.API.statusesRetweetsId" #-}
 
--- | Returns query data asks a single Tweet, specified by the id parameter.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'showId' 1234567890
--- @
---
--- >>> showId 1234567890
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/show/1234567890.json" []
--- >>> showId 1234567890 & #include_my_retweet ?~ True
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/show/1234567890.json" [("include_my_retweet","true")]
 showId :: StatusId -> APIRequest StatusesShowId Status
-showId status_id = APIRequest "GET" uri def
-  where
-    uri = endpoint ++ "statuses/show/" ++ show status_id ++ ".json"
-
-type StatusesShowId =
-    '[ "trim_user" ':= Bool
-     , "include_my_retweet" ':= Bool
-     , "include_entities" ':= Bool
-     , "include_ext_alt_text" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+showId = statusesShowId
+{-# DEPRECATED showId "Please use Web.Twitter.Conduit.API.statusesShowId" #-}
 
--- | Returns post data which destroys the status specified by the require ID parameter.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'destroyId' 1234567890
--- @
---
--- >>> destroyId 1234567890
--- APIRequest "POST" "https://api.twitter.com/1.1/statuses/destroy/1234567890.json" []
 destroyId :: StatusId -> APIRequest StatusesDestroyId Status
-destroyId status_id = APIRequest "POST" uri def
-  where
-    uri = endpoint ++ "statuses/destroy/" ++ show status_id ++ ".json"
-
-type StatusesDestroyId =
-    '[ "trim_user" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
-
--- | Returns post data which updates the authenticating user's current status.
--- To upload an image to accompany the tweet, use 'updateWithMedia'.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'update' \"Hello World\"
--- @
---
--- >>> update "Hello World"
--- APIRequest "POST" "https://api.twitter.com/1.1/statuses/update.json" [("status","Hello World")]
--- >>> update "Hello World" & #in_reply_to_status_id ?~ 1234567890
--- APIRequest "POST" "https://api.twitter.com/1.1/statuses/update.json" [("in_reply_to_status_id","1234567890"),("status","Hello World")]
-update :: T.Text -> APIRequest StatusesUpdate Status
-update status = APIRequest "POST" uri [("status", PVString status)]
-  where
-    uri = endpoint ++ "statuses/update.json"
+destroyId = statusesDestroyId
+{-# DEPRECATED destroyId "Please use Web.Twitter.Conduit.API.statusesDestroyId" #-}
 
-type StatusesUpdate =
-    '[ "in_reply_to_status_id" ':= Integer
-     , -- , "lat_long"
-       -- , "place_id"
-       "display_coordinates" ':= Bool
-     , "trim_user" ':= Bool
-     , "media_ids" ':= [Integer]
-     , "tweet_mode" ':= TweetMode
-     ]
+update :: Text -> APIRequest StatusesUpdate Status
+update = statusesUpdate
+{-# DEPRECATED update "Please use Web.Twitter.Conduit.API.statusesUpdate" #-}
 
--- | Returns post data which retweets a tweet, specified by ID.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'retweetId' 1234567890
--- @
---
--- >>> retweetId 1234567890
--- APIRequest "POST" "https://api.twitter.com/1.1/statuses/retweet/1234567890.json" []
 retweetId :: StatusId -> APIRequest StatusesRetweetId RetweetedStatus
-retweetId status_id = APIRequest "POST" uri def
-  where
-    uri = endpoint ++ "statuses/retweet/" ++ show status_id ++ ".json"
-
-type StatusesRetweetId =
-    '[ "trim_user" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
-
--- | Returns post data which updates the authenticating user's current status and attaches media for upload.
---
--- You can perform a search query using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'updateWithMedia' \"Hello World\" ('MediaFromFile' \"/home/thimura/test.jpeg\")
--- @
---
--- >>> updateWithMedia "Hello World" (MediaFromFile "/home/fuga/test.jpeg")
--- APIRequestMultipart "POST" "https://api.twitter.com/1.1/statuses/update_with_media.json" [("status","Hello World")]
-updateWithMedia ::
-    T.Text ->
-    MediaData ->
-    APIRequest StatusesUpdateWithMedia Status
-updateWithMedia tweet mediaData =
-    APIRequestMultipart "POST" uri [("status", PVString tweet)] [mediaBody mediaData]
-  where
-    uri = endpoint ++ "statuses/update_with_media.json"
-    mediaBody (MediaFromFile fp) = partFileSource "media[]" fp
-    mediaBody (MediaRequestBody filename filebody) = partFileRequestBody "media[]" filename filebody
+retweetId = statusesRetweetId
+{-# DEPRECATED retweetId "Please use Web.Twitter.Conduit.API.statusesRetweetId" #-}
 
-type StatusesUpdateWithMedia =
-    '[ "possibly_sensitive" ':= Bool
-     , "in_reply_to_status_id" ':= Integer
-     , -- , "lat_long"
-       -- , "place_id"
-       "display_coordinates" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+updateWithMedia :: Text -> MediaData -> APIRequest StatusesUpdateWithMedia Status
+updateWithMedia = statusesUpdateWithMedia
+{-# DEPRECATED updateWithMedia "Please use Web.Twitter.Conduit.API.statusesUpdateWithMedia" #-}
 
--- | Returns fully-hydrated tweet objects for up to 100 tweets per request, as specified by comma-separated values passed to the id parameter.
---
--- You can perform a request using 'call':
---
--- @
--- res <- 'call' twInfo mgr '$' 'lookup' [20, 432656548536401920]
--- @
---
--- >>> lookup [10]
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10")]
--- >>> lookup [10, 432656548536401920]
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10,432656548536401920")]
--- >>> lookup [10, 432656548536401920] & #include_entities ?~ True
--- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("include_entities","true"),("id","10,432656548536401920")]
 lookup :: [StatusId] -> APIRequest StatusesLookup [Status]
-lookup ids = APIRequest "GET" (endpoint ++ "statuses/lookup.json") [("id", PVIntegerArray ids)]
-
-type StatusesLookup =
-    '[ "include_entities" ':= Bool
-     , "trim_user" ':= Bool
-     , "map" ':= Bool
-     , "tweet_mode" ':= TweetMode
-     ]
+lookup = statusesLookup
+{-# DEPRECATED lookup "Please use Web.Twitter.Conduit.API.statusesLookup" #-}
diff --git a/tests/ApiSpec.hs b/tests/ApiSpec.hs
--- a/tests/ApiSpec.hs
+++ b/tests/ApiSpec.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedLabels #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module ApiSpec where
@@ -6,17 +7,17 @@
 import Control.Lens
 import Data.Conduit
 import qualified Data.Conduit.List as CL
+import Data.Time
 import Network.HTTP.Conduit
 import System.IO.Unsafe
+import Test.Hspec
 import TestUtils
-import Web.Twitter.Conduit (TWInfo, call, sourceWithCursor)
+import Web.Twitter.Conduit (TWInfo, accountVerifyCredentials, call, sourceWithCursor, sourceWithMaxId)
 import Web.Twitter.Conduit.Api
 import Web.Twitter.Conduit.Lens
 import qualified Web.Twitter.Conduit.Parameters as Param
 import Web.Twitter.Types.Lens
 
-import Test.Hspec
-
 twInfo :: TWInfo
 twInfo = unsafePerformIO getTWInfo
 
@@ -24,6 +25,10 @@
 mgr = unsafePerformIO $ newManager tlsManagerSettings
 {-# NOINLINE mgr #-}
 
+self :: User
+self = unsafePerformIO $ call twInfo mgr $ accountVerifyCredentials
+{-# NOINLINE self #-}
+
 spec :: Spec
 spec = do
     unit
@@ -37,6 +42,70 @@
 
 integrated :: Spec
 integrated = do
+    describe "mentionsTimeline" $ do
+        it "returns the 20 most recent mentions for user" $ do
+            res <- call twInfo mgr statusesMentionsTimeline
+            length res `shouldSatisfy` (> 0)
+            let mentionsScreenName = res ^.. traversed . statusEntities . _Just . enUserMentions . traversed . entityBody . userEntityUserScreenName
+            mentionsScreenName `shouldSatisfy` allOf folded (== (self ^. userScreenName))
+            length mentionsScreenName `shouldSatisfy` (== length res)
+
+    describe "userTimeline" $ do
+        it "returns the 20 most recent tweets posted by the user indicated by ScreenNameParam" $ do
+            res <- call twInfo mgr $ statusesUserTimeline (Param.ScreenNameParam "thimura")
+            length res `shouldSatisfy` (== 20)
+            res `shouldSatisfy` (allOf folded (^. statusUser . userScreenName . to (== "thimura")))
+        it "returns the recent tweets which include RTs when specified include_rts option" $ do
+            res <-
+                call twInfo mgr $
+                    statusesUserTimeline (Param.ScreenNameParam "thimura")
+                        & #count ?~ 100
+                        & #include_rts ?~ True
+            res `shouldSatisfy` (anyOf (folded . statusRetweetedStatus . _Just . statusUser . userScreenName) (/= "thimura"))
+        it "iterate with sourceWithMaxId" $ do
+            let src =
+                    sourceWithMaxId twInfo mgr $
+                        statusesUserTimeline (Param.ScreenNameParam "thimura") & #count ?~ 200
+            tl <- runConduit $ src .| CL.isolate 600 .| CL.consume
+            length tl `shouldSatisfy` (== 600)
+
+            let ids = tl ^.. traversed . statusId
+            zip ids (tail ids) `shouldSatisfy` all (\(a, b) -> a > b)
+
+    describe "homeTimeline" $ do
+        it "returns the most recent tweets in home timeline" $ do
+            res <- call twInfo mgr statusesHomeTimeline
+            length res `shouldSatisfy` (> 0)
+
+    describe "showId" $ do
+        it "works for the known tweets" $ do
+            res <- call twInfo mgr $ statusesShowId 477833886768959488
+            res ^. statusId `shouldBe` 477833886768959488
+            res ^. statusText `shouldBe` "真紅かわいいはアレセイア"
+            res ^. statusCreatedAt `shouldBe` UTCTime (fromGregorian 2014 6 14) (secondsToDiffTime 55450)
+            res ^. statusUser . userScreenName `shouldBe` "thimura"
+
+    describe "update & destroyId" $ do
+        it "posts new tweet and destroy it" $ do
+            res1 <- call twInfo mgr $ statusesUpdate "おまえの明日が、今日よりもずっと、楽しい事で溢れているようにと、祈っているよ"
+            res1 ^. statusUser . userScreenName `shouldBe` self ^. userScreenName
+
+            res2 <- call twInfo mgr $ statusesDestroyId (res1 ^. statusId)
+            res2 ^. statusId `shouldBe` res1 ^. statusId
+
+    describe "lookup" $ do
+        it "works for the known tweets" $ do
+            res <- call twInfo mgr $ statusesLookup [438691466345340928, 477757405942411265]
+            length res `shouldSatisfy` (== 2)
+            (res !! 0) ^. statusId `shouldBe` 438691466345340928
+            (res !! 1) ^. statusId `shouldBe` 477757405942411265
+
+        it "handles extended tweets" $ do
+            res <- call twInfo mgr $ statusesLookup [1128358947772145672]
+            (res !! 0) ^. statusText `shouldBe` "Through the Twitter Developer Labs program, we'll soon preview new versions of GET /tweets and GET /users, followed\8230 https://t.co/9i4c5bUUCu"
+            res <- call twInfo mgr $ statusesLookup [1128358947772145672] & #tweet_mode ?~ Param.Extended
+            (res !! 0) ^. statusText `shouldBe` "Through the Twitter Developer Labs program, we'll soon preview new versions of GET /tweets and GET /users, followed by Tweet streaming, search &amp; metrics. More to come! \128073 https://t.co/rDE48yNiSw https://t.co/oFsvkpnDhS"
+
     describe "friendsIds" $ do
         it "returns a cursored collection of users IDs" $ do
             res <- call twInfo mgr $ friendsIds (Param.ScreenNameParam "thimura")
@@ -44,7 +113,7 @@
 
         it "iterate with sourceWithCursor" $ do
             let src = sourceWithCursor twInfo mgr $ friendsIds (Param.ScreenNameParam "thimura")
-            friends <- src $$ CL.consume
+            friends <- runConduit $ src .| CL.consume
             length friends `shouldSatisfy` (>= 0)
 
     describe "listsMembers" $ do
@@ -58,5 +127,5 @@
 
         it "iterate with sourceWithCursor" $ do
             let src = sourceWithCursor twInfo mgr $ listsMembers (Param.ListNameParam "thimura/haskell")
-            members <- src $$ CL.consume
+            members <- runConduit $ src .| CL.consume
             members ^.. traversed . userScreenName `shouldContain` ["Hackage"]
diff --git a/tests/StatusSpec.hs b/tests/StatusSpec.hs
deleted file mode 100644
--- a/tests/StatusSpec.hs
+++ /dev/null
@@ -1,107 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedLabels #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module StatusSpec where
-
-import Control.Lens
-import Data.Conduit
-import qualified Data.Conduit.List as CL
-import Data.Time
-import Network.HTTP.Conduit
-import System.IO.Unsafe
-import Web.Twitter.Conduit (TWInfo, accountVerifyCredentials, call, sourceWithMaxId)
-import qualified Web.Twitter.Conduit.Parameters as Param
-import Web.Twitter.Conduit.Status as Status
-import Web.Twitter.Types.Lens
-
-import Test.Hspec
-import TestUtils
-
-twInfo :: TWInfo
-twInfo = unsafePerformIO getTWInfo
-
-mgr :: Manager
-mgr = unsafePerformIO $ newManager tlsManagerSettings
-{-# NOINLINE mgr #-}
-
-self :: User
-self = unsafePerformIO $ call twInfo mgr $ accountVerifyCredentials
-{-# NOINLINE self #-}
-
-spec :: Spec
-spec = do
-    unit
-
-#ifdef RUN_INTEGRATED_TEST
-    integrated
-#endif
-
-unit :: Spec
-unit = return ()
-
-integrated :: Spec
-integrated = do
-    describe "mentionsTimeline" $ do
-        it "returns the 20 most recent mentions for user" $ do
-            res <- call twInfo mgr mentionsTimeline
-            length res `shouldSatisfy` (> 0)
-            let mentionsScreenName = res ^.. traversed . statusEntities . _Just . enUserMentions . traversed . entityBody . userEntityUserScreenName
-            mentionsScreenName `shouldSatisfy` allOf folded (== (self ^. userScreenName))
-            length mentionsScreenName `shouldSatisfy` (== length res)
-
-    describe "userTimeline" $ do
-        it "returns the 20 most recent tweets posted by the user indicated by ScreenNameParam" $ do
-            res <- call twInfo mgr $ userTimeline (Param.ScreenNameParam "thimura")
-            length res `shouldSatisfy` (== 20)
-            res `shouldSatisfy` (allOf folded (^. statusUser . userScreenName . to (== "thimura")))
-        it "returns the recent tweets which include RTs when specified include_rts option" $ do
-            res <-
-                call twInfo mgr $
-                    userTimeline (Param.ScreenNameParam "thimura")
-                        & #count ?~ 100
-                        & #include_rts ?~ True
-            res `shouldSatisfy` (anyOf (folded . statusRetweetedStatus . _Just . statusUser . userScreenName) (/= "thimura"))
-        it "iterate with sourceWithMaxId" $ do
-            let src =
-                    sourceWithMaxId twInfo mgr $
-                        userTimeline (Param.ScreenNameParam "thimura") & #count ?~ 200
-            tl <- src $$ CL.isolate 600 =$ CL.consume
-            length tl `shouldSatisfy` (== 600)
-
-            let ids = tl ^.. traversed . statusId
-            zip ids (tail ids) `shouldSatisfy` all (\(a, b) -> a > b)
-
-    describe "homeTimeline" $ do
-        it "returns the most recent tweets in home timeline" $ do
-            res <- call twInfo mgr homeTimeline
-            length res `shouldSatisfy` (> 0)
-
-    describe "showId" $ do
-        it "works for the known tweets" $ do
-            res <- call twInfo mgr $ showId 477833886768959488
-            res ^. statusId `shouldBe` 477833886768959488
-            res ^. statusText `shouldBe` "真紅かわいいはアレセイア"
-            res ^. statusCreatedAt `shouldBe` UTCTime (fromGregorian 2014 6 14) (secondsToDiffTime 55450)
-            res ^. statusUser . userScreenName `shouldBe` "thimura"
-
-    describe "update & destroyId" $ do
-        it "posts new tweet and destroy it" $ do
-            res1 <- call twInfo mgr $ update "おまえの明日が、今日よりもずっと、楽しい事で溢れているようにと、祈っているよ"
-            res1 ^. statusUser . userScreenName `shouldBe` self ^. userScreenName
-
-            res2 <- call twInfo mgr $ destroyId (res1 ^. statusId)
-            res2 ^. statusId `shouldBe` res1 ^. statusId
-
-    describe "lookup" $ do
-        it "works for the known tweets" $ do
-            res <- call twInfo mgr $ Status.lookup [438691466345340928, 477757405942411265]
-            length res `shouldSatisfy` (== 2)
-            (res !! 0) ^. statusId `shouldBe` 438691466345340928
-            (res !! 1) ^. statusId `shouldBe` 477757405942411265
-
-        it "handles extended tweets" $ do
-            res <- call twInfo mgr $ Status.lookup [1128358947772145672]
-            (res !! 0) ^. statusText `shouldBe` "Through the Twitter Developer Labs program, we'll soon preview new versions of GET /tweets and GET /users, followed\8230 https://t.co/9i4c5bUUCu"
-            res <- call twInfo mgr $ Status.lookup [1128358947772145672] & #tweet_mode ?~ Param.Extended
-            (res !! 0) ^. statusText `shouldBe` "Through the Twitter Developer Labs program, we'll soon preview new versions of GET /tweets and GET /users, followed by Tweet streaming, search &amp; metrics. More to come! \128073 https://t.co/rDE48yNiSw https://t.co/oFsvkpnDhS"
diff --git a/twitter-conduit.cabal b/twitter-conduit.cabal
--- a/twitter-conduit.cabal
+++ b/twitter-conduit.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.24
 name:               twitter-conduit
-version:            0.6.0
+version:            0.6.1
 license:            BSD3
 license-file:       LICENSE
 maintainer:         Takahiro HIMURA <taka@himura.jp>
@@ -66,7 +66,7 @@
     default-language: Haskell2010
     ghc-options:      -Wall
     build-depends:
-        base >=4.9 && <5,
+        base >=4.12 && <5,
         aeson >=0.7.0.5,
         attoparsec >=0.10,
         authenticate-oauth >=1.3,
@@ -75,6 +75,7 @@
         conduit-extra >=1.3,
         containers,
         data-default >=0.3,
+        deepseq,
         exceptions >=0.5,
         ghc-prim,
         http-client >=0.5.0,
@@ -107,7 +108,6 @@
         Spec
         ApiSpec
         BaseSpec
-        StatusSpec
         TestUtils
 
     default-language:   Haskell2010
