diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2016-2017 itchyny <https://github.com/itchyny>
+Copyright (c) 2016-2020 itchyny <https://github.com/itchyny>
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/mackerel-client.cabal b/mackerel-client.cabal
--- a/mackerel-client.cabal
+++ b/mackerel-client.cabal
@@ -1,5 +1,5 @@
 name:                   mackerel-client
-version:                0.2.0
+version:                0.3.0
 author:                 itchyny
 maintainer:             itchyny <itchyny@hatena.ne.jp>
 license:                MIT
@@ -7,7 +7,7 @@
 category:               Web
 stability:              Experimental
 build-type:             Simple
-cabal-version:          >=1.8
+cabal-version:          >=1.10
 synopsis:               An API client library for Mackerel
 homepage:               https://github.com/itchyny/mackerel-client-hs
 description:            This library provides bindings to Mackerel APIs.
@@ -19,6 +19,7 @@
 library
   hs-source-dirs:       src
   ghc-options:          -Wall
+  default-language:     Haskell2010
   exposed-modules:      Web.Mackerel
                       , Web.Mackerel.Types
                       , Web.Mackerel.Types.Organization
@@ -71,6 +72,7 @@
   main-is:              Spec.hs
   type:                 exitcode-stdio-1.0
   ghc-options:          -Wall
+  default-language:     Haskell2010
   other-modules:        Types.OrganizationSpec
                       , Types.UserSpec
                       , Types.InvitationSpec
diff --git a/src/Web/Mackerel/Api/Alert.hs b/src/Web/Mackerel/Api/Alert.hs
--- a/src/Web/Mackerel/Api/Alert.hs
+++ b/src/Web/Mackerel/Api/Alert.hs
@@ -5,7 +5,6 @@
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.HashMap.Lazy as HM
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/Dashboard.hs b/src/Web/Mackerel/Api/Dashboard.hs
--- a/src/Web/Mackerel/Api/Dashboard.hs
+++ b/src/Web/Mackerel/Api/Dashboard.hs
@@ -10,7 +10,6 @@
 
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/GraphAnnotation.hs b/src/Web/Mackerel/Api/GraphAnnotation.hs
--- a/src/Web/Mackerel/Api/GraphAnnotation.hs
+++ b/src/Web/Mackerel/Api/GraphAnnotation.hs
@@ -9,7 +9,6 @@
 
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/Host.hs b/src/Web/Mackerel/Api/Host.hs
--- a/src/Web/Mackerel/Api/Host.hs
+++ b/src/Web/Mackerel/Api/Host.hs
@@ -17,7 +17,6 @@
 import Data.Default (Default(..))
 import qualified Data.HashMap.Lazy as HM
 import Data.Maybe (maybeToList)
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/Invitation.hs b/src/Web/Mackerel/Api/Invitation.hs
--- a/src/Web/Mackerel/Api/Invitation.hs
+++ b/src/Web/Mackerel/Api/Invitation.hs
@@ -10,7 +10,7 @@
 import Web.Mackerel.Internal.Api
 import Web.Mackerel.Types.Invitation
 
-createInvitation :: Client -> Invitation -> IO (Either ApiError Invitation)
+createInvitation :: Client -> InvitationCreate -> IO (Either ApiError Invitation)
 createInvitation client invitation
   = request client POST "/api/v0/invitations" [] (Just invitation) (createHandler id)
 
