diff --git a/src/Toxiproxy.hs b/src/Toxiproxy.hs
--- a/src/Toxiproxy.hs
+++ b/src/Toxiproxy.hs
@@ -1,6 +1,8 @@
-{-# LANGUAGE DataKinds     #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DataKinds                  #-}
+{-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings          #-}
 module Toxiproxy
     ( getVersion
     , postReset
@@ -18,56 +20,85 @@
     , Proxy(..)
     , Toxic(..)
     , Populate(..)
+    , Version(..)
+    , Stream(..)
+    , ToxicType(..)
     , toxiproxyUrl
     , withDisabled
     , withToxic
     , withProxy
     , run
-    , Version
     ) where
 
 import Servant.API
 import Servant.Client
 import qualified Data.Proxy as Proxy
-import Data.Text (Text)
+import Data.Text (Text, pack, toLower, unpack)
 import Data.List (stripPrefix)
-import Data.Char (toLower)
+import qualified Data.Char as Char (toLower)
 import GHC.Generics
 import Data.Aeson (FromJSON, parseJSON, fieldLabelModifier, defaultOptions, genericParseJSON,
-                   ToJSON, genericToJSON, toJSON)
+                   ToJSON, genericToJSON, toJSON, FromJSONKey, Value( String ))
 import Data.Map.Strict (Map)
 import Network.HTTP.Client (newManager, defaultManagerSettings)
 import Control.Exception (bracket)
 import Control.Monad (void)
+import Data.String (IsString)
 
 type ToxiproxyAPI =
        "version"  :> Get '[PlainText] Version
   :<|> "reset"    :> Post '[] NoContent
-  :<|> "proxies"  :> Get '[JSON] (Map Text Proxy)
-  :<|> "proxies"  :> ReqBody '[JSON] Proxy :> Post '[JSON] Proxy
-  :<|> "proxies"  :> Capture "name" Text :> Get '[JSON] Proxy
-  :<|> "populate" :> ReqBody '[JSON] [Proxy] :> Post '[JSON] Populate
-  :<|> "proxies"  :> Capture "name" Text :> ReqBody '[JSON] Proxy :> Post '[JSON] Proxy
-  :<|> "proxies"  :> Capture "name" Text :> Delete '[] NoContent
-  :<|> "proxies"  :> Capture "name" Text :>
+  :<|> "proxies"  :> Get '[JSON] (Map ProxyName Proxy)
+  :<|> "proxies"  :> ReqBody '[JSON] Proxy    :> Post '[JSON] Proxy
+  :<|> "proxies"  :> Capture "name" ProxyName :> Get '[JSON] Proxy
+  :<|> "populate" :> ReqBody '[JSON] [Proxy]  :> Post '[JSON] Populate
+  :<|> "proxies"  :> Capture "name" ProxyName :> ReqBody '[JSON] Proxy :> Post '[JSON] Proxy
+  :<|> "proxies"  :> Capture "name" ProxyName :> Delete '[] NoContent
+  :<|> "proxies"  :> Capture "name" ProxyName :>
        "toxics"   :> Get '[JSON] [Toxic]
-  :<|> "proxies"  :> Capture "name" Text :>
-       "toxics"   :> ReqBody '[JSON] Toxic :> Post '[JSON] Toxic
-  :<|> "proxies"  :> Capture "name" Text :>
-       "toxics"   :> Capture "name" Text :> Get '[JSON] Toxic
-  :<|> "proxies"  :> Capture "name" Text :>
-       "toxics"   :> Capture "name" Text :> ReqBody '[JSON] Toxic :> Get '[JSON] Toxic
-  :<|> "proxies"  :> Capture "name" Text :>
-       "toxics"   :> Capture "name" Text :> Delete '[JSON] NoContent
+  :<|> "proxies"  :> Capture "name" ProxyName :>
+       "toxics"   :> ReqBody '[JSON] Toxic    :> Post '[JSON] Toxic
+  :<|> "proxies"  :> Capture "name" ProxyName :>
+       "toxics"   :> Capture "name" ToxicName :> Get '[JSON] Toxic
+  :<|> "proxies"  :> Capture "name" ProxyName :>
+       "toxics"   :> Capture "name" ToxicName :> ReqBody '[JSON] Toxic :> Get '[JSON] Toxic
+  :<|> "proxies"  :> Capture "name" ProxyName :>
+       "toxics"   :> Capture "name" ToxicName :> Delete '[JSON] NoContent
 
-type Version = Text
+-- | A unique string for identifying a proxy on the server.
+newtype ProxyName = ProxyName Text
+  deriving (Show, Eq, IsString, Ord, Generic, ToHttpApiData, FromJSONKey)
 
+instance FromJSON ProxyName
+instance ToJSON   ProxyName
+
+-- | A unique string for identifying a toxic on a proxy.
+newtype ToxicName = ToxicName Text
+  deriving (Show, Eq, IsString, Generic, ToHttpApiData)
+
+instance FromJSON ToxicName
+instance ToJSON   ToxicName
+
+-- | The version of the Toxiproxy server. This library is fully supported by any version
+--   greater or equal to 2.1.3.
+newtype Version = Version Text
+  deriving (Show, Eq, MimeUnrender PlainText)
+
+-- | A Toxiproxy proxy. It forwards TCP connections between a listen and upstream host.
+--   Toxics can be injected into the proxy to simulate network failure.
 data Proxy = Proxy
-  { proxyName     :: Text
-  , proxyListen   :: Text
-  , proxyUpstream :: Text
+  { proxyName     :: ProxyName
+  -- ^ A unique human readable name to identify a proxy.
+  , proxyListen   :: Host
+  -- ^ The proxy listens on this host:port.
+  , proxyUpstream :: Host
+  -- ^ The proxy forwards to this upstream host:port.
   , proxyEnabled  :: Bool
+  -- ^ Whether a proxy is currently listening / accepting connections.
   , proxyToxics   :: [Toxic]
+  -- ^ The toxics currently applied to the proxy. These should not be specified when
+  --   initially creating a proxy. They must be created seperately with 'createToxic'
+  --   or 'withToxic'.
   } deriving (Show, Eq, Generic)
 
 instance FromJSON Proxy where
@@ -80,12 +111,26 @@
     defaultOptions
       { fieldLabelModifier = stripPrefixJSON "proxy" }
 
+-- | A host:port pair to represent the entrence of a proxy or the upstream the proxy
+--   forwards to. For the best experience, provide 127.0.0.1 instead of localhost.
+type Host = Text
+
+-- | A toxic is applied to a proxy. It allows the user to simulate a specified kind of
+--   network failure on the proxy.
 data Toxic = Toxic
-  { toxicName       :: Text
-  , toxicType       :: Text
-  , toxicStream     :: Text
+  { toxicName       :: ToxicName
+  -- ^ A unique human readable name to identify a toxic.
+  , toxicType       :: ToxicType
+  -- ^ The type of toxic. For example "latency". Please refer to 'ToxicType' or the
+  -- Toxiproxy documentation for more information.
+  , toxicStream     :: Stream
+  -- ^ The direction on which the toxic is applied. Please refer to 'Stream'.
   , toxicToxicity   :: Float
+  -- ^ The strength that the toxic is applied to the proxy. Please refer to the Toxiproxy
+  --   documation.
   , toxicAttributes :: Map Text Int
+  -- ^ Attributes configure a toxic. They differ based on the 'ToxicType'. Please refer to
+  --   the Toxiproxy documentation.
   } deriving (Show, Eq, Generic)
 
 instance FromJSON Toxic where
@@ -98,6 +143,7 @@
     defaultOptions
       { fieldLabelModifier = stripPrefixJSON "toxic" }
 
+-- | The return value of the 'populate' endpoint.
 newtype Populate = Populate { populateProxies :: [Proxy] }
   deriving (Show, Eq, Generic)
 
@@ -106,41 +152,108 @@
     defaultOptions
       { fieldLabelModifier = stripPrefixJSON "populate" }
 
+-- | A toxic can be applied to the upstream or the downstream of a connection. Upstream is
+--   the stream traveling from the connecting client to the upstream server. Downstream is
+--   the stream traveling from the upstream server to the connecting client.
+data Stream = Upstream | Downstream
+  deriving (Show, Eq)
+
+instance ToJSON Stream where
+  toJSON Upstream   = String "upstream"
+  toJSON Downstream = String "downstream"
+
+instance FromJSON Stream where
+  parseJSON (String stream) =
+    case stream of
+      "upstream"   -> return Upstream
+      "downstream" -> return Downstream
+
+-- | Different toxic types simulate different kinds of failure. Different toxics require
+--   different attribute configuration. Please refer to the Toxiproxy documentation.
+data ToxicType =
+    Latency
+  | Bandwidth
+  | SlowClose
+  | Timeout
+  | Slicer
+  | LimitData
+  | Other Text
+  deriving (Show, Eq)
+
+instance ToJSON ToxicType where
+  toJSON Latency       = String "latency"
+  toJSON Bandwidth     = String "bandwidth"
+  toJSON SlowClose     = String "slow_close"
+  toJSON Timeout       = String "timeout"
+  toJSON Slicer        = String "slicer"
+  toJSON LimitData     = String "limit_data"
+  toJSON (Other other) = String other
+
+instance FromJSON ToxicType where
+  parseJSON (String toxicType) =
+    case toxicType of
+      "latency"   -> return Latency
+      "bandwidth" -> return Bandwidth
+      "slow_clos" -> return SlowClose
+      "timeout"   -> return Timeout
+      "slicer"    -> return Slicer
+      "limit_dat" -> return LimitData
+      other       -> return . Other $ other
+
 stripPrefixJSON :: String -> String -> String
 stripPrefixJSON prefix str =
   case stripPrefix prefix str of
     Nothing             -> str
-    Just (first : rest) -> toLower first : rest
+    Just (first : rest) -> Char.toLower first : rest
 
 toxiproxyAPI :: Proxy.Proxy ToxiproxyAPI
 toxiproxyAPI = Proxy.Proxy
 
 getVersion   :: ClientM Version
 postReset    :: ClientM NoContent
-getProxies   :: ClientM (Map Text Proxy)
+getProxies   :: ClientM (Map ProxyName Proxy)
 createProxy  :: Proxy -> ClientM Proxy
-getProxy     :: Text -> ClientM Proxy
+getProxy     :: ProxyName -> ClientM Proxy
 postPopulate :: [Proxy] -> ClientM Populate
-updateProxy  :: Text -> Proxy -> ClientM Proxy
-deleteProxy  :: Text -> ClientM NoContent
-getToxics    :: Text -> ClientM [Toxic]
-createToxic  :: Text -> Toxic -> ClientM Toxic
-getToxic     :: Text -> Text -> ClientM Toxic
-updateToxic  :: Text -> Text -> Toxic -> ClientM Toxic
-deleteToxic  :: Text -> Text -> ClientM NoContent
+updateProxy  :: ProxyName -> Proxy -> ClientM Proxy
+deleteProxy  :: ProxyName -> ClientM NoContent
+getToxics    :: ProxyName -> ClientM [Toxic]
+createToxic  :: ProxyName -> Toxic -> ClientM Toxic
+getToxic     :: ProxyName -> ToxicName -> ClientM Toxic
+updateToxic  :: ProxyName -> ToxicName -> Toxic -> ClientM Toxic
+deleteToxic  :: ProxyName -> ToxicName -> ClientM NoContent
 
 (getVersion :<|> postReset :<|> getProxies :<|> createProxy :<|> getProxy :<|> postPopulate
             :<|> updateProxy :<|> deleteProxy :<|> getToxics :<|> createToxic :<|> getToxic
             :<|> updateToxic :<|> deleteToxic) = client toxiproxyAPI
 
+-- | The default Toxiproxy service URL.
+--   (127.0.0.1:8474)
 toxiproxyUrl :: BaseUrl
 toxiproxyUrl = BaseUrl Http "127.0.0.1" 8474 ""
 
+-- | A helper for easily querying the Toxiproxy API. Assumes Toxiproxy is running on
+--  'toxiproxyUrl'.
+--
+-- @
+-- proxies <- run getProxies
+-- @
 run :: ClientM a -> IO (Either ServantError a)
 run f = do
   manager <- newManager defaultManagerSettings
   runClientM f (ClientEnv manager toxiproxyUrl)
 
+-- | Given an enabled proxy, disable the proxy, run the given action and then re-enable
+--   the proxy.
+--
+--   This is useful for simulating a crashed server or closed connection.
+--
+-- @
+-- connectToMyProxy       -- This will connect.
+-- withDisabled myProxy $
+--   connectToMyProxy     -- This will get rejected.
+-- connectToMyProxy       -- This will connect again.
+-- @
 withDisabled :: Proxy -> IO a -> IO a
 withDisabled proxy f =
   bracket disable enable $ const f
@@ -149,6 +262,15 @@
     disable       = void . run $ updateProxy (proxyName proxy) disabledProxy
     disabledProxy = proxy { proxyEnabled = False }
 
+-- | Given a proxy and a toxic, create the toxic on the proxy, run the given action and
+--   then delete the toxic.
+--
+--   This is useful for running some action with a toxic enabled.
+--
+-- @
+-- withToxic myProxy latencyToxic $
+--   sendRequestThroughProxy -- This request will have latency applied to it.
+-- @
 withToxic :: Proxy -> Toxic -> IO a -> IO a
 withToxic proxy toxic f =
   bracket enable disable $ const f
@@ -156,6 +278,11 @@
     enable = void . run $ createToxic (proxyName proxy) toxic
     disable = const . run $ deleteToxic (proxyName proxy) (toxicName toxic)
 
+-- | Given a proxy record, create the proxy on the server, run the given action and then
+--   delete the proxy off the server.
+--
+--   This is useful for wrapping 'withDisabled' and 'withToxic' calls. It enures that your
+--   test cleans up the Toxiproxy server so that proxies don't leak into your other tests.
 withProxy :: Proxy -> (Proxy -> IO a) -> IO a
 withProxy proxy =
   bracket create delete
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -64,8 +64,8 @@
         let toxicName = "latency"
         let toxic = Toxic
               { toxicName       = toxicName
-              , toxicType       = toxicName
-              , toxicStream     = "upstream"
+              , toxicType       = Latency
+              , toxicStream     = Upstream
               , toxicToxicity   = 1
               , toxicAttributes = Map.fromList [("latency", 1000), ("jitter", 0)]
               }
@@ -113,8 +113,8 @@
               }
         let toxic = Toxic
               { toxicName       = "latency"
-              , toxicType       = "latency"
-              , toxicStream     = "upstream"
+              , toxicType       = Latency
+              , toxicStream     = Upstream
               , toxicToxicity   = 1
               , toxicAttributes = Map.fromList [("latency", 1000), ("jitter", 0)]
               }
@@ -136,7 +136,7 @@
     server = proc "toxiproxy-server" []
 
 version :: Version
-version = "git-fe6bf4f"
+version = Version "git-fe6bf4f"
 
 proxyUrl :: BaseUrl
 proxyUrl = BaseUrl Http "127.0.0.1" 4444 ""
diff --git a/toxiproxy-haskell.cabal b/toxiproxy-haskell.cabal
--- a/toxiproxy-haskell.cabal
+++ b/toxiproxy-haskell.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 5cb73d2ae60bbc8465572da4b0035b5ad27b03f3c50e79f4af4eae94ab5783f3
+-- hash: d0e71416ad274526a7e079fcae1e0d802defc1f7a0e5e9e03dcfd872153b1dd2
 
 name:           toxiproxy-haskell
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       Client library for Toxiproxy: a TCP failure testing proxy.
 description:    Please see the README on Github at <https://github.com/jpittis/toxiproxy-haskell#readme>
 category:       web
