diff --git a/postmark.cabal b/postmark.cabal
--- a/postmark.cabal
+++ b/postmark.cabal
@@ -1,5 +1,5 @@
 Name:               postmark
-Version:            0.2.2
+Version:            0.2.3
 License:            BSD3
 License-File:       LICENSE
 Author:             Mark Hibberd <mark@hibberd.id.au>
diff --git a/src/Network/Api/Postmark.hs b/src/Network/Api/Postmark.hs
--- a/src/Network/Api/Postmark.hs
+++ b/src/Network/Api/Postmark.hs
@@ -7,11 +7,12 @@
 --
 -- Library for postmarkapp.com HTTP Api.
 --
--- To get start see some examples in the 'Network.Api.Postmark.Tutorial' module at <http://hackage.haskell.org/packages/archive/postmark/0.0.2/doc/html/Network-Api-Postmark-Tutorial.html>.
+-- To get start see some examples in the "Network.Api.Postmark.Tutorial" module.
 --
 -- Source and more information can be found at <https://github.com/apiengine/postmark>.
 --
 -- To experiment with a live demo try:
+--
 -- > $ git clone https://github.com/apiengine/postmark
 -- > $ cd postmark
 -- > $ cabal install --only-dependencies &&  cabal configure -f demo  && cabal build
@@ -19,11 +20,39 @@
 --
 -- Issues can be reported at <https://github.com/apiengine/postmark/issues>.
 --
-module Network.Api.Postmark (module X) where
+module Network.Api.Postmark (
 
-import Network.Api.Postmark.Core as X
-import Network.Api.Postmark.Data as X hiding (ojson, oljson, omjson, toText)
-import Network.Api.Postmark.Error as X
-import Network.Api.Postmark.Request as X
-import Network.Api.Postmark.Response as X
-import Network.Api.Postmark.Settings as X
+  -- * Settings
+  PostmarkSettings (..), PostmarkApiToken, postmarkHttp, postmarkHttps,
+  -- ** Using the test token
+  postmarkTestToken, postmarkHttpTest, postmarkHttpsTest,
+
+  -- * Sending email
+  email, emails, Email (..), defaultEmail,
+  -- ** Using a template
+  emailWithTemplate, EmailWithTemplate (..), defaultEmailWithTemplate,
+  -- ** Tracking links
+  TrackLinks (..),
+  -- ** Attachments
+  Attachment (..),
+  -- ** Response type
+  Sent (..),
+
+  -- * Error types
+  PostmarkError (..), PostmarkErrorType (..),
+
+  -- * Lower-level API
+  -- ** Request
+  request, PostmarkRequest (..), PostmarkRequest',
+  -- ** Response
+  PostmarkResponse (..), PostmarkUnexpectedType (..),
+  PostmarkResponse', syntaxErr, formatErr,
+
+) where
+
+import Network.Api.Postmark.Core
+import Network.Api.Postmark.Data
+import Network.Api.Postmark.Error
+import Network.Api.Postmark.Request
+import Network.Api.Postmark.Response
+import Network.Api.Postmark.Settings
diff --git a/src/Network/Api/Postmark/Core.hs b/src/Network/Api/Postmark/Core.hs
--- a/src/Network/Api/Postmark/Core.hs
+++ b/src/Network/Api/Postmark/Core.hs
@@ -1,9 +1,14 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Network.Api.Postmark.Core (
+
+  -- * API endpoints
   email,
   emails,
   emailWithTemplate,
+
+  -- * Run a request
   request
+
 ) where
 
 import qualified Data.ByteString.Lazy as BL
diff --git a/src/Network/Api/Postmark/Data.hs b/src/Network/Api/Postmark/Data.hs
--- a/src/Network/Api/Postmark/Data.hs
+++ b/src/Network/Api/Postmark/Data.hs
@@ -1,6 +1,32 @@
 {-# LANGUAGE OverloadedStrings, GADTSyntax #-}
-module Network.Api.Postmark.Data where
+module Network.Api.Postmark.Data (
 
+  -- * Request types
+
+  -- ** Email
+  Email (..),
+  defaultEmail,
+
+  -- ** Email with template
+  EmailWithTemplate (..),
+  defaultEmailWithTemplate,
+
+  -- ** Track links
+  TrackLinks (..),
+
+  -- ** Attachment
+  Attachment (..),
+
+  -- ** Response type
+  Sent (..),
+
+  -- * Internal Json tools
+  ojson,
+  oljson,
+  omjson,
+  toText
+) where
+
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.Text.Lazy as LT
 import qualified Data.Text.Lazy.Encoding as LE
@@ -37,11 +63,18 @@
   , emailAttachments :: [Attachment]
   }
 
+-- | When “link tracking” is enabled, Postmark will record statistics when a
+-- user clicks on a link in an email. You can use this feature to determine
+-- if a particular recipient has clicked a link that was emailed to them.
+--
+-- https://postmarkapp.com/developer/user-guide/tracking-links#enabling-link-tracking
 data TrackLinks