diff --git a/src/Web/Mackerel/Api/Metadata.hs b/src/Web/Mackerel/Api/Metadata.hs
--- a/src/Web/Mackerel/Api/Metadata.hs
+++ b/src/Web/Mackerel/Api/Metadata.hs
@@ -5,7 +5,6 @@
 import Data.Aeson (Value)
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/Monitor.hs b/src/Web/Mackerel/Api/Monitor.hs
--- a/src/Web/Mackerel/Api/Monitor.hs
+++ b/src/Web/Mackerel/Api/Monitor.hs
@@ -10,7 +10,6 @@
 import Data.Aeson (Value)
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/Role.hs b/src/Web/Mackerel/Api/Role.hs
--- a/src/Web/Mackerel/Api/Role.hs
+++ b/src/Web/Mackerel/Api/Role.hs
@@ -1,10 +1,13 @@
 {-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
 -- | Role API.
-module Web.Mackerel.Api.Role (listRoles) where
+module Web.Mackerel.Api.Role
+  ( listRoles
+  , createRole
+  , deleteRole
+  ) where
 
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
@@ -18,3 +21,11 @@
 listRoles :: Client -> String -> IO (Either ApiError [Role])
 listRoles client serviceName'
   = request client GET ("/api/v0/services/" <> BS.pack serviceName' <> "/roles") [] emptyBody (createHandler responseRoles)
+
+createRole :: Client -> String -> Role -> IO (Either ApiError Role)
+createRole client serviceName' role
+  = request client POST ("/api/v0/services/" <> BS.pack serviceName' <> "/roles") [] (Just role) (createHandler id)
+
+deleteRole :: Client -> String -> String -> IO (Either ApiError Role)
+deleteRole client serviceName' name
+  = request client DELETE ("/api/v0/services/" <> BS.pack serviceName' <> "/roles/" <> BS.pack name) [] emptyBody (createHandler id)
diff --git a/src/Web/Mackerel/Api/Service.hs b/src/Web/Mackerel/Api/Service.hs
--- a/src/Web/Mackerel/Api/Service.hs
+++ b/src/Web/Mackerel/Api/Service.hs
@@ -9,7 +9,6 @@
 
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Api/User.hs b/src/Web/Mackerel/Api/User.hs
--- a/src/Web/Mackerel/Api/User.hs
+++ b/src/Web/Mackerel/Api/User.hs
@@ -4,7 +4,6 @@
 
 import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString.Char8 as BS
-import Data.Semigroup ((<>))
 import Network.HTTP.Types (StdMethod(..))
 
 import Web.Mackerel.Client
diff --git a/src/Web/Mackerel/Internal/Api.hs b/src/Web/Mackerel/Internal/Api.hs
--- a/src/Web/Mackerel/Internal/Api.hs
+++ b/src/Web/Mackerel/Internal/Api.hs
@@ -7,8 +7,7 @@
 import Data.Aeson.Types (parseMaybe)
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.ByteString.Lazy as LBS
-import Data.Maybe (maybe, fromMaybe)
-import Data.Semigroup ((<>))
+import Data.Maybe (fromMaybe)
 import Network.HTTP.Client
 import Network.HTTP.Client.TLS (tlsManagerSettings)
 import Network.HTTP.Types (StdMethod, renderStdMethod, Query, statusCode)
diff --git a/src/Web/Mackerel/Types.hs b/src/Web/Mackerel/Types.hs
--- a/src/Web/Mackerel/Types.hs
+++ b/src/Web/Mackerel/Types.hs
@@ -1,6 +1,7 @@
 module Web.Mackerel.Types (module Types) where
 
 import Web.Mackerel.Types.Alert as Types
+import Web.Mackerel.Types.Authority as Types
 import Web.Mackerel.Types.Channel as Types
 import Web.Mackerel.Types.Dashboard as Types
 import Web.Mackerel.Types.GraphAnnotation as Types
diff --git a/src/Web/Mackerel/Types/Alert.hs b/src/Web/Mackerel/Types/Alert.hs
--- a/src/Web/Mackerel/Types/Alert.hs
+++ b/src/Web/Mackerel/Types/Alert.hs
@@ -13,14 +13,14 @@
 import Web.Mackerel.Types.Monitor (MonitorId, MonitorType)
 
 data AlertId = AlertId String
-            deriving (Eq, Show)
+             deriving (Eq, Show)
 
 instance FromJSON AlertId where
-  parseJSON (Aeson.String alertId) = return $ AlertId $ Text.unpack alertId
+  parseJSON (Aeson.String alertId') = return $ AlertId $ Text.unpack alertId'
   parseJSON o = typeMismatch "AlertId" o
 
 instance ToJSON AlertId where
-  toJSON (AlertId alertId) = toJSON alertId
+  toJSON (AlertId alertId') = toJSON alertId'
 
 data AlertStatus = AlertStatusOk
                  | AlertStatusCritical
diff --git a/src/Web/Mackerel/Types/Channel.hs b/src/Web/Mackerel/Types/Channel.hs
--- a/src/Web/Mackerel/Types/Channel.hs
+++ b/src/Web/Mackerel/Types/Channel.hs
@@ -13,11 +13,11 @@
                deriving (Eq, Show)
 
 instance FromJSON ChannelId where
-  parseJSON (Aeson.String channelId) = return $ ChannelId $ Text.unpack channelId
+  parseJSON (Aeson.String channelId') = return $ ChannelId $ Text.unpack channelId'
   parseJSON o = typeMismatch "ChannelId" o
 
 instance ToJSON ChannelId where
-  toJSON (ChannelId channelId) = toJSON channelId
+  toJSON (ChannelId channelId') = toJSON channelId'
 
 data Channel
   = Channel {
diff --git a/src/Web/Mackerel/Types/Invitation.hs b/src/Web/Mackerel/Types/Invitation.hs
--- a/src/Web/Mackerel/Types/Invitation.hs
+++ b/src/Web/Mackerel/Types/Invitation.hs
@@ -1,11 +1,8 @@
 {-# LANGUAGE TemplateHaskell #-}
 module Web.Mackerel.Types.Invitation where
 
-import Data.Aeson
-import qualified Data.Aeson as Aeson
-import Data.Aeson.TH (deriveJSON)
-import Data.Aeson.Types (typeMismatch)
-import qualified Data.Text as Text
+import Data.Aeson.TH (deriveJSON, fieldLabelModifier)
+import Data.Char (toLower)
 
 import Web.Mackerel.Internal.TH
 import Web.Mackerel.Types.Authority
@@ -13,7 +10,16 @@
 data Invitation
   = Invitation {
     invitationEmail :: String,
-    invitationAuthority :: Authority
+    invitationAuthority :: Authority,
+    invitationExpiresAt :: Integer
   } deriving (Eq, Show)
 
 $(deriveJSON options ''Invitation)
+
+data InvitationCreate
+  = InvitationCreate {
+    invitationCreateEmail :: String,
+    invitationCreateAuthority :: Authority
+  } deriving (Eq, Show)
+
+$(deriveJSON options { fieldLabelModifier = (\(c:cs) -> toLower c : cs) . drop 16 } ''InvitationCreate)
diff --git a/test/Types/InvitationSpec.hs b/test/Types/InvitationSpec.hs
--- a/test/Types/InvitationSpec.hs
+++ b/test/Types/InvitationSpec.hs
@@ -15,13 +15,15 @@
 
   let invitation' = Invitation {
         invitationEmail = "foobar@example.com",
-        invitationAuthority = AuthorityManager
+        invitationAuthority = AuthorityManager,
+        invitationExpiresAt = 1492393387
       }
 
   let json = [aesonQQ|
     {
       "email": "foobar@example.com",
-      "authority": "manager"
+      "authority": "manager",
+      "expiresAt": 1492393387
     }
   |]
 
@@ -32,9 +34,35 @@
     it "should reject an invalid json" $ do
       decode "{}" `shouldBe` (Nothing :: Maybe Invitation)
       let (Object hm) = json
-      forM_ ["email", "authority"] $ \key ->
+      forM_ ["email", "authority", "expiresAt"] $ \key ->
         decode (encode (Object (HM.delete key hm))) `shouldBe` (Nothing :: Maybe Invitation)
 
-  describe "invitation ToJSON" $
+  describe "Invitation ToJSON" $
     it "should encode into a json" $
       decode (encode invitation') `shouldBe` Just json
+
+  let invitationCreate' = InvitationCreate {
+        invitationCreateEmail = "foobar@example.com",
+        invitationCreateAuthority = AuthorityCollaborator
+      }
+
+  let jsonCreate = [aesonQQ|
+    {
+      "email": "foobar@example.com",
+      "authority": "collaborator"
+    }
+  |]
+
+  describe "InvitationCreate FromJSON" $ do
+    it "should parse a json" $
+      decode (encode jsonCreate) `shouldBe` Just invitationCreate'
+
+    it "should reject an invalid json" $ do
+      decode "{}" `shouldBe` (Nothing :: Maybe InvitationCreate)
+      let (Object hm) = jsonCreate
+      forM_ ["email", "authority"] $ \key ->
+        decode (encode (Object (HM.delete key hm))) `shouldBe` (Nothing :: Maybe InvitationCreate)
+
+  describe "InvitationCreate ToJSON" $
+    it "should encode into a json" $
+      decode (encode invitationCreate') `shouldBe` Just jsonCreate
