diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,102 +1,145 @@
 # This Travis job script has been generated by a script via
 #
-#   make_travis_yml_2.hs 'twitter-conduit.cabal'
+#   haskell-ci 'twitter-conduit.cabal' '-o' '.travis.yml'
 #
-# For more information, see https://github.com/hvr/multi-ghc-travis
+# For more information, see https://github.com/haskell-CI/haskell-ci
 #
+# version: 0.3.20190521
+#
 language: c
-sudo: false
-
+dist: xenial
 git:
-  submodules: false  # whether to recursively clone submodules
-
+  # whether to recursively clone submodules
+  submodules: false
 cache:
   directories:
     - $HOME/.cabal/packages
     - $HOME/.cabal/store
-
 before_cache:
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log
   # remove files that are regenerated by 'cabal update'
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
-
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar
+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx
+  - rm -rfv $CABALHOME/packages/head.hackage
 matrix:
   include:
-    - compiler: "ghc-7.8.4"
-    # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.8.4], sources: [hvr-ghc]}}
-    - compiler: "ghc-7.10.3"
-    # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.10.3], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.0.2"
-    # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.0.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.2.2"
-    # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.2], sources: [hvr-ghc]}}
-    - compiler: "ghc-8.4.3"
-    # env: TEST=--disable-tests BENCH=--disable-benchmarks
-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.4.3], sources: [hvr-ghc]}}
-
+    - compiler: ghc-8.6.5
+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-2.4"]}}
+    - compiler: ghc-8.4.4
+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-2.4"]}}
+    - compiler: ghc-8.2.2
+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-2.4"]}}
+    - compiler: ghc-8.0.2
+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-2.4"]}}
 before_install:
- - HC=${CC}
- - HCPKG=${HC/ghc/ghc-pkg}
- - unset CC
- - PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$PATH
- - PKGNAME='twitter-conduit'
-
+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')
+  - HCPKG="$HC-pkg"
+  - unset CC
+  - CABAL=/opt/ghc/bin/cabal
+  - CABALHOME=$HOME/.cabal
+  - export PATH="$CABALHOME/bin:$PATH"
+  - TOP=$(pwd)
+  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))
+  - echo $HCNUMVER
+  - CABAL="$CABAL -vnormal+nowrap+markoutput"
+  - set -o pipefail
+  - |
+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk
+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk
+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk
+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk
+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk
+    echo '  if (state == "cabal") {'                                       >> .colorful.awk
+    echo '    print blue($0)'                                              >> .colorful.awk
+    echo '  } else {'                                                      >> .colorful.awk
+    echo '    print $0'                                                    >> .colorful.awk
+    echo '  }'                                                             >> .colorful.awk
+    echo '}'                                                               >> .colorful.awk
+  - cat .colorful.awk
+  - |
+    color_cabal_output () {
+      awk -f $TOP/.colorful.awk
+    }
+  - echo text | color_cabal_output
 install:
- - cabal --version
- - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
- - BENCH=${BENCH---enable-benchmarks}
- - TEST=${TEST---enable-tests}
- - HADDOCK=${HADDOCK-true}
- - INSTALLED=${INSTALLED-true}
- - travis_retry cabal update -v
- - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
- - rm -fv cabal.project.local
- - "echo 'packages: .' > cabal.project"
- - rm -f cabal.project.freeze
- - cabal new-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all
- - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all
-
-# Here starts the actual work to be performed for the package under test;
-# any command which exits with a non-zero exit code causes the build to fail.
+  - ${CABAL} --version
+  - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
+  - TEST=--enable-tests
+  - BENCH=--enable-benchmarks
+  - GHCHEAD=${GHCHEAD-false}
+  - rm -f $CABALHOME/config
+  - |
+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config
+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config
+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config
+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config
+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config
+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config
+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config
+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config
+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config
+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config
+    echo "install-dirs user"                            >> $CABALHOME/config
+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config
+    echo "repository hackage.haskell.org"               >> $CABALHOME/config
+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config
+  - cat $CABALHOME/config
+  - rm -fv cabal.project cabal.project.local cabal.project.freeze
+  - travis_retry ${CABAL} v2-update -v
+  # Generate cabal.project
+  - rm -rf cabal.project cabal.project.local cabal.project.freeze
+  - touch cabal.project
+  - |
+    echo 'packages: "."' >> cabal.project
+  - |
+    echo "write-ghc-environment-files: always" >> cabal.project
+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(twitter-conduit)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
+  - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi
+  - ${CABAL} v2-freeze -w ${HC} ${TEST} ${BENCH} | color_cabal_output
+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
+  - rm  cabal.project.freeze
+  - ${CABAL} v2-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all | color_cabal_output
+  - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output
 script:
- - if [ -f configure.ac ]; then autoreconf -i; fi
- - rm -rf .ghc.environment.* dist/
- - cabal sdist # test that a source-distribution can be generated
- - cd dist/
- - SRCTAR=(${PKGNAME}-*.tar.gz)
- - SRC_BASENAME="${SRCTAR/%.tar.gz}"
- - tar -xvf "./$SRC_BASENAME.tar.gz"
- - cd "$SRC_BASENAME/"
-## from here on, CWD is inside the extracted source-tarball
- - rm -fv cabal.project.local
- - "echo 'packages: .' > cabal.project"
- # this builds all libraries and executables (without tests/benchmarks)
- - rm -f cabal.project.freeze
- - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
- # this builds all libraries and executables (including tests/benchmarks)
- # - rm -rf ./dist-newstyle
-
- # Build with installed constraints for packages in global-db
- - if $INSTALLED; then
-     ${HCPKG} list --global --simple-output --names-only | sed -r 's/([a-zA-Z0-9-]+*) */--constraint=\1 installed;/g' | sed 's/;$/;all/' | xargs -d ';' cabal new-build -w ${HC} --disable-tests --disable-benchmarks;
-   else echo "Not building with installed constraints"; fi
-
- # build & run tests, build benchmarks
- - cabal new-build -w ${HC} ${TEST} ${BENCH} all
- - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} all; fi
-
- # haddock
- - rm -rf ./dist-newstyle
- - if $HADDOCK; then cabal new-haddock -w ${HC} --disable-tests --disable-benchmarks all; else echo "Skipping haddock generation";fi
+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
+  # Packaging...
+  - ${CABAL} v2-sdist all | color_cabal_output
+  # Unpacking...
+  - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
+  - cd ${DISTDIR} || false
+  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;
+  # Generate cabal.project
+  - rm -rf cabal.project cabal.project.local cabal.project.freeze
+  - touch cabal.project
+  - |
+    echo 'packages: "twitter-conduit-*/*.cabal"' >> cabal.project
+  - |
+    echo "write-ghc-environment-files: always" >> cabal.project
+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(twitter-conduit)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
+  # Building...
+  # this builds all libraries and executables (without tests/benchmarks)
+  - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks all | color_cabal_output
+  # Building with tests and benchmarks...
+  # build & run tests, build benchmarks
+  - ${CABAL} v2-build -w ${HC} ${TEST} ${BENCH} all | color_cabal_output
+  # Testing...
+  - ${CABAL} v2-test -w ${HC} ${TEST} ${BENCH} all | color_cabal_output
+  # cabal check...
+  - (cd twitter-conduit-* && ${CABAL} -vnormal check)
+  # haddock...
+  - ${CABAL} v2-haddock -w ${HC} ${TEST} ${BENCH} all | color_cabal_output
+  # Building without installed constraints for packages in global-db...
+  - rm -f cabal.project.local
+  - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks all | color_cabal_output
 
+# REGENDATA ["twitter-conduit.cabal","-o",".travis.yml"]
 # EOF
 
 notifications:
