diff --git a/Hastodon.cabal b/Hastodon.cabal
--- a/Hastodon.cabal
+++ b/Hastodon.cabal
@@ -1,5 +1,5 @@
 Name: Hastodon
-Version: 0.0.1
+Version: 0.0.2
 Synopsis: mastodon client module for Haskell
 Category: Web
 Description: mastodon client module for Haskell
diff --git a/Web/Hastodon.hs b/Web/Hastodon.hs
--- a/Web/Hastodon.hs
+++ b/Web/Hastodon.hs
@@ -1,7 +1,21 @@
 module Web.Hastodon
   (
-    mkHastodonClient
+    Account(..)
+  , Application(..)
+  , Attachment(..)
+  , Card(..)
+  , Context(..)
+  , Instance(..)
+  , Mention(..)
+  , Notification(..)
+  , OAuthClient(..)
+  , Relationship(..)
+  , Report(..)
+  , Results(..)
+  , Status(..)
+  , Tag(..)
 
+  , mkHastodonClient
   , getAccountById
   , getCurrentAccount
   , getFollowers
@@ -101,6 +115,14 @@
   token :: String
 }
 
+data OAuthResponse = OAuthResponse {
+  accessToken :: String
+  -- NOTE currently ignore other fields.
+} deriving (Show)
+instance FromJSON OAuthResponse where
+  parseJSON (Object v) =
+    OAuthResponse <$> (v .: T.pack "access_token")
+
 data Account = Account {
   accountId :: Int,
   accountUsername :: String,
@@ -333,6 +355,19 @@
 -- helpers
 -- 
 
+getOAuthToken :: String -> String -> String -> String -> String -> IO (Either JSONException OAuthResponse)
+getOAuthToken clientId clientSecret username password host = do
+  initReq <- parseRequest $ "https://" ++ host ++ "/oauth/token"
+  let reqBody = [(Char8.pack "client_id", Char8.pack clientId),
+                 (Char8.pack "client_secret", Char8.pack clientSecret),
+                 (Char8.pack "username", Char8.pack username),
+                 (Char8.pack "password", Char8.pack password),
+                 (Char8.pack "grant_type", Char8.pack "password"),
+                 (Char8.pack "scope", Char8.pack "read write follow")]
+  let req = setRequestBodyURLEncoded reqBody $ initReq
+  res <- httpJSONEither req
+  return $ (getResponseBody res :: Either JSONException OAuthResponse)
+
 mkHastodonHeader :: String -> Request -> Request
 mkHastodonHeader token =
   addRequestHeader hAuthorization $ Char8.pack $ "Bearer " ++ token
@@ -365,8 +400,12 @@
 -- exported functions
 -- 
 
-mkHastodonClient :: String -> String -> HastodonClient
-mkHastodonClient host token = HastodonClient host token
+mkHastodonClient :: String -> String -> String -> String -> String -> IO (Maybe HastodonClient)
+mkHastodonClient clientId clientSecret username password host = do
+  oauthRes <- getOAuthToken clientId clientSecret username password host
+  case oauthRes of
+    Left err -> return $ Nothing
+    Right oauthData -> return $ Just $ HastodonClient host (accessToken oauthData)
 
 getAccountById :: Int -> HastodonClient -> IO (Either JSONException Account)
 getAccountById id client = do
@@ -436,12 +475,14 @@
   res <- postAndGetHastodonResponseJSON (replace ":id" (show id) pUnmute) [] client
   return (getResponseBody res :: Either JSONException Relationship)
 
-postApps :: String -> HastodonClient -> IO (Either JSONException OAuthClient)
-postApps clientName client = do
+postApps :: String -> String -> IO (Either JSONException OAuthClient)
+postApps host clientName = do
   let reqBody = [(Char8.pack "client_name", Char8.pack clientName),
                  (Char8.pack "redirect_uris", Char8.pack "urn:ietf:wg:oauth:2.0:oob"),
                  (Char8.pack "scopes", Char8.pack "read write follow")]
-  res <- postAndGetHastodonResponseJSON pApps reqBody client
+  initReq <- parseRequest $ "https://" ++ host ++ pApps
+  let req = setRequestBodyURLEncoded reqBody $ initReq
+  res <- httpJSONEither req
   return (getResponseBody res :: Either JSONException OAuthClient)
 
 getBlocks :: HastodonClient -> IO (Either JSONException [Account])