-  = None
-  | HtmlAndText
-  | HtmlOnly
-  | TextOnly
+  = None        -- ^ No links will be replaced or tracked.
+  | HtmlAndText -- ^ Links will be replaced in both HTML and text bodies.
+  | HtmlOnly    -- ^ Links will be replaced in only the HTML body. You may
+                --   want this option if you do not want encoded tracking
+                --   links to appear in the plain text of an email.
+  | TextOnly    -- ^ Links will be replaced in only the text body.
   deriving (Show)
 
 data Attachment = Attachment {
@@ -157,6 +190,7 @@
     , ojson "TrackLinks" (emailTrackLinks' v)
     , oljson "Attachments" (emailAttachments' v) id
     ])
+
 -- * Response types
 
 data Sent =
diff --git a/src/Network/Api/Postmark/Error.hs b/src/Network/Api/Postmark/Error.hs
--- a/src/Network/Api/Postmark/Error.hs
+++ b/src/Network/Api/Postmark/Error.hs
@@ -1,5 +1,8 @@
 {-# LANGUAGE OverloadedStrings, GADTSyntax #-}
-module Network.Api.Postmark.Error where
+module Network.Api.Postmark.Error (
+  PostmarkError (..),
+  PostmarkErrorType (..)
+) where
 
 import Data.Aeson
 import Data.Text
diff --git a/src/Network/Api/Postmark/Request.hs b/src/Network/Api/Postmark/Request.hs
--- a/src/Network/Api/Postmark/Request.hs
+++ b/src/Network/Api/Postmark/Request.hs
@@ -1,5 +1,8 @@
 {-# LANGUAGE GADTs, GADTSyntax #-}
-module Network.Api.Postmark.Request where
+module Network.Api.Postmark.Request (
+  PostmarkRequest (..),
+  PostmarkRequest'
+) where
 
 import Network.Api.Postmark.Error
 
diff --git a/src/Network/Api/Postmark/Response.hs b/src/Network/Api/Postmark/Response.hs
--- a/src/Network/Api/Postmark/Response.hs
+++ b/src/Network/Api/Postmark/Response.hs
@@ -1,4 +1,10 @@
-module Network.Api.Postmark.Response where
+module Network.Api.Postmark.Response (
+  PostmarkResponse (..),
+  PostmarkUnexpectedType (..),
+  PostmarkResponse',
+  syntaxErr,
+  formatErr
+) where
 
 import qualified Data.ByteString.Lazy as BL
 import Data.Text
diff --git a/src/Network/Api/Postmark/Settings.hs b/src/Network/Api/Postmark/Settings.hs
--- a/src/Network/Api/Postmark/Settings.hs
+++ b/src/Network/Api/Postmark/Settings.hs
@@ -1,25 +1,70 @@
 {-# LANGUAGE OverloadedStrings #-}
-module Network.Api.Postmark.Settings where
+module Network.Api.Postmark.Settings (
 
+  -- * Settings types
+  PostmarkSettings (..),
+  PostmarkApiToken,
+
+  -- * Settings construction
+  postmarkHttp,
+  postmarkHttps,
+
+  -- * Using the test token
+  postmarkTestToken,
+  postmarkHttpTest,
+  postmarkHttpsTest
+
+) where
+
 import Data.Text
 
+-- | The Postmark “server token” which is sent via the
+-- @X-Postmark-Server-Token@ HTTP header. You can find your server
+-- token under the “Credentials” tab on the Postmark website.
+--
+-- If you do not yet have a Postmark account, or if you want to send
+-- test emails that don't actually get delivered, you may use
+-- 'postmarkTestToken'.
+--
+-- https://postmarkapp.com/developer/api/overview#authentication
+type PostmarkApiToken = Text
+
+-- | To construct 'PostmarkSettings', use 'postmarkHttps' or
+-- 'postmarkHttp'.
+--
+-- Or to use the test API instead, use 'postmarkHttpsTest' or
+-- 'postmarkHttpTest'.
 data PostmarkSettings =
   PostmarkSettings {
       apiUrl :: Text
-    , apiToken :: Text
+    , apiToken :: PostmarkApiToken
     } deriving (Eq, Show)
 
-postmarkTestToken :: Text
+-- | An API token that you can use when you want to send test emails that
+-- don't actually get delivered to the recipient.
+--
+-- https://postmarkapp.com/developer/api/overview#authentication
+postmarkTestToken :: PostmarkApiToken
 postmarkTestToken = "POSTMARK_API_TEST"
 
+-- | Postmark settings using the HTTP protocol and the test API token
+-- ('postmarkTestToken').
+--
+-- HTTPS is recommended instead ('postmarkHttpsTest').
 postmarkHttpTest :: PostmarkSettings
 postmarkHttpTest = postmarkHttp postmarkTestToken
 
+-- | Postmark settings using the HTTPS protocol and the test API token
+-- ('postmarkTestToken').
 postmarkHttpsTest :: PostmarkSettings
 postmarkHttpsTest = postmarkHttps postmarkTestToken
 
-postmarkHttp :: Text -> PostmarkSettings
+-- | Constructs Postmark settings using the HTTP protocol and your API token.
+--
+-- HTTPS is recommended instead ('postmarkHttps').
+postmarkHttp :: PostmarkApiToken -> PostmarkSettings
 postmarkHttp = PostmarkSettings "http://api.postmarkapp.com"
 
-postmarkHttps :: Text -> PostmarkSettings
+-- | Constructs Postmark settings using the HTTPS protocol and your API token.
+postmarkHttps :: PostmarkApiToken -> PostmarkSettings
 postmarkHttps = PostmarkSettings "https://api.postmarkapp.com"