diff --git a/.travis/check-sdist.sh b/.travis/check-sdist.sh
deleted file mode 100644
--- a/.travis/check-sdist.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-BASEDIR="$PWD"
-TARGET="$1"
-DIST="$(stack path | awk '/^dist-dir/ {print $2}')"
-
-stack sdist
-
-if [ ! -f ${DIST%/}/${TARGET}-*.tar.gz ]; then
-    echo "NG: missing archive"
-    exit 1
-fi
-
-cd "$DIST"
-srctgz=(${TARGET}*.tar.gz)
-srctgz="${srctgz[0]}"
-pkgname="${srctgz%.tar.gz}"
-tar xvzf "${srctgz}"
-cd "$BASEDIR"
-NG=$(git ls-tree -r HEAD | while read perm blob hash name; do [ -e "$DIST/$pkgname/$name" ] || echo "$name"; done)
-if [ -n "$NG" ]; then
-    echo "Missing files:"
-    echo $NG
-    exit 1
-fi
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,11 @@
+## 0.4.0
+
+* Follow direct message API changes [#65](https://github.com/himura/twitter-conduit/pull/65) [#62](https://github.com/himura/twitter-conduit/pull/62)
+* Changed WithCursor type [5b9e9d7a](https://github.com/himura/twitter-conduit/commit/5b9e9d7a13d33327fe637cae8e2359a38fce92b5)
+    * Added type parameter to WithCursor to supports `Text` as the next cursor type.
+    * Changed {previous,next}Cursor in WithCursor to be optional
+* Changed APIRequest type to take HTTP Method [f25fd9b3](https://github.com/himura/twitter-conduit/commit/f25fd9b3b860032f384d01b3457ea896e596366b)
+
 ## 0.3.0
 
 * Upgrade http-conduit dependencies to:
diff --git a/Web/Twitter/Conduit.hs b/Web/Twitter/Conduit.hs
--- a/Web/Twitter/Conduit.hs
+++ b/Web/Twitter/Conduit.hs
@@ -50,34 +50,6 @@
        , Manager
        , newManager
        , tlsManagerSettings
-
-       -- * deprecated
-       , contributorDetails
-       , count
-       , cursor
-       , displayCoordinates
-       , excludeReplies
-       , filterLevel
-       , follow
-       , inReplyToStatusId
-       , includeEntities
-       , includeMyRetweet
-       , includeRts
-       , includeUserEntities
-       , lang
-       , language
-       , locale
-       , map
-       , maxId
-       , mediaIds
-       , page
-       , possiblySensitive
-       , replies
-       , sinceId
-       , skipStatus
-       , stallWarnings
-       , trimUser
-       , until
        ) where
 
 import Web.Twitter.Conduit.Api
@@ -96,8 +68,6 @@
 import Network.HTTP.Conduit (Manager, newManager, tlsManagerSettings)
 import Web.Authenticate.OAuth
 
-import Prelude hiding (map, until)
-
 -- for haddock
 import Data.Conduit
 import qualified Data.Conduit.List as CL
@@ -222,107 +192,3 @@
 --                                   , status ^. statusText
 --                                   ]
 -- @
-
-contributorDetails :: Parameters.HasContributorDetailsParam a => Lens' a (Maybe Bool)
-contributorDetails = Parameters.contributorDetails
-{-# DEPRECATED contributorDetails "Please use Web.Twitter.Conduit.Parameters.contributorDetails" #-}
-
-count :: Parameters.HasCountParam a => Lens' a (Maybe Integer)
-count = Parameters.count
-{-# DEPRECATED count "Please use Web.Twitter.Conduit.Parameters.count" #-}
-
-cursor :: Parameters.HasCursorParam a => Lens' a (Maybe Integer)
-cursor = Parameters.cursor
-{-# DEPRECATED cursor "Please use Web.Twitter.Conduit.Parameters.cursor" #-}
-
-displayCoordinates :: Parameters.HasDisplayCoordinatesParam a => Lens' a (Maybe Bool)
-displayCoordinates = Parameters.displayCoordinates
-{-# DEPRECATED displayCoordinates "Please use Web.Twitter.Conduit.Parameters.displayCoordinates" #-}
-
-excludeReplies :: Parameters.HasExcludeRepliesParam a => Lens' a (Maybe Bool)
-excludeReplies = Parameters.excludeReplies
-{-# DEPRECATED excludeReplies "Please use Web.Twitter.Conduit.Parameters.excludeReplies" #-}
-
-filterLevel :: Parameters.HasFilterLevelParam a => Lens' a (Maybe T.Text)
-filterLevel = Parameters.filterLevel
-{-# DEPRECATED filterLevel "Please use Web.Twitter.Conduit.Parameters.filterLevel" #-}
-
-follow :: Parameters.HasFollowParam a => Lens' a (Maybe Bool)
-follow = Parameters.follow
-{-# DEPRECATED follow "Please use Web.Twitter.Conduit.Parameters.follow" #-}
-
-inReplyToStatusId :: Parameters.HasInReplyToStatusIdParam a => Lens' a (Maybe Integer)
-inReplyToStatusId = Parameters.inReplyToStatusId
-{-# DEPRECATED inReplyToStatusId "Please use Web.Twitter.Conduit.Parameters.inReplyToStatusId" #-}
-
-includeEntities :: Parameters.HasIncludeEntitiesParam a => Lens' a (Maybe Bool)
-includeEntities = Parameters.includeEntities
-{-# DEPRECATED includeEntities "Please use Web.Twitter.Conduit.Parameters.includeEntities" #-}
-
-includeMyRetweet :: Parameters.HasIncludeMyRetweetParam a => Lens' a (Maybe Bool)
-includeMyRetweet = Parameters.includeMyRetweet
-{-# DEPRECATED includeMyRetweet "Please use Web.Twitter.Conduit.Parameters.includeMyRetweet" #-}
-
-includeRts :: Parameters.HasIncludeRtsParam a => Lens' a (Maybe Bool)
-includeRts = Parameters.includeRts
-{-# DEPRECATED includeRts "Please use Web.Twitter.Conduit.Parameters.includeRts" #-}
-
-includeUserEntities :: Parameters.HasIncludeUserEntitiesParam a => Lens' a (Maybe Bool)
-includeUserEntities = Parameters.includeUserEntities
-{-# DEPRECATED includeUserEntities "Please use Web.Twitter.Conduit.Parameters.includeUserEntities" #-}
-
-lang :: Parameters.HasLangParam a => Lens' a (Maybe T.Text)
-lang = Parameters.lang
-{-# DEPRECATED lang "Please use Web.Twitter.Conduit.Parameters.lang" #-}
-
-language :: Parameters.HasLanguageParam a => Lens' a (Maybe T.Text)
-language = Parameters.language
-{-# DEPRECATED language "Please use Web.Twitter.Conduit.Parameters.language" #-}
-
-locale :: Parameters.HasLocaleParam a => Lens' a (Maybe T.Text)
-locale = Parameters.locale
-{-# DEPRECATED locale "Please use Web.Twitter.Conduit.Parameters.locale" #-}
-
-map :: Parameters.HasMapParam a => Lens' a (Maybe Bool)
-map = Parameters.map
-{-# DEPRECATED map "Please use Web.Twitter.Conduit.Parameters.map" #-}
-
-maxId :: Parameters.HasMaxIdParam a => Lens' a (Maybe Integer)
-maxId = Parameters.maxId
-{-# DEPRECATED maxId "Please use Web.Twitter.Conduit.Parameters.maxId" #-}
-
-mediaIds :: Parameters.HasMediaIdsParam a => Lens' a (Maybe [Integer])
-mediaIds = Parameters.mediaIds
-{-# DEPRECATED mediaIds "Please use Web.Twitter.Conduit.Parameters.mediaIds" #-}
-
-page :: Parameters.HasPageParam a => Lens' a (Maybe Integer)
-page = Parameters.page
-{-# DEPRECATED page "Please use Web.Twitter.Conduit.Parameters.page" #-}
-
-possiblySensitive :: Parameters.HasPossiblySensitiveParam a => Lens' a (Maybe Bool)
-possiblySensitive = Parameters.possiblySensitive
-{-# DEPRECATED possiblySensitive "Please use Web.Twitter.Conduit.Parameters.possiblySensitive" #-}
-
-replies :: Parameters.HasRepliesParam a => Lens' a (Maybe T.Text)
-replies = Parameters.replies
-{-# DEPRECATED replies "Please use Web.Twitter.Conduit.Parameters.replies" #-}
-
-sinceId :: Parameters.HasSinceIdParam a => Lens' a (Maybe Integer)
-sinceId = Parameters.sinceId
-{-# DEPRECATED sinceId "Please use Web.Twitter.Conduit.Parameters.sinceId" #-}
-
-skipStatus :: Parameters.HasSkipStatusParam a => Lens' a (Maybe Bool)
-skipStatus = Parameters.skipStatus
-{-# DEPRECATED skipStatus "Please use Web.Twitter.Conduit.Parameters.skipStatus" #-}
-
-stallWarnings :: Parameters.HasStallWarningsParam a => Lens' a (Maybe Bool)
-stallWarnings = Parameters.stallWarnings
-{-# DEPRECATED stallWarnings "Please use Web.Twitter.Conduit.Parameters.stallWarnings" #-}
-
-trimUser :: Parameters.HasTrimUserParam a => Lens' a (Maybe Bool)
-trimUser = Parameters.trimUser
-{-# DEPRECATED trimUser "Please use Web.Twitter.Conduit.Parameters.trimUser" #-}
-
-until :: Parameters.HasUntilParam a => Lens' a (Maybe Day)
-until = Parameters.until
-{-# DEPRECATED until "Please use Web.Twitter.Conduit.Parameters.until" #-}
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
@@ -1,8 +1,9 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE CPP #-}
 
 module Web.Twitter.Conduit.Api
        (
@@ -153,6 +154,7 @@
 import Network.HTTP.Client.MultipartFormData
 import qualified Data.Text as T
 import Data.Default
+import Data.Aeson
 
 -- $setup
 -- >>> :set -XOverloadedStrings
@@ -169,12 +171,12 @@
 -- @
 --
 -- >>> searchTweets "search text"
--- APIRequestGet "https://api.twitter.com/1.1/search/tweets.json" [("q","search text")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/search/tweets.json" [("q","search text")]
 -- >>> searchTweets "search text" & lang ?~ "ja" & count ?~ 100
--- APIRequestGet "https://api.twitter.com/1.1/search/tweets.json" [("count","100"),("lang","ja"),("q","search text")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/search/tweets.json" [("count","100"),("lang","ja"),("q","search text")]
 searchTweets :: T.Text -- ^ search string
              -> APIRequest SearchTweets (SearchResult [Status])
-searchTweets q = APIRequestGet (endpoint ++ "search/tweets.json") [("q", PVString q)]
+searchTweets q = APIRequest "GET" (endpoint ++ "search/tweets.json") [("q", PVString q)]
 deriveHasParamInstances ''SearchTweets
     [ "lang"
     , "locale"
@@ -198,23 +200,23 @@
 -- You can perform a query using 'call':
 --
 -- @
--- res <- 'call' twInfo mgr '$' 'directMessages' '&' 'count' '?~' 100
+-- res <- 'call' twInfo mgr '$' 'directMessages' '&' 'count' '?~' 50
 -- @
 --
 -- >>> directMessages
--- APIRequestGet "https://api.twitter.com/1.1/direct_messages.json" []
--- >>> directMessages & count ?~ 100
--- APIRequestGet "https://api.twitter.com/1.1/direct_messages.json" [("count","100")]
-directMessages :: APIRequest DirectMessages [DirectMessage]
-directMessages = APIRequestGet (endpoint ++ "direct_messages.json") def
+-- APIRequest "GET" "https://api.twitter.com/1.1/direct_messages/events/list.json" []
+-- >>> directMessages & count ?~ 50
+-- APIRequest "GET" "https://api.twitter.com/1.1/direct_messages/events/list.json" [("count","50")]
+directMessages :: APIRequest DirectMessages (WithCursor T.Text EventsCursorKey DirectMessage)
+directMessages = APIRequest "GET" (endpoint ++ "direct_messages/events/list.json") def
 deriveHasParamInstances ''DirectMessages
-    [ "since_id"
-    , "max_id"
-    , "count"
+    [ "count"
     , "include_entities"
     , "skip_status"
     , "full_text"
     ]
+instance HasCursorParam (APIRequest DirectMessages a) T.Text where
+    cursor = wrappedParam "cursor" PVString unPVString
 
 data DirectMessagesSent
 -- | Returns query data which asks recent direct messages sent by the authenticating user.
@@ -226,11 +228,11 @@
 -- @
 --
 -- >>> directMessagesSent
--- APIRequestGet "https://api.twitter.com/1.1/direct_messages/sent.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/direct_messages/sent.json" []
 -- >>> directMessagesSent & count ?~ 100
--- APIRequestGet "https://api.twitter.com/1.1/direct_messages/sent.json" [("count","100")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/direct_messages/sent.json" [("count","100")]
 directMessagesSent :: APIRequest DirectMessagesSent [DirectMessage]
-directMessagesSent = APIRequestGet (endpoint ++ "direct_messages/sent.json") def
+directMessagesSent = APIRequest "GET" (endpoint ++ "direct_messages/sent.json") def
 deriveHasParamInstances ''DirectMessagesSent
     [ "since_id"
     , "max_id"
@@ -251,9 +253,9 @@
 -- @
 --
 -- >>> directMessagesShow 1234567890
--- APIRequestGet "https://api.twitter.com/1.1/direct_messages/show.json" [("id","1234567890")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/direct_messages/show.json" [("id","1234567890")]
 directMessagesShow :: StatusId -> APIRequest DirectMessagesShow DirectMessage
-directMessagesShow sId = APIRequestGet (endpoint ++ "direct_messages/show.json") [("id", PVInteger sId)]
+directMessagesShow sId = APIRequest "GET" (endpoint ++ "direct_messages/show.json") [("id", PVInteger sId)]
 deriveHasParamInstances ''DirectMessagesShow
     [ "full_text"
     ]
@@ -268,13 +270,17 @@
 -- @
 --
 -- >>> directMessagesDestroy 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/direct_messages/destroy.json" [("id","1234567890")]
-directMessagesDestroy :: StatusId -> APIRequest DirectMessagesDestroy DirectMessage
-directMessagesDestroy sId = APIRequestPost (endpoint ++ "direct_messages/destroy.json") [("id", PVInteger sId)]
-deriveHasParamInstances ''DirectMessagesDestroy
-    [ "include_entities"
-    ]
+-- APIRequest "DELETE" "https://api.twitter.com/1.1/direct_messages/events/destroy.json" [("id","1234567890")]
+directMessagesDestroy :: StatusId -> APIRequest DirectMessagesDestroy NoContent
+directMessagesDestroy sId = APIRequest "DELETE" (endpoint ++ "direct_messages/events/destroy.json") [("id", PVInteger sId)]
 
+newtype DirectMessagesNewResponse = DirectMessagesNewResponse
+    { directMessageBody :: DirectMessage
+    } deriving (Show, Eq)
+
+instance FromJSON DirectMessagesNewResponse where
+    parseJSON = withObject "DirectMessagesNewResponse" $ \o -> DirectMessagesNewResponse <$> o .: "event"
+
 data DirectMessagesNew
 -- | Returns post data which sends a new direct message to the specified user from the authenticating user.
 --
@@ -284,13 +290,27 @@
 -- res <- 'call' twInfo mgr '$' 'directMessagesNew' (ScreenNameParam \"thimura\") \"Hello DM\"
 -- @
 --
--- >>> directMessagesNew (ScreenNameParam "thimura") "Hello DM"
--- APIRequestPost "https://api.twitter.com/1.1/direct_messages/new.json" [("text","Hello DM"),("screen_name","thimura")]
--- >>> directMessagesNew (UserIdParam 69179963) "Hello thimura! by UserId"
--- APIRequestPost "https://api.twitter.com/1.1/direct_messages/new.json" [("text","Hello thimura! by UserId"),("user_id","69179963")]
-directMessagesNew :: UserParam -> T.Text -> APIRequest DirectMessagesNew DirectMessage
-directMessagesNew q msg = APIRequestPost (endpoint ++ "direct_messages/new.json") (("text", PVString msg):mkUserParam q)
+-- >>> directMessagesNew 69179963 "Hello thimura! by UserId"
+-- APIRequestJSON "POST" "https://api.twitter.com/1.1/direct_messages/events/new.json" []
+directMessagesNew :: RecipientId -> T.Text -> APIRequest DirectMessagesNew DirectMessagesNewResponse
+directMessagesNew up msg =
+    APIRequestJSON "POST" (endpoint ++ "direct_messages/events/new.json") [] body
+  where
+    body =
+        object
+            [ "event" .=
+              object
+                  [ "type" .= ("message_create" :: String)
+                  , "message_create" .=
+                    object
+                        [ "target" .= object ["recipient_id" .= up]
+                        , "message_data" .= object ["text" .= msg]
+                        ]
+                  ]
+            ]
 
+type RecipientId = Integer
+
 data FriendshipsNoRetweetsIds
 -- | Returns a collection of user_ids that the currently authenticated user does not want to receive retweets from.
 --
@@ -301,9 +321,9 @@
 -- @
 --
 -- >>> friendshipsNoRetweetsIds
--- APIRequestGet "https://api.twitter.com/1.1/friendships/no_retweets/ids.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/friendships/no_retweets/ids.json" []
 friendshipsNoRetweetsIds :: APIRequest FriendshipsNoRetweetsIds [UserId]
-friendshipsNoRetweetsIds = APIRequestGet (endpoint ++ "friendships/no_retweets/ids.json") []
+friendshipsNoRetweetsIds = APIRequest "GET" (endpoint ++ "friendships/no_retweets/ids.json") []
 
 data FriendsIds
 -- | Returns query data which asks a collection of user IDs for every user the specified user is following.
@@ -321,16 +341,16 @@
 -- @
 --
 -- >>> friendsIds (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/friends/ids.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/friends/ids.json" [("screen_name","thimura")]
 -- >>> friendsIds (ScreenNameParam "thimura") & count ?~ 5000
--- APIRequestGet "https://api.twitter.com/1.1/friends/ids.json" [("count","5000"),("screen_name","thimura")]
-friendsIds :: UserParam -> APIRequest FriendsIds (WithCursor IdsCursorKey UserId)
-friendsIds q = APIRequestGet (endpoint ++ "friends/ids.json") (mkUserParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/friends/ids.json" [("count","5000"),("screen_name","thimura")]
+friendsIds :: UserParam -> APIRequest FriendsIds (WithCursor Integer IdsCursorKey UserId)
+friendsIds q = APIRequest "GET" (endpoint ++ "friends/ids.json") (mkUserParam q)
 deriveHasParamInstances ''FriendsIds
-    [ "cursor"
-    -- , "stringify_ids" -- (needless)
-    , "count"
+    [ "count"
     ]
+instance HasCursorParam (APIRequest FriendsIds a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data FollowersIds
 -- | Returns query data which asks a collection of user IDs for every user following the specified user.
@@ -348,16 +368,16 @@
 -- @
 --
 -- >>> followersIds (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/followers/ids.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/followers/ids.json" [("screen_name","thimura")]
 -- >>> followersIds (ScreenNameParam "thimura") & count ?~ 5000
--- APIRequestGet "https://api.twitter.com/1.1/followers/ids.json" [("count","5000"),("screen_name","thimura")]
-followersIds :: UserParam -> APIRequest FollowersIds (WithCursor IdsCursorKey UserId)
-followersIds q = APIRequestGet (endpoint ++ "followers/ids.json") (mkUserParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/followers/ids.json" [("count","5000"),("screen_name","thimura")]
+followersIds :: UserParam -> APIRequest FollowersIds (WithCursor Integer IdsCursorKey UserId)
+followersIds q = APIRequest "GET" (endpoint ++ "followers/ids.json") (mkUserParam q)
 deriveHasParamInstances ''FollowersIds
-    [ "cursor"
-    -- , "stringify_ids" -- (needless)
-    , "count"
+    [ "count"
     ]
+instance HasCursorParam (APIRequest FollowersIds a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data FriendshipsIncoming
 -- | Returns a collection of numeric IDs for every user who has a pending request to follow the authenticating user.
@@ -375,13 +395,11 @@
 -- @
 --
 -- >>> friendshipsIncoming
--- APIRequestGet "https://api.twitter.com/1.1/friendships/incoming.json" []
-friendshipsIncoming :: APIRequest FriendshipsIncoming (WithCursor IdsCursorKey UserId)
-friendshipsIncoming = APIRequestGet (endpoint ++ "friendships/incoming.json") def
-deriveHasParamInstances ''FriendshipsIncoming
-    [ "cursor"
-    -- , "stringify_ids" -- (needless)
-    ]
+-- APIRequest "GET" "https://api.twitter.com/1.1/friendships/incoming.json" []
+friendshipsIncoming :: APIRequest FriendshipsIncoming (WithCursor Integer IdsCursorKey UserId)
+friendshipsIncoming = APIRequest "GET" (endpoint ++ "friendships/incoming.json") def
+instance HasCursorParam (APIRequest FriendshipsIncoming a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data FriendshipsOutgoing
 -- | Returns a collection of numeric IDs for every protected user for whom the authenticating user has a pending follow request.
@@ -399,13 +417,11 @@
 -- @
 --
 -- >>> friendshipsOutgoing
--- APIRequestGet "https://api.twitter.com/1.1/friendships/outgoing.json" []
-friendshipsOutgoing :: APIRequest FriendshipsOutgoing (WithCursor IdsCursorKey UserId)
-friendshipsOutgoing = APIRequestGet (endpoint ++ "friendships/outgoing.json") def
-deriveHasParamInstances ''FriendshipsOutgoing
-    [ "cursor"
-    -- , "stringify_ids" -- (needless)
-    ]
+-- APIRequest "GET" "https://api.twitter.com/1.1/friendships/outgoing.json" []
+friendshipsOutgoing :: APIRequest FriendshipsOutgoing (WithCursor Integer IdsCursorKey UserId)
+friendshipsOutgoing = APIRequest "GET" (endpoint ++ "friendships/outgoing.json") def
+instance HasCursorParam (APIRequest FriendshipsOutgoing a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data FriendshipsCreate
 -- | Returns post data which follows the user specified in the ID parameter.
@@ -417,11 +433,11 @@
 -- @
 --
 -- >>> friendshipsCreate (ScreenNameParam "thimura")
--- APIRequestPost "https://api.twitter.com/1.1/friendships/create.json" [("screen_name","thimura")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/friendships/create.json" [("screen_name","thimura")]
 -- >>> friendshipsCreate (UserIdParam 69179963)
--- APIRequestPost "https://api.twitter.com/1.1/friendships/create.json" [("user_id","69179963")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/friendships/create.json" [("user_id","69179963")]
 friendshipsCreate :: UserParam -> APIRequest FriendshipsCreate User
-friendshipsCreate user = APIRequestPost (endpoint ++ "friendships/create.json") (mkUserParam user)
+friendshipsCreate user = APIRequest "POST" (endpoint ++ "friendships/create.json") (mkUserParam user)
 deriveHasParamInstances ''FriendshipsCreate
     [ "follow"
     ]
@@ -436,11 +452,11 @@
 -- @
 --
 -- >>> friendshipsDestroy (ScreenNameParam "thimura")
--- APIRequestPost "https://api.twitter.com/1.1/friendships/destroy.json" [("screen_name","thimura")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/friendships/destroy.json" [("screen_name","thimura")]
 -- >>> friendshipsDestroy (UserIdParam 69179963)
--- APIRequestPost "https://api.twitter.com/1.1/friendships/destroy.json" [("user_id","69179963")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/friendships/destroy.json" [("user_id","69179963")]
 friendshipsDestroy :: UserParam -> APIRequest FriendshipsDestroy User
-friendshipsDestroy user = APIRequestPost (endpoint ++ "friendships/destroy.json") (mkUserParam user)
+friendshipsDestroy user = APIRequest "POST" (endpoint ++ "friendships/destroy.json") (mkUserParam user)
 
 data FriendsList
 -- | Returns query data which asks a cursored collection of user objects for every user the specified users is following.
@@ -458,17 +474,18 @@
 -- @
 --
 -- >>> friendsList (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/friends/list.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/friends/list.json" [("screen_name","thimura")]
 -- >>> friendsList (UserIdParam 69179963)
--- APIRequestGet "https://api.twitter.com/1.1/friends/list.json" [("user_id","69179963")]
-friendsList :: UserParam -> APIRequest FriendsList (WithCursor UsersCursorKey User)
-friendsList q = APIRequestGet (endpoint ++ "friends/list.json") (mkUserParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/friends/list.json" [("user_id","69179963")]
+friendsList :: UserParam -> APIRequest FriendsList (WithCursor Integer UsersCursorKey User)
+friendsList q = APIRequest "GET" (endpoint ++ "friends/list.json") (mkUserParam q)
 deriveHasParamInstances ''FriendsList
-    [ "cursor"
-    , "count"
+    [ "count"
     , "skip_status"
     , "include_user_entities"
     ]
+instance HasCursorParam (APIRequest FriendsList a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data FollowersList
 -- | Returns query data which asks a cursored collection of user objects for users following the specified user.
@@ -486,17 +503,18 @@
 -- @
 --
 -- >>> followersList (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/followers/list.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/followers/list.json" [("screen_name","thimura")]
 -- >>> followersList (UserIdParam 69179963)
--- APIRequestGet "https://api.twitter.com/1.1/followers/list.json" [("user_id","69179963")]
-followersList :: UserParam -> APIRequest FollowersList (WithCursor UsersCursorKey User)
-followersList q = APIRequestGet (endpoint ++ "followers/list.json") (mkUserParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/followers/list.json" [("user_id","69179963")]
+followersList :: UserParam -> APIRequest FollowersList (WithCursor Integer UsersCursorKey User)
+followersList q = APIRequest "GET" (endpoint ++ "followers/list.json") (mkUserParam q)
 deriveHasParamInstances ''FollowersList
-    [ "cursor"
-    , "count"
+    [ "count"
     , "skip_status"
     , "include_user_entities"
     ]
+instance HasCursorParam (APIRequest FollowersList a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data AccountVerifyCredentials
 -- | Returns query data asks that the credential is valid.
@@ -508,9 +526,9 @@
 -- @
 --
 -- >>> accountVerifyCredentials
--- APIRequestGet "https://api.twitter.com/1.1/account/verify_credentials.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/account/verify_credentials.json" []
 accountVerifyCredentials :: APIRequest AccountVerifyCredentials User
-accountVerifyCredentials = APIRequestGet (endpoint ++ "account/verify_credentials.json") []
+accountVerifyCredentials = APIRequest "GET" (endpoint ++ "account/verify_credentials.json") []
 deriveHasParamInstances ''AccountVerifyCredentials
     [ "include_entities"
     , "skip_status"
@@ -528,9 +546,9 @@
 -- @
 --
 -- >>> accountUpdateProfile & url ?~ "http://www.example.com"
--- APIRequestPost "https://api.twitter.com/1.1/account/update_profile.json" [("url","http://www.example.com")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/account/update_profile.json" [("url","http://www.example.com")]
 accountUpdateProfile :: APIRequest AccountUpdateProfile User
-accountUpdateProfile = APIRequestPost (endpoint ++ "account/update_profile.json") []
+accountUpdateProfile = APIRequest "POST" (endpoint ++ "account/update_profile.json") []
 deriveHasParamInstances ''AccountUpdateProfile
     [ "include_entities"
     , "skip_status"
@@ -551,9 +569,9 @@
 -- @
 --
 -- >>> usersLookup (ScreenNameListParam ["thimura", "twitterapi"])
--- APIRequestGet "https://api.twitter.com/1.1/users/lookup.json" [("screen_name","thimura,twitterapi")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/users/lookup.json" [("screen_name","thimura,twitterapi")]
 usersLookup :: UserListParam -> APIRequest UsersLookup [User]
-usersLookup q = APIRequestGet (endpoint ++ "users/lookup.json") (mkUserListParam q)
+usersLookup q = APIRequest "GET" (endpoint ++ "users/lookup.json") (mkUserListParam q)
 deriveHasParamInstances ''UsersLookup
     [ "include_entities"
     ]
@@ -568,9 +586,9 @@
 -- @
 --
 -- >>> usersShow (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/users/show.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/users/show.json" [("screen_name","thimura")]
 usersShow :: UserParam -> APIRequest UsersShow User
-usersShow q = APIRequestGet (endpoint ++ "users/show.json") (mkUserParam q)
+usersShow q = APIRequest "GET" (endpoint ++ "users/show.json") (mkUserParam q)
 deriveHasParamInstances ''UsersShow
     [ "include_entities"
     ]
@@ -585,13 +603,13 @@
 -- @
 --
 -- >>> favoritesList Nothing
--- APIRequestGet "https://api.twitter.com/1.1/favorites/list.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/favorites/list.json" []
 -- >>> favoritesList (Just (ScreenNameParam "thimura"))
--- APIRequestGet "https://api.twitter.com/1.1/favorites/list.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/favorites/list.json" [("screen_name","thimura")]
 -- >>> favoritesList (Just (UserIdParam 69179963))
--- APIRequestGet "https://api.twitter.com/1.1/favorites/list.json" [("user_id","69179963")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/favorites/list.json" [("user_id","69179963")]
 favoritesList :: Maybe UserParam -> APIRequest FavoritesList [Status]
-favoritesList mbuser = APIRequestGet (endpoint ++ "favorites/list.json") (mkParam mbuser)
+favoritesList mbuser = APIRequest "GET" (endpoint ++ "favorites/list.json") (mkParam mbuser)
   where
     mkParam Nothing = []
     mkParam (Just usr) = mkUserParam usr
@@ -612,9 +630,9 @@
 -- @
 --
 -- >>> favoritesCreate 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/favorites/create.json" [("id","1234567890")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/favorites/create.json" [("id","1234567890")]
 favoritesCreate :: StatusId -> APIRequest FavoritesCreate Status
-favoritesCreate sid = APIRequestPost (endpoint ++ "favorites/create.json") [("id", PVInteger sid)]
+favoritesCreate sid = APIRequest "POST" (endpoint ++ "favorites/create.json") [("id", PVInteger sid)]
 deriveHasParamInstances ''FavoritesCreate
     [ "include_entities"
     ]
@@ -629,9 +647,9 @@
 -- @
 --
 -- >>> favoritesDestroy 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/favorites/destroy.json" [("id","1234567890")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/favorites/destroy.json" [("id","1234567890")]
 favoritesDestroy :: StatusId -> APIRequest FavoritesDestroy Status
-favoritesDestroy sid = APIRequestPost (endpoint ++ "favorites/destroy.json") [("id", PVInteger sid)]
+favoritesDestroy sid = APIRequest "POST" (endpoint ++ "favorites/destroy.json") [("id", PVInteger sid)]
 deriveHasParamInstances ''FavoritesDestroy
     [ "include_entities"
     ]
@@ -651,11 +669,11 @@
 -- @
 --
 -- >>> listsStatuses (ListNameParam "thimura/haskell")
--- APIRequestGet "https://api.twitter.com/1.1/lists/statuses.json" [("slug","haskell"),("owner_screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/statuses.json" [("slug","haskell"),("owner_screen_name","thimura")]
 -- >>> listsStatuses (ListIdParam 20849097)
--- APIRequestGet "https://api.twitter.com/1.1/lists/statuses.json" [("list_id","20849097")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/statuses.json" [("list_id","20849097")]
 listsStatuses :: ListParam -> APIRequest ListsStatuses [Status]
-listsStatuses q = APIRequestGet (endpoint ++ "lists/statuses.json") (mkListParam q)
+listsStatuses q = APIRequest "GET" (endpoint ++ "lists/statuses.json") (mkListParam q)
 deriveHasParamInstances ''ListsStatuses
     [ "since_id"
     , "max_id"
@@ -674,11 +692,11 @@
 -- @
 --
 -- >>> listsMembersDestroy (ListNameParam "thimura/haskell") (ScreenNameParam "thimura")
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/destroy.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/destroy.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura")]
 -- >>> listsMembersDestroy (ListIdParam 20849097) (UserIdParam 69179963)
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/destroy.json" [("list_id","20849097"),("user_id","69179963")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/destroy.json" [("list_id","20849097"),("user_id","69179963")]
 listsMembersDestroy :: ListParam -> UserParam -> APIRequest ListsMembersDestroy List
-listsMembersDestroy list user = APIRequestPost (endpoint ++ "lists/members/destroy.json") (mkListParam list ++ mkUserParam user)
+listsMembersDestroy list user = APIRequest "POST" (endpoint ++ "lists/members/destroy.json") (mkListParam list ++ mkUserParam user)
 
 data ListsMemberships
 -- | Returns the request parameters which asks the lists the specified user has been added to.
@@ -691,17 +709,18 @@
 -- @
 --
 -- >>> listsMemberships Nothing
--- APIRequestGet "https://api.twitter.com/1.1/lists/memberships.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/memberships.json" []
 -- >>> listsMemberships (Just (ScreenNameParam "thimura"))
--- APIRequestGet "https://api.twitter.com/1.1/lists/memberships.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/memberships.json" [("screen_name","thimura")]
 -- >>> listsMemberships (Just (UserIdParam 69179963))
--- APIRequestGet "https://api.twitter.com/1.1/lists/memberships.json" [("user_id","69179963")]
-listsMemberships :: Maybe UserParam -> APIRequest ListsMemberships (WithCursor ListsCursorKey List)
-listsMemberships q = APIRequestGet (endpoint ++ "lists/memberships.json") $ maybe [] mkUserParam q
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/memberships.json" [("user_id","69179963")]
+listsMemberships :: Maybe UserParam -> APIRequest ListsMemberships (WithCursor Integer ListsCursorKey List)
+listsMemberships q = APIRequest "GET" (endpoint ++ "lists/memberships.json") $ maybe [] mkUserParam q
 deriveHasParamInstances ''ListsMemberships
-    [ "cursor"
-    , "count"
+    [ "count"
     ]
+instance HasCursorParam (APIRequest ListsMemberships a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data ListsSubscribers
 -- | Returns the request parameter which asks the subscribers of the specified list.
@@ -713,16 +732,17 @@
 -- @
 --
 -- >>> listsSubscribers (ListNameParam "thimura/haskell")
--- APIRequestGet "https://api.twitter.com/1.1/lists/subscribers.json" [("slug","haskell"),("owner_screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/subscribers.json" [("slug","haskell"),("owner_screen_name","thimura")]
 -- >>> listsSubscribers (ListIdParam 20849097)
--- APIRequestGet "https://api.twitter.com/1.1/lists/subscribers.json" [("list_id","20849097")]
-listsSubscribers :: ListParam -> APIRequest ListsSubscribers (WithCursor UsersCursorKey User)
-listsSubscribers q = APIRequestGet (endpoint ++ "lists/subscribers.json") (mkListParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/subscribers.json" [("list_id","20849097")]
+listsSubscribers :: ListParam -> APIRequest ListsSubscribers (WithCursor Integer UsersCursorKey User)
+listsSubscribers q = APIRequest "GET" (endpoint ++ "lists/subscribers.json") (mkListParam q)
 deriveHasParamInstances ''ListsSubscribers
-    [ "cursor"
-    , "count"
+    [ "count"
     , "skip_status"
     ]
+instance HasCursorParam (APIRequest ListsSubscribers a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data ListsSubscriptions
 -- | Returns the request parameter which obtains a collection of the lists the specified user is subscribed to.
@@ -734,17 +754,18 @@
 -- @
 --
 -- >>> listsSubscriptions Nothing
--- APIRequestGet "https://api.twitter.com/1.1/lists/subscriptions.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/subscriptions.json" []
 -- >>> listsSubscriptions (Just (ScreenNameParam "thimura"))
--- APIRequestGet "https://api.twitter.com/1.1/lists/subscriptions.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/subscriptions.json" [("screen_name","thimura")]
 -- >>> listsSubscriptions (Just (UserIdParam 69179963))
--- APIRequestGet "https://api.twitter.com/1.1/lists/subscriptions.json" [("user_id","69179963")]
-listsSubscriptions :: Maybe UserParam -> APIRequest ListsSubscriptions (WithCursor ListsCursorKey List)
-listsSubscriptions q = APIRequestGet (endpoint ++ "lists/subscriptions.json") $ maybe [] mkUserParam q
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/subscriptions.json" [("user_id","69179963")]
+listsSubscriptions :: Maybe UserParam -> APIRequest ListsSubscriptions (WithCursor Integer ListsCursorKey List)
+listsSubscriptions q = APIRequest "GET" (endpoint ++ "lists/subscriptions.json") $ maybe [] mkUserParam q
 deriveHasParamInstances ''ListsSubscriptions
-    [ "cursor"
-    , "count"
+    [ "count"
     ]
+instance HasCursorParam (APIRequest ListsSubscriptions a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data ListsOwnerships
 -- | Returns the request parameter which asks the lists owned by the specified Twitter user.
@@ -756,17 +777,18 @@
 -- @
 --
 -- >>> listsOwnerships Nothing
--- APIRequestGet "https://api.twitter.com/1.1/lists/ownerships.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/ownerships.json" []
 -- >>> listsOwnerships (Just (ScreenNameParam "thimura"))
--- APIRequestGet "https://api.twitter.com/1.1/lists/ownerships.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/ownerships.json" [("screen_name","thimura")]
 -- >>> listsOwnerships (Just (UserIdParam 69179963))
--- APIRequestGet "https://api.twitter.com/1.1/lists/ownerships.json" [("user_id","69179963")]
-listsOwnerships :: Maybe UserParam -> APIRequest ListsOwnerships (WithCursor ListsCursorKey List)
-listsOwnerships q = APIRequestGet (endpoint ++ "lists/ownerships.json") $ maybe [] mkUserParam q
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/ownerships.json" [("user_id","69179963")]
+listsOwnerships :: Maybe UserParam -> APIRequest ListsOwnerships (WithCursor Integer ListsCursorKey List)
+listsOwnerships q = APIRequest "GET" (endpoint ++ "lists/ownerships.json") $ maybe [] mkUserParam q
 deriveHasParamInstances ''ListsOwnerships
-    [ "cursor"
-    , "count"
+    [ "count"
     ]
+instance HasCursorParam (APIRequest ListsOwnerships a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data ListsMembersCreateAll
 -- | Adds multiple members to a list.
@@ -778,11 +800,11 @@
 -- @
 --
 -- >>> listsMembersCreateAll (ListNameParam "thimura/haskell") (ScreenNameListParam ["thimura", "twitterapi"])
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/create_all.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura,twitterapi")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/create_all.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura,twitterapi")]
 -- >>> listsMembersCreateAll (ListIdParam 20849097) (UserIdListParam [69179963, 6253282])
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/create_all.json" [("list_id","20849097"),("user_id","69179963,6253282")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/create_all.json" [("list_id","20849097"),("user_id","69179963,6253282")]
 listsMembersCreateAll :: ListParam -> UserListParam -> APIRequest ListsMembersCreateAll List
-listsMembersCreateAll list users = APIRequestPost (endpoint ++ "lists/members/create_all.json") (mkListParam list ++ mkUserListParam users)
+listsMembersCreateAll list users = APIRequest "POST" (endpoint ++ "lists/members/create_all.json") (mkListParam list ++ mkUserListParam users)
 
 data ListsMembersDestroyAll
 -- | Adds multiple members to a list.
@@ -794,11 +816,11 @@
 -- @
 --
 -- >>> listsMembersDestroyAll (ListNameParam "thimura/haskell") (ScreenNameListParam ["thimura", "twitterapi"])
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/destroy_all.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura,twitterapi")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/destroy_all.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura,twitterapi")]
 -- >>> listsMembersDestroyAll (ListIdParam 20849097) (UserIdListParam [69179963, 6253282])
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/destroy_all.json" [("list_id","20849097"),("user_id","69179963,6253282")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/destroy_all.json" [("list_id","20849097"),("user_id","69179963,6253282")]
 listsMembersDestroyAll :: ListParam -> UserListParam -> APIRequest ListsMembersDestroyAll List
-listsMembersDestroyAll list users = APIRequestPost (endpoint ++ "lists/members/destroy_all.json") (mkListParam list ++ mkUserListParam users)
+listsMembersDestroyAll list users = APIRequest "POST" (endpoint ++ "lists/members/destroy_all.json") (mkListParam list ++ mkUserListParam users)
 
 data ListsMembers
 -- | Returns query data asks the members of the specified list.
@@ -810,16 +832,17 @@
 -- @
 --
 -- >>> listsMembers (ListNameParam "thimura/haskell")
--- APIRequestGet "https://api.twitter.com/1.1/lists/members.json" [("slug","haskell"),("owner_screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/members.json" [("slug","haskell"),("owner_screen_name","thimura")]
 -- >>> listsMembers (ListIdParam 20849097)
--- APIRequestGet "https://api.twitter.com/1.1/lists/members.json" [("list_id","20849097")]
-listsMembers :: ListParam -> APIRequest ListsMembers (WithCursor UsersCursorKey User)
-listsMembers q = APIRequestGet (endpoint ++ "lists/members.json") (mkListParam q)
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/members.json" [("list_id","20849097")]
+listsMembers :: ListParam -> APIRequest ListsMembers (WithCursor Integer UsersCursorKey User)
+listsMembers q = APIRequest "GET" (endpoint ++ "lists/members.json") (mkListParam q)
 deriveHasParamInstances ''ListsMembers
     [ "count"
-    , "cursor"
     , "skip_status"
     ]
+instance HasCursorParam (APIRequest ListsMembers a) Integer where
+    cursor = wrappedParam "cursor" PVInteger unPVInteger
 
 data ListsMembersCreate
 -- | Returns the post parameter which adds a member to a list.
@@ -831,11 +854,11 @@
 -- @
 --
 -- >>> listsMembersCreate (ListNameParam "thimura/haskell") (ScreenNameParam "thimura")
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/create.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/create.json" [("slug","haskell"),("owner_screen_name","thimura"),("screen_name","thimura")]
 -- >>> listsMembersCreate (ListIdParam 20849097) (UserIdParam 69179963)
--- APIRequestPost "https://api.twitter.com/1.1/lists/members/create.json" [("list_id","20849097"),("user_id","69179963")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/members/create.json" [("list_id","20849097"),("user_id","69179963")]
 listsMembersCreate :: ListParam -> UserParam -> APIRequest ListsMembersCreate List
-listsMembersCreate list user = APIRequestPost (endpoint ++ "lists/members/create.json") (mkListParam list ++ mkUserParam user)
+listsMembersCreate list user = APIRequest "POST" (endpoint ++ "lists/members/create.json") (mkListParam list ++ mkUserParam user)
 
 data ListsDestroy
 -- | Returns the post parameter which deletes the specified list.
@@ -847,11 +870,11 @@
 -- @
 --
 -- >>> listsDestroy (ListNameParam "thimura/haskell")
--- APIRequestPost "https://api.twitter.com/1.1/lists/destroy.json" [("slug","haskell"),("owner_screen_name","thimura")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/destroy.json" [("slug","haskell"),("owner_screen_name","thimura")]
 -- >>> listsDestroy (ListIdParam 20849097)
--- APIRequestPost "https://api.twitter.com/1.1/lists/destroy.json" [("list_id","20849097")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/destroy.json" [("list_id","20849097")]
 listsDestroy :: ListParam -> APIRequest ListsDestroy List
-listsDestroy list = APIRequestPost (endpoint ++ "lists/destroy.json") (mkListParam list)
+listsDestroy list = APIRequest "POST" (endpoint ++ "lists/destroy.json") (mkListParam list)
 
 data ListsUpdate
 -- | Returns the post parameter which updates the specified list.
@@ -863,12 +886,12 @@
 -- @
 --
 -- >>> listsUpdate (ListNameParam "thimura/haskell") True (Just "Haskellers")
--- APIRequestPost "https://api.twitter.com/1.1/lists/update.json" [("slug","haskell"),("owner_screen_name","thimura"),("description","Haskellers"),("mode","public")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/update.json" [("slug","haskell"),("owner_screen_name","thimura"),("description","Haskellers"),("mode","public")]
 listsUpdate :: ListParam
             -> Bool -- ^ is public
             -> Maybe T.Text -- ^ description
             -> APIRequest ListsUpdate List
-listsUpdate list isPublic description = APIRequestPost (endpoint ++ "lists/update.json") (mkListParam list ++ p')
+listsUpdate list isPublic description = APIRequest "POST" (endpoint ++ "lists/update.json") (mkListParam list ++ p')
   where
     p = [("mode", PVString . mode $ isPublic)]
     p' = maybe id (\d -> (("description", PVString d):)) description p
@@ -885,16 +908,16 @@
 -- @
 --
 -- >>> listsCreate "haskell" True Nothing
--- APIRequestPost "https://api.twitter.com/1.1/lists/create.json" [("name","haskell"),("mode","public")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/create.json" [("name","haskell"),("mode","public")]
 -- >>> listsCreate "haskell" False Nothing
--- APIRequestPost "https://api.twitter.com/1.1/lists/create.json" [("name","haskell"),("mode","private")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/create.json" [("name","haskell"),("mode","private")]
 -- >>> listsCreate "haskell" True (Just "Haskellers")
--- APIRequestPost "https://api.twitter.com/1.1/lists/create.json" [("description","Haskellers"),("name","haskell"),("mode","public")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/lists/create.json" [("description","Haskellers"),("name","haskell"),("mode","public")]
 listsCreate :: T.Text -- ^ list name
             -> Bool -- ^ whether public(True) or private(False)
             -> Maybe T.Text -- ^ the description to give the list
             -> APIRequest ListsCreate List
-listsCreate name isPublic description = APIRequestPost (endpoint ++ "lists/create.json") p'
+listsCreate name isPublic description = APIRequest "POST" (endpoint ++ "lists/create.json") p'
   where
     p = [("name", PVString name), ("mode", PVString . mode $ isPublic)]
     p' = maybe id (\d -> (("description", PVString d):)) description p
@@ -911,11 +934,11 @@
 -- @
 --
 -- >>> listsShow (ListNameParam "thimura/haskell")
--- APIRequestGet "https://api.twitter.com/1.1/lists/show.json" [("slug","haskell"),("owner_screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/show.json" [("slug","haskell"),("owner_screen_name","thimura")]
 -- >>> listsShow (ListIdParam 20849097)
--- APIRequestGet "https://api.twitter.com/1.1/lists/show.json" [("list_id","20849097")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/lists/show.json" [("list_id","20849097")]
 listsShow :: ListParam -> APIRequest ListsShow List
-listsShow q = APIRequestGet (endpoint ++ "lists/show.json") (mkListParam q)
+listsShow q = APIRequest "GET" (endpoint ++ "lists/show.json") (mkListParam q)
 
 data MediaUpload
 -- | Upload media and returns the media data.
@@ -938,11 +961,11 @@
 -- See: <https://dev.twitter.com/docs/api/multiple-media-extended-entities>
 --
 -- >>> mediaUpload (MediaFromFile "/home/test/test.png")
--- APIRequestPostMultipart "https://upload.twitter.com/1.1/media/upload.json" []
+-- APIRequestMultipart "POST" "https://upload.twitter.com/1.1/media/upload.json" []
 mediaUpload :: MediaData
             -> APIRequest MediaUpload UploadedMedia
 mediaUpload mediaData =
-    APIRequestPostMultipart uri [] [mediaBody mediaData]
+    APIRequestMultipart "POST" uri [] [mediaBody mediaData]
   where
     uri = "https://upload.twitter.com/1.1/media/upload.json"
     mediaBody (MediaFromFile fp) = partFileSource "media" fp
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,10 +1,14 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE UndecidableInstances #-}
 
 module Web.Twitter.Conduit.Base
-       ( getResponse
+       ( ResponseBodyType (..)
+       , NoContent
+       , getResponse
        , call
        , call'
        , callWithResponse
@@ -30,6 +34,7 @@
 import Web.Twitter.Types.Lens
 
 import Control.Lens
+import Control.Monad (void)
 import Control.Monad.Base
 import Control.Monad.Catch (MonadThrow (..))
 import Control.Monad.IO.Class
@@ -51,13 +56,19 @@
 
 makeRequest :: APIRequest apiName responseType
             -> IO HTTP.Request
-makeRequest (APIRequestGet u pa) = makeRequest' "GET" u (makeSimpleQuery pa)
-makeRequest (APIRequestPost u pa) = makeRequest' "POST" u (makeSimpleQuery pa)
-makeRequest (APIRequestPostMultipart u param prt) =
-    formDataBody body =<< makeRequest' "POST" u []
+makeRequest (APIRequest m u pa) = makeRequest' m u (makeSimpleQuery pa)
+makeRequest (APIRequestMultipart m u param prt) =
+    formDataBody body =<< makeRequest' m u []
   where
     body = prt ++ partParam
     partParam = Prelude.map (uncurry partBS . over _1 T.decodeUtf8) (makeSimpleQuery param)
+makeRequest (APIRequestJSON m u param body) = do
+    req <- makeRequest' m u (makeSimpleQuery param)
+    return $
+        req
+        { HTTP.requestBody = HTTP.RequestBodyLBS $ encode body
+        , HTTP.requestHeaders = ("Content-Type", "application/json") : HTTP.requestHeaders req
+        }
 
 makeRequest' :: HT.Method -- ^ HTTP request method (GET or POST)
              -> String -- ^ API Resource URL
@@ -79,6 +90,27 @@
 #endif
                              }
 
+class ResponseBodyType a where
+    parseResponseBody ::
+#if MIN_VERSION_http_conduit(2,3,0)
+           Response (C.ConduitM () ByteString (ResourceT IO) ())
+#else
+           Response (C.ResumableSource m ByteString)
+#endif
+        -> ResourceT IO (Response a)
+
+type NoContent = ()
+instance ResponseBodyType NoContent where
+    parseResponseBody res =
+        case responseStatus res of
+            st | st == HT.status204 -> return $ void res
+            _ -> do
+                body <- C.runConduit $ responseBody res C..| sinkJSON
+                throwM $ TwitterStatusError (responseStatus res) (responseHeaders res) body
+
+instance {-# OVERLAPPABLE #-} FromJSON a => ResponseBodyType a where
+    parseResponseBody = getValueOrThrow
+
 getResponse :: MonadResource m
             => TWInfo
             -> HTTP.Manager
@@ -161,7 +193,7 @@
 --
 -- If you need raw JSON value which is parsed by <http://hackage.haskell.org/package/aeson aeson>,
 -- use 'call'' to obtain it.
-call :: FromJSON responseType
+call :: ResponseBodyType responseType
      => TWInfo -- ^ Twitter Setting
      -> HTTP.Manager
      -> APIRequest apiName responseType
@@ -171,7 +203,7 @@
 -- | Perform an 'APIRequest' and then provide the response.
 -- The response of this function is not restrict to @responseType@,
 -- so you can choose an arbitrarily type of FromJSON instances.
-call' :: FromJSON value
+call' :: ResponseBodyType value
       => TWInfo -- ^ Twitter Setting
       -> HTTP.Manager
       -> APIRequest apiName responseType
@@ -188,7 +220,7 @@
 -- 'print' $ 'responseHeaders' res
 -- 'print' $ 'responseBody' res
 -- @
-callWithResponse :: FromJSON responseType
+callWithResponse :: ResponseBodyType responseType
                  => TWInfo -- ^ Twitter Setting
                  -> HTTP.Manager
                  -> APIRequest apiName responseType
@@ -207,7 +239,7 @@
 -- 'print' $ 'responseHeaders' res
 -- 'print' $ 'responseBody' (res :: Value)
 -- @
-callWithResponse' :: FromJSON value
+callWithResponse' :: ResponseBodyType value
                   => TWInfo
                   -> HTTP.Manager
                   -> APIRequest apiName responseType
@@ -215,7 +247,7 @@
 callWithResponse' info mgr req =
     runResourceT $ do
         res <- getResponse info mgr =<< liftIO (makeRequest req)
-        getValueOrThrow res
+        parseResponseBody res
 
 -- | A wrapper function to perform multiple API request with changing @max_id@ parameter.
 --
@@ -269,16 +301,17 @@
 sourceWithCursor :: ( MonadIO m
                     , FromJSON responseType
                     , CursorKey ck
-                    , HasCursorParam (APIRequest apiName (WithCursor ck responseType))
+                    , HasCursorParam (APIRequest apiName (WithCursor Integer ck responseType)) Integer
                     )
                  => TWInfo -- ^ Twitter Setting
                  -> HTTP.Manager
-                 -> APIRequest apiName (WithCursor ck responseType)
+                 -> APIRequest apiName (WithCursor Integer ck responseType)
                  -> C.Source m responseType
-sourceWithCursor info mgr req = loop (-1)
+sourceWithCursor info mgr req = loop (Just (-1))
   where
-    loop 0 = CL.sourceNull
-    loop cur = do
+    loop Nothing = CL.sourceNull
+    loop (Just 0) = CL.sourceNull
+    loop (Just cur) = do
         res <- liftIO $ call info mgr $ req & cursor ?~ cur
         CL.sourceList $ contents res
         loop $ nextCursor res
@@ -290,19 +323,20 @@
 -- This function cooperate with instances of 'HasCursorParam'.
 sourceWithCursor' :: ( MonadIO m
                      , CursorKey ck
-                     , HasCursorParam (APIRequest apiName (WithCursor ck responseType))
+                     , HasCursorParam (APIRequest apiName (WithCursor Integer ck responseType)) Integer
                      )
                   => TWInfo -- ^ Twitter Setting
                   -> HTTP.Manager
-                  -> APIRequest apiName (WithCursor ck responseType)
+                  -> APIRequest apiName (WithCursor Integer ck responseType)
                   -> C.Source m Value
-sourceWithCursor' info mgr req = loop (-1)
+sourceWithCursor' info mgr req = loop (Just (-1))
   where
-    relax :: APIRequest apiName (WithCursor ck responseType)
-          -> APIRequest apiName (WithCursor ck Value)
+    relax :: APIRequest apiName (WithCursor Integer ck responseType)
+          -> APIRequest apiName (WithCursor Integer ck Value)
     relax = unsafeCoerce
-    loop 0 = CL.sourceNull
-    loop cur = do
+    loop Nothing = CL.sourceNull
+    loop (Just 0) = CL.sourceNull
+    loop (Just cur) = do
         res <- liftIO $ call info mgr $ relax $ req & cursor ?~ cur
         CL.sourceList $ contents res
         loop $ nextCursor res
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
@@ -8,6 +8,7 @@
        , IdsCursorKey
        , UsersCursorKey
        , ListsCursorKey
+       , EventsCursorKey
        , WithCursor (..)
        ) where
 
@@ -40,33 +41,43 @@
 instance CursorKey ListsCursorKey where
     cursorKey = const "lists"
 
+data EventsCursorKey
+instance CursorKey EventsCursorKey where
+    cursorKey = const "events"
+
 #if __GLASGOW_HASKELL__ >= 706
 -- | 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 IdsCursorKey UserId)
+-- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 1234567890, \"ids\": [1111111111]}" :: Maybe (WithCursor Integer IdsCursorKey UserId)
 -- >>> nextCursor res
--- 1234567890
+-- Just 1234567890
 -- >>> contents res
 -- [1111111111]
 --
--- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 0, \"users\": [1000]}" :: Maybe (WithCursor UsersCursorKey UserId)
+-- >>> let Just res = decode "{\"previous_cursor\": 0, \"next_cursor\": 0, \"users\": [1000]}" :: Maybe (WithCursor Integer UsersCursorKey UserId)
 -- >>> nextCursor res
--- 0
+-- Just 0
 -- >>> contents res
 -- [1000]
+--
+-- >>> let Just res = decode "{\"next_cursor\": \"hogehoge\", \"events\": [1000]}" :: Maybe (WithCursor Text EventsCursorKey UserId)
+-- >>> nextCursor res
+-- Just "hogehoge"
+-- >>> contents res
+-- [1000]
 #endif
-data WithCursor cursorKey wrapped = WithCursor
-    { previousCursor :: Integer
-    , nextCursor :: Integer
+data WithCursor cursorType cursorKey wrapped = WithCursor
+    { previousCursor :: Maybe cursorType
+    , nextCursor :: Maybe cursorType
     , contents :: [wrapped]
     } deriving Show
 
-instance (FromJSON wrapped, CursorKey c) =>
-         FromJSON (WithCursor c wrapped) where
+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"
+      WithCursor <$> o .:? "previous_cursor"
+                 <*> o .:? "next_cursor"
                  <*> o .:  cursorKey (undefined :: c)
     parseJSON _ = mempty
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
@@ -55,11 +55,11 @@
 twitterErrorMessage afb s = (\b -> s { TT.twitterErrorMessage = b }) <$> afb (TT.twitterErrorMessage s)
 
 -- * Lenses for 'TT.WithCursor'
-previousCursor :: forall cursorKey wrapped. Lens' (TT.WithCursor cursorKey wrapped) Integer
+previousCursor :: forall cursorType cursorKey wrapped. Lens' (TT.WithCursor cursorType cursorKey wrapped) (Maybe cursorType)
 previousCursor afb s = (\b -> s { TT.previousCursor = b }) <$> afb (TT.previousCursor s)
 
-nextCursor :: forall cursorKey wrapped. Lens' (TT.WithCursor cursorKey wrapped) Integer
+nextCursor :: forall cursorType cursorKey wrapped. Lens' (TT.WithCursor cursorType cursorKey wrapped) (Maybe cursorType)
 nextCursor afb s = (\b -> s { TT.nextCursor = b }) <$> afb (TT.nextCursor s)
 
-contents :: forall cursorKey a b. Lens (TT.WithCursor cursorKey a) (TT.WithCursor cursorKey b) [a] [b]
+contents :: forall cursorType cursorKey a b. Lens (TT.WithCursor cursorType cursorKey a) (TT.WithCursor cursorType cursorKey b) [a] [b]
 contents afb s = (\b -> s { TT.contents = b }) <$> afb (TT.contents s)
diff --git a/Web/Twitter/Conduit/Parameters.hs b/Web/Twitter/Conduit/Parameters.hs
--- a/Web/Twitter/Conduit/Parameters.hs
+++ b/Web/Twitter/Conduit/Parameters.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 
@@ -53,6 +54,7 @@
        , mkListParam
        ) where
 
+import Control.Lens
 import qualified Data.Text as T
 import Network.HTTP.Client (RequestBody)
 import Web.Twitter.Conduit.Parameters.TH
@@ -72,7 +74,6 @@
 defineHasParamClassInteger "since_id"
 defineHasParamClassInteger "max_id"
 defineHasParamClassInteger "page"
-defineHasParamClassInteger "cursor"
 defineHasParamClassBool "trim_user"
 defineHasParamClassBool "exclude_replies"
 defineHasParamClassBool "contributor_details"
@@ -103,6 +104,9 @@
 defineHasParamClassURI "url"
 defineHasParamClassBool "full_text"
 defineHasParamClassString "with"
+
+class Parameters p => HasCursorParam p a | p -> a where
+    cursor :: Lens' p (Maybe a)
 
 -- | converts 'UserParam' to 'HT.SimpleQuery'.
 --
diff --git a/Web/Twitter/Conduit/Parameters/TH.hs b/Web/Twitter/Conduit/Parameters/TH.hs
--- a/Web/Twitter/Conduit/Parameters/TH.hs
+++ b/Web/Twitter/Conduit/Parameters/TH.hs
@@ -14,6 +14,7 @@
        , defineHasParamClassStringArray
        , defineHasParamClassURI
        , deriveHasParamInstances
+       , wrappedParam
        ) where
 
 import Web.Twitter.Conduit.Request
diff --git a/Web/Twitter/Conduit/Request.hs b/Web/Twitter/Conduit/Request.hs
--- a/Web/Twitter/Conduit/Request.hs
+++ b/Web/Twitter/Conduit/Request.hs
@@ -16,6 +16,7 @@
 import Control.Applicative
 #endif
 import Control.Lens
+import Data.Aeson
 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Char8 as S8
 import Data.Text (Text)
@@ -41,7 +42,7 @@
 -- >>> type SampleId = Integer
 -- >>> instance HasCountParam (APIRequest SampleApi [SampleId])
 -- >>> instance HasMaxIdParam (APIRequest SampleApi [SampleId])
--- >>> let sampleApiRequest :: APIRequest SampleApi [SampleId]; sampleApiRequest = APIRequestGet "https://api.twitter.com/sample/api.json" def
+-- >>> let sampleApiRequest :: APIRequest SampleApi [SampleId]; sampleApiRequest = APIRequest "GET" "https://api.twitter.com/sample/api.json" def
 
 -- | API request. You should use specific builder functions instead of building this directly.
 --
@@ -54,7 +55,7 @@
 -- instance 'HasCountParam' ('APIRequest' 'SampleApi' ['SampleId'])
 -- instance 'HasMaxIdParam' ('APIRequest' 'SampleApi' ['SampleId'])
 -- 'sampleApiRequest' :: 'APIRequest' 'SampleApi' ['SampleId']
--- 'sampleApiRequest' = 'APIRequestGet' \"https:\/\/api.twitter.com\/sample\/api.json\" 'def'
+-- 'sampleApiRequest' = 'APIRequest' \"GET\" \"https:\/\/api.twitter.com\/sample\/api.json\" 'def'
 -- @
 --
 -- We can obtain request params from @'APIRequest' SampleApi [SampleId]@ :
@@ -70,28 +71,32 @@
 -- [("max_id",PVInteger {unPVInteger = 1234567890})]
 #endif
 data APIRequest apiName responseType
-    = APIRequestGet
-      { _url :: String
+    = APIRequest
+      { _method :: HT.Method
+      , _url :: String
       , _params :: APIQuery
       }
-    | APIRequestPost
-      { _url :: String
+    | APIRequestMultipart
+      { _method :: HT.Method
+      , _url :: String
       , _params :: APIQuery
+      , _part :: [Part]
       }
-    | APIRequestPostMultipart
-      { _url :: String
+    | APIRequestJSON
+      { _method :: HT.Method
+      , _url :: String
       , _params :: APIQuery
-      , _part :: [Part]
+      , _body :: Value
       }
 instance Parameters (APIRequest apiName responseType) where
-    params f (APIRequestGet u pa) = APIRequestGet u <$> f pa
-    params f (APIRequestPost u pa) = APIRequestPost u <$> f pa
-    params f (APIRequestPostMultipart u pa prt) =
-        (\p -> APIRequestPostMultipart u p prt) <$> f pa
+    params f (APIRequest m u pa) = APIRequest m u <$> f pa
+    params f (APIRequestMultipart m u pa prt) =
+        (\p -> APIRequestMultipart m u p prt) <$> f pa
+    params f (APIRequestJSON m u pa body) = (\p -> APIRequestJSON m u p body) <$> f pa
 instance Show (APIRequest apiName responseType) where
-    show (APIRequestGet u p) = "APIRequestGet " ++ show u ++ " " ++ show (makeSimpleQuery p)
-    show (APIRequestPost u p) = "APIRequestPost " ++ show u ++ " " ++ show (makeSimpleQuery p)
-    show (APIRequestPostMultipart u p _) = "APIRequestPostMultipart " ++ show u ++ " " ++ show (makeSimpleQuery p)
+    show (APIRequest m u p) = "APIRequest " ++ show m ++ " " ++ show u ++ " " ++ show (makeSimpleQuery p)
+    show (APIRequestMultipart m u p _) = "APIRequestMultipart " ++ show m ++ " " ++ show u ++ " " ++ show (makeSimpleQuery p)
+    show (APIRequestJSON m u p _) = "APIRequestJSON " ++ show m ++ " " ++ show u ++ " " ++ show (makeSimpleQuery p)
 
 type APIQuery = [APIQueryItem]
 type APIQueryItem = (ByteString, PV)
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
@@ -62,9 +62,9 @@
 -- @
 --
 -- >>> mentionsTimeline
--- APIRequestGet "https://api.twitter.com/1.1/statuses/mentions_timeline.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/mentions_timeline.json" []
 mentionsTimeline :: APIRequest StatusesMentionsTimeline [Status]
-mentionsTimeline = APIRequestGet (endpoint ++ "statuses/mentions_timeline.json") def
+mentionsTimeline = APIRequest "GET" (endpoint ++ "statuses/mentions_timeline.json") def
 deriveHasParamInstances ''StatusesMentionsTimeline
     [ "count"
     , "since_id"
@@ -84,11 +84,11 @@
 -- @
 --
 -- >>> userTimeline (ScreenNameParam "thimura")
--- APIRequestGet "https://api.twitter.com/1.1/statuses/user_timeline.json" [("screen_name","thimura")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/user_timeline.json" [("screen_name","thimura")]
 -- >>> userTimeline (ScreenNameParam "thimura") & includeRts ?~ True & count ?~ 200
--- APIRequestGet "https://api.twitter.com/1.1/statuses/user_timeline.json" [("count","200"),("include_rts","true"),("screen_name","thimura")]
+-- 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 = APIRequestGet (endpoint ++ "statuses/user_timeline.json") (mkUserParam q)
+userTimeline q = APIRequest "GET" (endpoint ++ "statuses/user_timeline.json") (mkUserParam q)
 deriveHasParamInstances ''StatusesUserTimeline
     [ "count"
     , "since_id"
@@ -109,11 +109,11 @@
 -- @
 --
 -- >>> homeTimeline
--- APIRequestGet "https://api.twitter.com/1.1/statuses/home_timeline.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" []
 -- >>> homeTimeline & count ?~ 200
--- APIRequestGet "https://api.twitter.com/1.1/statuses/home_timeline.json" [("count","200")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/home_timeline.json" [("count","200")]
 homeTimeline :: APIRequest StatusesHomeTimeline [Status]
-homeTimeline = APIRequestGet (endpoint ++ "statuses/home_timeline.json") def
+homeTimeline = APIRequest "GET" (endpoint ++ "statuses/home_timeline.json") def
 deriveHasParamInstances ''StatusesHomeTimeline
     [ "count"
     , "since_id"
@@ -134,11 +134,11 @@
 -- @
 --
 -- >>> retweetsOfMe
--- APIRequestGet "https://api.twitter.com/1.1/statuses/retweets_of_me.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" []
 -- >>> retweetsOfMe & count ?~ 100
--- APIRequestGet "https://api.twitter.com/1.1/statuses/retweets_of_me.json" [("count","100")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets_of_me.json" [("count","100")]
 retweetsOfMe :: APIRequest StatusesRetweetsOfMe [Status]
-retweetsOfMe = APIRequestGet (endpoint ++ "statuses/retweets_of_me.json") def
+retweetsOfMe = APIRequest "GET" (endpoint ++ "statuses/retweets_of_me.json") def
 deriveHasParamInstances ''StatusesRetweetsOfMe
     [ "count"
     , "since_id"
@@ -160,11 +160,11 @@
 -- @
 --
 -- >>> retweetsId 1234567890
--- APIRequestGet "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" []
 -- >>> retweetsId 1234567890 & count ?~ 100
--- APIRequestGet "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" [("count","100")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/retweets/1234567890.json" [("count","100")]
 retweetsId :: StatusId -> APIRequest StatusesRetweetsId [RetweetedStatus]
-retweetsId status_id = APIRequestGet uri def
+retweetsId status_id = APIRequest "GET" uri def
   where uri = endpoint ++ "statuses/retweets/" ++ show status_id ++ ".json"
 deriveHasParamInstances ''StatusesRetweetsId
     [ "count"
@@ -181,11 +181,11 @@
 -- @
 --
 -- >>> showId 1234567890
--- APIRequestGet "https://api.twitter.com/1.1/statuses/show/1234567890.json" []
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/show/1234567890.json" []
 -- >>> showId 1234567890 & includeMyRetweet ?~ True
--- APIRequestGet "https://api.twitter.com/1.1/statuses/show/1234567890.json" [("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 = APIRequestGet uri def
+showId status_id = APIRequest "GET" uri def
   where uri = endpoint ++ "statuses/show/" ++ show status_id ++ ".json"
 deriveHasParamInstances ''StatusesShowId
     [ "trim_user"
@@ -204,9 +204,9 @@
 -- @
 --
 -- >>> destroyId 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/statuses/destroy/1234567890.json" []
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/destroy/1234567890.json" []
 destroyId :: StatusId -> APIRequest StatusesDestroyId Status
-destroyId status_id = APIRequestPost uri def
+destroyId status_id = APIRequest "POST" uri def
   where uri = endpoint ++ "statuses/destroy/" ++ show status_id ++ ".json"
 deriveHasParamInstances ''StatusesDestroyId
     [ "trim_user"
@@ -223,11 +223,11 @@
 -- @
 --
 -- >>> update "Hello World"
--- APIRequestPost "https://api.twitter.com/1.1/statuses/update.json" [("status","Hello World")]
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/update.json" [("status","Hello World")]
 -- >>> update "Hello World" & inReplyToStatusId ?~ 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/statuses/update.json" [("in_reply_to_status_id","1234567890"),("status","Hello World")]
+-- 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 = APIRequestPost uri [("status", PVString status)]
+update status = APIRequest "POST" uri [("status", PVString status)]
   where uri = endpoint ++ "statuses/update.json"
 deriveHasParamInstances ''StatusesUpdate
     [ "in_reply_to_status_id"
@@ -248,9 +248,9 @@
 -- @
 --
 -- >>> retweetId 1234567890
--- APIRequestPost "https://api.twitter.com/1.1/statuses/retweet/1234567890.json" []
+-- APIRequest "POST" "https://api.twitter.com/1.1/statuses/retweet/1234567890.json" []
 retweetId :: StatusId -> APIRequest StatusesRetweetId RetweetedStatus
-retweetId status_id = APIRequestPost uri def
+retweetId status_id = APIRequest "POST" uri def
   where uri = endpoint ++ "statuses/retweet/" ++ show status_id ++ ".json"
 deriveHasParamInstances ''StatusesRetweetId
     [ "trim_user"
@@ -266,12 +266,12 @@
 -- @
 --
 -- >>> updateWithMedia "Hello World" (MediaFromFile "/home/fuga/test.jpeg")
--- APIRequestPostMultipart "https://api.twitter.com/1.1/statuses/update_with_media.json" [("status","Hello World")]
+-- 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 =
-    APIRequestPostMultipart uri [("status", PVString tweet)] [mediaBody mediaData]
+    APIRequestMultipart "POST" uri [("status", PVString tweet)] [mediaBody mediaData]
   where
     uri = endpoint ++ "statuses/update_with_media.json"
     mediaBody (MediaFromFile fp) = partFileSource "media[]" fp
@@ -294,13 +294,13 @@
 -- @
 --
 -- >>> lookup [10]
--- APIRequestGet "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10")]
 -- >>> lookup [10, 432656548536401920]
--- APIRequestGet "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10,432656548536401920")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("id","10,432656548536401920")]
 -- >>> lookup [10, 432656548536401920] & includeEntities ?~ True
--- APIRequestGet "https://api.twitter.com/1.1/statuses/lookup.json" [("include_entities","true"),("id","10,432656548536401920")]
+-- APIRequest "GET" "https://api.twitter.com/1.1/statuses/lookup.json" [("include_entities","true"),("id","10,432656548536401920")]
 lookup :: [StatusId] -> APIRequest StatusesLookup [Status]
-lookup ids = APIRequestGet (endpoint ++ "statuses/lookup.json") [("id", PVIntegerArray ids)]
+lookup ids = APIRequest "GET" (endpoint ++ "statuses/lookup.json") [("id", PVIntegerArray ids)]
 deriveHasParamInstances ''StatusesLookup
     [ "include_entities"
     , "trim_user"
diff --git a/Web/Twitter/Conduit/Stream.hs b/Web/Twitter/Conduit/Stream.hs
--- a/Web/Twitter/Conduit/Stream.hs
+++ b/Web/Twitter/Conduit/Stream.hs
@@ -104,7 +104,7 @@
 
 data Userstream
 userstream :: APIRequest Userstream StreamingAPI
-userstream = APIRequestGet "https://userstream.twitter.com/1.1/user.json" []
+userstream = APIRequest "GET" "https://userstream.twitter.com/1.1/user.json" []
 deriveHasParamInstances ''Userstream
     [ "language"
     , "filter_level"
@@ -119,13 +119,13 @@
 -- | Returns statuses/filter.json API query data.
 --
 -- >>> statusesFilter [Follow [1,2,3]]
--- APIRequestPost "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3")]
+-- APIRequest "POST" "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3")]
 -- >>> statusesFilter [Track ["haskell","functional"]]
--- APIRequestPost "https://stream.twitter.com/1.1/statuses/filter.json" [("track","haskell,functional")]
+-- APIRequest "POST" "https://stream.twitter.com/1.1/statuses/filter.json" [("track","haskell,functional")]
 -- >>> statusesFilter [Follow [1,2,3],Track ["haskell","functional"]]
--- APIRequestPost "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3"),("track","haskell,functional")]
+-- APIRequest "POST" "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3"),("track","haskell,functional")]
 statusesFilter :: [FilterParameter] -> APIRequest StatusesFilter StreamingAPI
-statusesFilter = APIRequestPost statusesFilterEndpoint . L.map paramToQueryItem
+statusesFilter fs = APIRequest "POST" statusesFilterEndpoint (L.map paramToQueryItem fs)
 
 paramToQueryItem :: FilterParameter -> APIQueryItem
 paramToQueryItem (Follow userIds) = ("follow", PVIntegerArray userIds)
@@ -139,14 +139,14 @@
 -- | Returns statuses/filter.json API query data.
 --
 -- >>> statusesFilterByFollow [1,2,3]
--- APIRequestPost "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3")]
+-- APIRequest "POST" "https://stream.twitter.com/1.1/statuses/filter.json" [("follow","1,2,3")]
 statusesFilterByFollow :: [UserId] -> APIRequest StatusesFilter StreamingAPI
 statusesFilterByFollow userIds = statusesFilter [Follow userIds]
 
 -- | Returns statuses/filter.json API query data.
 --
 -- >>> statusesFilterByTrack "haskell"
--- APIRequestPost "https://stream.twitter.com/1.1/statuses/filter.json" [("track","haskell")]
+-- APIRequest "POST" "https://stream.twitter.com/1.1/statuses/filter.json" [("track","haskell")]
 statusesFilterByTrack :: T.Text -- ^ keyword
                       -> APIRequest StatusesFilter StreamingAPI
 statusesFilterByTrack keyword = statusesFilter [Track [keyword]]
diff --git a/sample/simple.hs b/sample/simple.hs
--- a/sample/simple.hs
+++ b/sample/simple.hs
@@ -34,8 +34,9 @@
 
 getTWInfo :: Manager -> IO TWInfo
 getTWInfo mgr = do
-    cred <- authorize tokens getPIN mgr
-    return $ setCredential tokens cred def
+    Credential cred <- authorize tokens getPIN mgr
+    let cred' = filter (\(k, _) -> k == "oauth_token" || k == "oauth_token_secret") cred
+    return $ setCredential tokens (Credential cred') def
   where
     getPIN url = do
         putStrLn $ "browse URL: " ++ url
diff --git a/twitter-conduit.cabal b/twitter-conduit.cabal
--- a/twitter-conduit.cabal
+++ b/twitter-conduit.cabal
@@ -1,5 +1,5 @@
 name:              twitter-conduit
-version:           0.3.0
+version:           0.4.0
 license:           BSD3
 license-file:      LICENSE
 author:            HATTORI Hiroki, Hideyuki Tanaka, Takahiro HIMURA
@@ -11,7 +11,7 @@
 build-type:        Custom
 homepage:          https://github.com/himura/twitter-conduit
 
-tested-with:       GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3
+tested-with:       GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5
 
 description:
   This package provides bindings to Twitter's APIs (see <https://dev.twitter.com/>).
@@ -26,7 +26,6 @@
 extra-source-files:
   .gitignore
   .travis.yml
-  .travis/*.sh
   README.md
   ChangeLog.md
   Warning.hs
@@ -44,10 +43,6 @@
   description: Get Network.URI from the network-uri package
   default: True
 
-flag lens-aeson
-  description: Get Data.Aeson.Lens from the lens-aeson package
-  default: True
-
 flag run-integrated-test
   description: use debug output when running testsuites
   default: False
@@ -56,35 +51,29 @@
   ghc-options: -Wall
 
   build-depends:
-      base >= 4.5 && < 5
-    , transformers >= 0.2.2
-    , transformers-base
-    , template-haskell
-    , exceptions >= 0.5
+      base >= 4.9 && < 5
+    , aeson >= 0.7.0.5
+    , attoparsec >= 0.10
     , authenticate-oauth >= 1.3
-    , resourcet >= 1.0
+    , bytestring >= 0.10.2
     , conduit >= 1.1
     , conduit-extra >= 1.1
-    , http-types
-    , http-conduit >= 2.0 && < 2.4
-    , http-client >= 0.3.0
-    , aeson >= 0.7.0.5
-    , attoparsec >= 0.10
+    , containers
     , data-default >= 0.3
-    , bytestring >= 0.10.2
+    , exceptions >= 0.5
+    , http-client >= 0.3.0
+    , http-conduit >= 2.0 && < 2.4
+    , http-types
+    , lens >= 4.4
+    , lens-aeson >= 1
+    , resourcet >= 1.0
+    , template-haskell
     , text >= 0.11
-    , containers
     , time
-    , twitter-types >= 0.6
-    , twitter-types-lens >= 0.6
-
-  if flag(lens-aeson)
-    build-depends:
-        lens-aeson >= 1
-      , lens >= 4.4
-  else
-    build-depends:
-        lens >= 4.0 && < 4.4
+    , transformers >= 0.2.2
+    , transformers-base
+    , twitter-types >= 0.9
+    , twitter-types-lens >= 0.9
 
   exposed-modules:
     Web.Twitter.Conduit
@@ -132,38 +121,37 @@
   if flag(run-integrated-test)
     CPP-Options: -DRUN_INTEGRATED_TEST
 
-  build-tool-depends: hspec-discover:hspec-discover >= 2.3.0 && < 2.5
+  build-tool-depends: hspec-discover:hspec-discover >= 2.3.0
   build-depends:
-      base >= 4.5 && < 5
-    , template-haskell
-    , lens
-    , bytestring
-    , time
-    , text
+      base
     , aeson
-    , attoparsec >= 0.10
-    , data-default
-    , resourcet
-    , conduit
-    , conduit-extra >= 1.1
-    , http-types
-    , http-conduit
-    , http-client
+    , attoparsec
     , authenticate-oauth
+    , bytestring
     , case-insensitive
+    , conduit
+    , conduit-extra
     , containers
+    , data-default
     , hspec
-    , twitter-types >= 0.6
-    , twitter-types-lens >= 0.6
+    , http-client
+    , http-conduit
+    , http-types
+    , lens
+    , lens-aeson
+    , resourcet
+    , template-haskell
+    , text
+    , time
     , twitter-conduit
+    , twitter-types
+    , twitter-types-lens
 
   if flag(network-uri)
     build-depends: network-uri >= 2.6
   else
     build-depends: network < 2.6
 
-  if flag(lens-aeson)
-    build-depends: lens-aeson >= 1
 
   other-modules:
     Spec
@@ -176,6 +164,6 @@
 
 custom-setup
   setup-depends:
-    base >= 4.5 && <5,
-    Cabal >= 1.24,
-    cabal-doctest >= 1 && < 1.1
+      base
+    , Cabal >= 1.24
+    , cabal-doctest >= 1 && < 1.1
