diff --git a/liblastfm.cabal b/liblastfm.cabal
--- a/liblastfm.cabal
+++ b/liblastfm.cabal
@@ -1,5 +1,5 @@
 Name: liblastfm
-Version: 0.0.3.1
+Version: 0.0.3.2
 Synopsis: Wrapper to Lastfm API
 License: MIT
 License-file: LICENSE
@@ -11,7 +11,7 @@
 Build-Type: Simple
 
 Library
-  Build-Depends: base >= 3 && < 5, template-haskell == 2.7.*, bytestring == 0.9.*, mtl == 2.*, curl == 1.3.7, pureMD5 == 2.1.*, urlencoded == 0.3.*, aeson == 0.6.*, xml == 1.3.12, utf8-string == 0.3.*
+  Build-Depends: base >= 3 && < 5, template-haskell >= 2.5 && < 2.8, bytestring == 0.9.*, mtl == 2.*, curl == 1.3.7, pureMD5 == 2.1.*, urlencoded == 0.3.*, aeson == 0.6.*, xml == 1.3.12, utf8-string == 0.3.*
   HS-Source-Dirs: src
   Exposed-Modules: Network.Lastfm
                    Network.Lastfm.JSON.Album
@@ -44,8 +44,8 @@
                    Network.Lastfm.XML.Track
                    Network.Lastfm.XML.User
                    Network.Lastfm.XML.Venue
-  Other-Modules:   Network.Lastfm.TH
-                   Network.Lastfm.Types
+  Other-Modules:   Network.Lastfm.Internal
+                   Network.Lastfm.TH
                    Network.Lastfm.Error
                    Network.Lastfm.API.Album
                    Network.Lastfm.API.Artist
@@ -64,6 +64,8 @@
                    Network.Lastfm.API.Venue
   Extensions: UnicodeSyntax
   GHC-Options: -Wall
+               -fno-warn-unused-do-bind
+  CPP-Options: -Idocs
 
 source-repository head
   type:     git
diff --git a/src/Network/Lastfm.hs b/src/Network/Lastfm.hs
--- a/src/Network/Lastfm.hs
+++ b/src/Network/Lastfm.hs
@@ -1,73 +1,185 @@
-{-# LANGUAGE ScopedTypeVariables, TemplateHaskell #-}
--- | Response module
-{-# OPTIONS_HADDOCK not-home #-}
-module Network.Lastfm
-  ( Lastfm, Response, ResponseType(..)
-  , callAPI, callAPIsigned
-  , xml, json
-  , module Network.Lastfm.Types
-  ) where
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Network.Lastfm where
 
-import Codec.Binary.UTF8.String (encodeString)
-import Control.Applicative ((<$>))
-import Control.Arrow (second)
+import Control.Applicative ((<$>), empty)
+import Control.Monad (liftM)
+import Data.List (intercalate)
+import Data.Maybe (fromJust)
+
+import Data.Aeson ((.:), FromJSON, decode, parseJSON)
+import qualified Data.Aeson
 import Data.ByteString.Lazy.Char8 (ByteString)
-import Data.Digest.Pure.MD5 (md5)
-import Data.Function (on)
-import Data.List (sortBy)
-import Data.URLEncoded (urlEncode, export)
-import Language.Haskell.TH
-import Network.Curl
+
 import Network.Lastfm.Error
-import Network.Lastfm.Types
-import qualified Data.ByteString.Lazy.Char8 as BS
+import Network.Lastfm.TH
 
--- | Type synonym for Lastfm response or error.
+
 type Lastfm a = IO (Either LastfmError a)
--- | Type synonym for Lastfm response
 type Response = ByteString
--- | Desired type of Lastfm response
-data ResponseType = XML | JSON
 
--- | Low level function. Sends POST query to Lastfm API.
-callAPI ∷ ResponseType → [(String, String)] → Lastfm Response
-callAPI t = query (parseError t) . insertType t . map (second encodeString)
 
--- | Low level function. Sends signed POST query to Lastfm API.
-callAPIsigned ∷ ResponseType → Secret → [(String, String)] → Lastfm Response
-callAPIsigned t (Secret s) xs = query (parseError t) zs
-  where ys = map (second encodeString) . filter (not . null . snd) $ xs
-        zs = insertType t $ ("api_sig", sign ys) : ys
+newtype Secret = Secret String
 
-        sign ∷ [(String, String)] → String
-        sign = show . md5 . BS.pack . (++ s) . concatMap (uncurry (++)) . sortBy (compare `on` fst)
 
-insertType ∷ ResponseType → [(String, String)] → [(String, String)]
-insertType XML = id
-insertType JSON = (("format", "json") :)
+$(newtypes "String" ["Album", "AlbumArtist", "APIKey", "Artist", "AuthToken",
+  "Context", "Country", "Description", "Group", "Language", "Latitude",
+  "Location", "Longitude", "Mbid", "Message", "Method", "Metro", "Name",
+  "Recipient", "SessionKey", "Station", "StreamId", "Tag", "TaggingType",
+  "Title", "Token", "Track", "User", "Username", "Venuename", "ChosenByUser"])
+$(newtypes "Bool" ["Autocorrect", "BuyLinks", "Discovery", "FestivalsOnly", "Public", "RecentTracks", "RTP", "UseRecs"])
+$(newtypes "Int" ["Distance", "Duration", "Event", "Limit", "Page", "Playlist", "TrackNumber", "Venue"])
+$(newtypes "Integer" ["End", "EndTimestamp", "Fingerprint", "From", "Start", "StartTimestamp", "Timestamp", "To"])
 
-parseError ∷ ResponseType → ByteString → Maybe LastfmError
-parseError XML = xmlError
-parseError JSON = jsonError
 
-query ∷ (ByteString → Maybe LastfmError) → [(String, String)] → IO (Either LastfmError Response)
-query γ xs = curlResponse xs >>= \r →
-  return $ case γ r of
-    Just n → Left n
-    Nothing → Right r
+data Bitrate = B64 | B128
+data Multiplier = M1 | M2
+data Order = Popularity | DateAdded
+data Status = Yes | Maybe | No
+data Value = ValueUser User
+           | ValueArtists [Artist]
+data Period = Week | Quater | HalfYear | Year | Overall
 
-curlResponse ∷ [(String, String)] → IO ByteString
-curlResponse xs = withCurlDo $
-  respBody <$> (curlGetResponse_ "http://ws.audioscrobbler.com/2.0/?"
-    [ CurlPostFields . map (export . urlEncode) $ xs
-    , CurlFailOnError False
-    , CurlUserAgent "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0 Iceweasel/10.0"
-    ] ∷ IO (CurlResponse_ [(String, String)] ByteString))
 
-xml ∷ [String] → Q [Dec]
-xml = mapM func
-  where func xs = funD (mkName xs) [clause [] (normalB $ appE (varE (mkName ("API." ++ xs))) [e| XML |]) []]
+instance Show Value where
+  show (ValueUser _) = "user"
+  show (ValueArtists _) = "artists"
 
-json ∷ [String] → Q [Dec]
-json = mapM func
-  where func xs = funD (mkName xs) [clause [] (normalB $ appE (varE (mkName ("API." ++ xs))) [e| JSON |]) []]
+
+instance FromJSON Token where
+  parseJSON (Data.Aeson.Object v) = Token <$> v .: "token"
+  parseJSON _ = empty
+
+
+instance FromJSON SessionKey where
+  parseJSON (Data.Aeson.Object v) = SessionKey <$> ((v .: "session") >>= (.: "key"))
+  parseJSON _ = empty
+
+
+simple ∷ (FromJSON a, Monad m) ⇒ m ByteString → m a
+simple = liftM (fromJust . decode)
+
+
+class Argument a where
+  key ∷ a → String
+  value ∷ a → String
+
+
+instance Argument a ⇒ Argument (Maybe a) where key = maybe "" key; value = maybe "" value
+instance Argument a ⇒ Argument [a] where
+  key (a:_) = key a ++ "s"
+  key [] = ""
+  value = intercalate "," . map value
+
+
+boolToString ∷ Bool → String
+boolToString True = "1"
+boolToString False = "0"
+
+
+--instance Argument $first where key = const $second; value ($first a) = $func a
+$(instances "id"
+  [ ("Album","album")
+  , ("AlbumArtist", "albumartist")
+  , ("APIKey", "api_key")
+  , ("Artist", "artist")
+  , ("AuthToken", "authToken")
+  , ("ChosenByUser", "chosenByUser")
+  , ("Context", "context")
+  , ("Country", "country")
+  , ("Description", "description")
+  , ("Group", "group")
+  , ("Language", "lang")
+  , ("Latitude", "lat")
+  , ("Location", "location")
+  , ("Longitude", "long")
+  , ("Mbid", "mbid")
+  , ("Message", "message")
+  , ("Method", "method")
+  , ("Metro", "metro")
+  , ("Name", "name")
+  , ("Recipient", "recipient")
+  , ("SessionKey", "sk")
+  , ("Station", "station")
+  , ("StreamId", "streamId")
+  , ("Tag", "tag")
+  , ("TaggingType", "taggingtype")
+  , ("Title", "title")
+  , ("Token", "token")
+  , ("Track", "track")
+  , ("User", "user")
+  , ("Username", "username")
+  , ("Venuename", "venue")
+  ])
+
+
+$( instances "boolToString"
+  [ ("Autocorrect", "autocorrect")
+  , ("BuyLinks", "buylinks")
+  , ("Discovery", "discovery")
+  , ("FestivalsOnly", "festivalsonly")
+  , ("Public", "public")
+  , ("RecentTracks", "recenttracks")
+  , ("RTP", "rtp")
+  , ("UseRecs", "userecs")
+  ])
+
+
+$( instances "show"
+  [ ("Distance", "distance")
+  , ("Duration", "duration")
+  , ("Event", "event")
+  , ("Limit", "limit")
+  , ("Page", "page")
+  , ("Playlist", "playlistID")
+  , ("TrackNumber", "tracknumber")
+  , ("Venue", "venue")
+  , ("End", "end")
+  , ("EndTimestamp", "endTimestamp")
+  , ("Fingerprint", "fingerprintid")
+  , ("From", "from")
+  , ("Start", "start")
+  , ("StartTimestamp", "startTimestamp")
+  , ("Timestamp", "timestamp")
+  , ("To", "to")
+  ])
+
+
+instance Argument Bitrate where
+  key = const "bitrate"
+  value B64 = "64"
+  value B128 = "128"
+
+
+instance Argument Multiplier where
+  key = const "speed_multiplier"
+  value M1 = "1.0"
+  value M2 = "2.0"
+
+
+instance Argument Order where
+  key = const "order"
+  value Popularity = "popularity"
+  value DateAdded = "dateadded"
+
+
+instance Argument Status where
+  key = const "status"
+  value Yes = "0"
+  value Maybe = "1"
+  value No = "2"
+
+
+instance Argument Value where
+  key = const "value"
+  value (ValueUser u) = value u
+  value (ValueArtists as) = value as
+
+
+instance Argument Period where
+  key = const "period"
+  value Week = "7day"
+  value Quater = "3month"
+  value HalfYear = "6month"
+  value Year = "12month"
+  value Overall = "overall"
diff --git a/src/Network/Lastfm/API/Album.hs b/src/Network/Lastfm/API/Album.hs
--- a/src/Network/Lastfm/API/Album.hs
+++ b/src/Network/Lastfm/API/Album.hs
@@ -4,7 +4,7 @@
   ) where
 
 import Control.Arrow ((|||))
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 addTags ∷ ResponseType → (Artist, Album) → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 addTags t (artist, album) tags apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/Artist.hs b/src/Network/Lastfm/API/Artist.hs
--- a/src/Network/Lastfm/API/Artist.hs
+++ b/src/Network/Lastfm/API/Artist.hs
@@ -5,7 +5,7 @@
   ) where
 
 import Control.Arrow ((|||))
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 addTags ∷ ResponseType → Artist → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 addTags t artist tags apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/Auth.hs b/src/Network/Lastfm/API/Auth.hs
--- a/src/Network/Lastfm/API/Auth.hs
+++ b/src/Network/Lastfm/API/Auth.hs
@@ -4,7 +4,7 @@
   ) where
 
 import Data.Functor ((<$>))
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getMobileSession ∷ Username → APIKey → AuthToken → Lastfm SessionKey
 getMobileSession username apiKey token = simple <$> callAPI JSON [(#) (Method "auth.getMobileSession"), (#) username, (#) token, (#) apiKey]
diff --git a/src/Network/Lastfm/API/Chart.hs b/src/Network/Lastfm/API/Chart.hs
--- a/src/Network/Lastfm/API/Chart.hs
+++ b/src/Network/Lastfm/API/Chart.hs
@@ -3,18 +3,24 @@
   , getTopArtists, getTopTags, getTopTracks
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
+getHypedArtists ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getHypedArtists = get "getHypedArtists"
 
+getHypedTracks ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getHypedTracks = get "getHypedTracks"
 
+getLovedTracks ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getLovedTracks = get "getLovedTracks"
 
+getTopArtists ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getTopArtists = get "getTopArtists"
 
+getTopTags ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getTopTags = get "getTopTags"
 
+getTopTracks ∷ ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 getTopTracks = get "getTopTracks"
 
 get ∷ String → ResponseType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/API/Event.hs b/src/Network/Lastfm/API/Event.hs
--- a/src/Network/Lastfm/API/Event.hs
+++ b/src/Network/Lastfm/API/Event.hs
@@ -2,7 +2,7 @@
   ( attend, getAttendees, getInfo, getShouts, share, shout
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 attend ∷ ResponseType → Event → Status → APIKey → SessionKey → Secret → Lastfm Response
 attend t event status apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/Geo.hs b/src/Network/Lastfm/API/Geo.hs
--- a/src/Network/Lastfm/API/Geo.hs
+++ b/src/Network/Lastfm/API/Geo.hs
@@ -4,7 +4,7 @@
   , getMetroWeeklyChartlist, getMetros, getTopArtists, getTopTracks
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getEvents ∷ ResponseType
           → Maybe Latitude
diff --git a/src/Network/Lastfm/API/Group.hs b/src/Network/Lastfm/API/Group.hs
--- a/src/Network/Lastfm/API/Group.hs
+++ b/src/Network/Lastfm/API/Group.hs
@@ -2,7 +2,7 @@
   ( getHype, getMembers, getWeeklyChartList, getWeeklyAlbumChart, getWeeklyArtistChart, getWeeklyTrackChart
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getHype ∷ ResponseType → Group → APIKey → Lastfm Response
 getHype t group apiKey = callAPI t
diff --git a/src/Network/Lastfm/API/Library.hs b/src/Network/Lastfm/API/Library.hs
--- a/src/Network/Lastfm/API/Library.hs
+++ b/src/Network/Lastfm/API/Library.hs
@@ -3,7 +3,7 @@
   , removeAlbum, removeArtist, removeScrobble, removeTrack
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 addAlbum ∷ ResponseType → Artist → Album → APIKey → SessionKey → Secret → Lastfm Response
 addAlbum t artist album apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/Playlist.hs b/src/Network/Lastfm/API/Playlist.hs
--- a/src/Network/Lastfm/API/Playlist.hs
+++ b/src/Network/Lastfm/API/Playlist.hs
@@ -2,7 +2,7 @@
   ( addTrack, create
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 addTrack ∷ ResponseType → Playlist → Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 addTrack t playlist artist track apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/Radio.hs b/src/Network/Lastfm/API/Radio.hs
--- a/src/Network/Lastfm/API/Radio.hs
+++ b/src/Network/Lastfm/API/Radio.hs
@@ -2,7 +2,7 @@
   ( getPlaylist, search, tune
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getPlaylist ∷ ResponseType
             → Maybe Discovery
diff --git a/src/Network/Lastfm/API/Tag.hs b/src/Network/Lastfm/API/Tag.hs
--- a/src/Network/Lastfm/API/Tag.hs
+++ b/src/Network/Lastfm/API/Tag.hs
@@ -3,7 +3,7 @@
   , getWeeklyArtistChart, getWeeklyChartList, search
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getInfo ∷ ResponseType → Tag → Maybe Language → APIKey → Lastfm Response
 getInfo t tag language apiKey = callAPI t
diff --git a/src/Network/Lastfm/API/Tasteometer.hs b/src/Network/Lastfm/API/Tasteometer.hs
--- a/src/Network/Lastfm/API/Tasteometer.hs
+++ b/src/Network/Lastfm/API/Tasteometer.hs
@@ -2,7 +2,7 @@
   ( compare
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 import Prelude hiding (compare)
 
 (?<) ∷ Argument a ⇒ a → Int → (String, String)
diff --git a/src/Network/Lastfm/API/Track.hs b/src/Network/Lastfm/API/Track.hs
--- a/src/Network/Lastfm/API/Track.hs
+++ b/src/Network/Lastfm/API/Track.hs
@@ -5,7 +5,7 @@
   ) where
 
 import Control.Arrow ((|||))
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 addTags ∷ ResponseType → Artist → Track → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 addTags t artist track tags apiKey sessionKey secret = callAPIsigned t secret
diff --git a/src/Network/Lastfm/API/User.hs b/src/Network/Lastfm/API/User.hs
--- a/src/Network/Lastfm/API/User.hs
+++ b/src/Network/Lastfm/API/User.hs
@@ -6,7 +6,7 @@
   , getWeeklyChartList, getWeeklyTrackChart, shout
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getArtistTracks ∷ ResponseType → User → Artist → Maybe StartTimestamp → Maybe EndTimestamp → Maybe Page → APIKey → Lastfm Response
 getArtistTracks t user artist startTimestamp endTimestamp page apiKey = callAPI t
diff --git a/src/Network/Lastfm/API/Venue.hs b/src/Network/Lastfm/API/Venue.hs
--- a/src/Network/Lastfm/API/Venue.hs
+++ b/src/Network/Lastfm/API/Venue.hs
@@ -2,7 +2,7 @@
   ( getEvents, getPastEvents, search
   ) where
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 
 getEvents ∷ ResponseType → Venue → Maybe FestivalsOnly → APIKey → Lastfm Response
 getEvents t venue festivalsOnly apiKey = callAPI t
diff --git a/src/Network/Lastfm/Error.hs b/src/Network/Lastfm/Error.hs
--- a/src/Network/Lastfm/Error.hs
+++ b/src/Network/Lastfm/Error.hs
@@ -1,16 +1,20 @@
 {-# LANGUAGE OverloadedStrings #-}
-module Network.Lastfm.Error where
+module Network.Lastfm.Error
+  ( LastfmError(..)
+  , jsonError, xmlError
+  ) where
 
 import Control.Applicative ((<$>), empty)
 import Control.Monad ((<=<))
-import Control.Monad.Error (Error)
+
 import Data.Aeson
 import Data.ByteString.Lazy.Char8 (ByteString)
+import Network.Curl (CurlCode)
 import Text.XML.Light
 
+
 data LastfmError
-  = NotUsed -- To avoid subtracting 1 from Lastfm reponses
-  | DoesntExist
+  = DoesntExist
   | InvalidService
   | InvalidMethod
   | AuthenticationFailed
@@ -38,49 +42,85 @@
   | SuspendedAPIKey
   | Deprecated
   | RateLimitExceeded
-    deriving Enum
+  | UnknownError Int
+  | CurlError CurlCode
 
+
 instance Show LastfmError where
-  show NotUsed = "NotUsed: Internal liblastfm error for convenience"
-  show DoesntExist = "DoesntExist: This error does not exist"
-  show InvalidService = "InvalidService: This service does not exist"
-  show InvalidMethod = "InvalidMethod: No method with that name in this package"
-  show AuthenticationFailed = "AuthenticationFailed: You do not have permissions to access the service"
-  show InvalidFormat = "InvalidFormat: This service doesn't exist in that format"
-  show InvalidParameters = "InvalidParameters: Your request is missing a required parameter"
-  show InvalidResource = "InvalidResource: Invalid resource specified"
-  show OperationFailed = "OperationFailed: Something else went wrong"
-  show InvalidSessionKey = "InvalidSessionKey: Please re-authenticate"
-  show InvalidAPIKey = "InvalidAPIKey: You must be granted a valid key by last.fm"
-  show ServiceOffline = "ServiceOffline: This service is temporarily offline. Try again later."
-  show SubscribersOnly  = "SubscribersOnly : This station is only available to paid last.fm subscribers"
-  show InvalidMethodSignature = "InvalidMethodSignature: Invalid method signature supplied"
-  show TokenHasNotAuthorized = "TokenHasNotAuthorized: This token has not been authorized"
-  show NotForStreaming = "NotForStreaming: This item is not available for streaming."
-  show TemporaryUnavailable = "TemporaryUnavailable: The service is temporarily unavailable, please try again."
-  show LoginRequired = "LoginRequired: Login: User requires to be logged in"
-  show TrialExpired = "TrialExpired: This user has no free radio plays left. Subscription required."
-  show DoesntExistAgain = "DoesntExistAgain: This error does not exist"
-  show NotEnoughContent = "NotEnoughContent: There is not enough content to play this station"
-  show NotEnoughMembers = "NotEnoughMembers: This group does not have enough members for radio"
-  show NotEnoughFans = "NotEnoughFans: This artist does not have enough fans for for radio"
-  show NotEnoughNeighbours = "NotEnoughNeighbours: There are not enough neighbours for radio"
-  show NoPeakRadio = "NoPeakRadio: This user is not allowed to listen to radio during peak usage"
-  show RadioNotFound = "RadioNotFound: Radio station not found"
-  show SuspendedAPIKey = "SuspendedAPIKey: Access for your account has been suspended, please contact Last.fm"
-  show Deprecated = "Deprecated: This type of request is no longer supported"
-  show RateLimitExceeded = "RateLimitExceeded: Your IP has made too many requests in a short period"
+  show e = unwords $ case e of
+    DoesntExist            → ["DoesntExist:",            "This error does not exist"]
+    InvalidService         → ["InvalidService:",         "This service does not exist"]
+    InvalidMethod          → ["InvalidMethod:",          "No method with that name in this package"]
+    AuthenticationFailed   → ["AuthenticationFailed:",   "You do not have permissions to access the service"]
+    InvalidFormat          → ["InvalidFormat:",          "This service doesn't exist in that format"]
+    InvalidParameters      → ["InvalidParameters:",      "Your request is missing a required parameter"]
+    InvalidResource        → ["InvalidResource:",        "Invalid resource specified"]
+    OperationFailed        → ["OperationFailed:",        "Something else went wrong"]
+    InvalidSessionKey      → ["InvalidSessionKey:",      "Please re-authenticate"]
+    InvalidAPIKey          → ["InvalidAPIKey:",          "You must be granted a valid key by last.fm"]
+    ServiceOffline         → ["ServiceOffline:",         "This service is temporarily offline. Try again later."]
+    SubscribersOnly        → ["SubscribersOnly:",        "This station is only available to paid last.fm subscribers"]
+    InvalidMethodSignature → ["InvalidMethodSignature:", "Invalid method signature supplied"]
+    TokenHasNotAuthorized  → ["TokenHasNotAuthorized:",  "This token has not been authorized"]
+    NotForStreaming        → ["NotForStreaming:",        "This item is not available for streaming."]
+    TemporaryUnavailable   → ["TemporaryUnavailable:",   "The service is temporarily unavailable, please try again."]
+    LoginRequired          → ["LoginRequired:",          "Login: User requires to be logged in"]
+    TrialExpired           → ["TrialExpired:",           "This user has no free radio plays left. Subscription required."]
+    DoesntExistAgain       → ["DoesntExistAgain:",       "This error does not exist"]
+    NotEnoughContent       → ["NotEnoughContent:",       "There is not enough content to play this station"]
+    NotEnoughMembers       → ["NotEnoughMembers:",       "This group does not have enough members for radio"]
+    NotEnoughFans          → ["NotEnoughFans:",          "This artist does not have enough fans for for radio"]
+    NotEnoughNeighbours    → ["NotEnoughNeighbours:",    "There are not enough neighbours for radio"]
+    NoPeakRadio            → ["NoPeakRadio:",            "This user is not allowed to listen to radio during peak usage"]
+    RadioNotFound          → ["RadioNotFound:",          "Radio station not found"]
+    SuspendedAPIKey        → ["SuspendedAPIKey:",        "Access for your account has been suspended, please contact Last.fm"]
+    Deprecated             → ["Deprecated:",             "This type of request is no longer supported"]
+    RateLimitExceeded      → ["RateLimitExceeded:",      "Your IP has made too many requests in a short period"]
+    UnknownError n         → ["UnknownError:",           "Lastfm API specs say nothing about this particular error:", show n]
+    CurlError s            → ["CurlError:", show s]
 
-instance Error LastfmError
 
+instance FromJSON LastfmError where
+  parseJSON (Object v) = disambiguate <$> v .: "error"
+  parseJSON _ = empty
+
+
 xmlError ∷ ByteString → Maybe LastfmError
-xmlError r = do
-  xml ← parseXMLDoc r
-  toEnum . read <$> (findAttr (unqual "code") <=< findChild (unqual "error")) xml
+xmlError r = disambiguate . read <$> (findAttr (unqual "code") <=< findChild (unqual "error") <=< parseXMLDoc) r
 
+
 jsonError ∷ ByteString → Maybe LastfmError
 jsonError = decode
 
-instance FromJSON LastfmError where
-  parseJSON (Object v) = toEnum <$> v .: "error"
-  parseJSON _ = empty
+
+disambiguate ∷ Int → LastfmError
+disambiguate n = case n of
+  1 → DoesntExist
+  2 → InvalidService
+  3 → InvalidMethod
+  4 → AuthenticationFailed
+  5 → InvalidFormat
+  6 → InvalidParameters
+  7 → InvalidResource
+  8 → OperationFailed
+  9 → InvalidSessionKey
+  10 → InvalidAPIKey
+  11 → ServiceOffline
+  12 → SubscribersOnly
+  13 → InvalidMethodSignature
+  14 → TokenHasNotAuthorized
+  15 → NotForStreaming
+  16 → TemporaryUnavailable
+  17 → LoginRequired
+  18 → TrialExpired
+  19 → DoesntExistAgain
+  20 → NotEnoughContent
+  21 → NotEnoughMembers
+  22 → NotEnoughFans
+  23 → NotEnoughNeighbours
+  24 → NoPeakRadio
+  25 → RadioNotFound
+  26 → SuspendedAPIKey
+  27 → Deprecated
+  28 → RateLimitExceeded
+  _ → UnknownError n
diff --git a/src/Network/Lastfm/Internal.hs b/src/Network/Lastfm/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Lastfm/Internal.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+-- | Response module
+{-# OPTIONS_HADDOCK hide #-}
+module Network.Lastfm.Internal
+  ( ResponseType(..)
+  , callAPI, callAPIsigned, xml, json, (#)
+  , module Network.Lastfm
+  ) where
+
+import Control.Applicative ((<$>))
+import Control.Arrow ((&&&), second)
+import Data.Function (on)
+import Data.List (sortBy)
+
+import Codec.Binary.UTF8.String (encodeString)
+import Data.ByteString.Lazy.Char8 (ByteString)
+import qualified Data.ByteString.Lazy.Char8 as BS
+import Data.Digest.Pure.MD5 (md5)
+import Data.URLEncoded (urlEncode, export)
+import Network.Curl
+
+import Network.Lastfm
+import Network.Lastfm.Error
+import Network.Lastfm.TH
+
+
+-- Send POST query to Lastfm API
+callAPI ∷ ResponseType → [(String, String)] → Lastfm Response
+callAPI t = query (parseError t) . insertType t . map (second encodeString)
+
+
+-- Send signed POST query to Lastfm API
+callAPIsigned ∷ ResponseType → Secret → [(String, String)] → Lastfm Response
+callAPIsigned t (Secret s) xs = query (parseError t) zs
+ where
+  ys = map (second encodeString) . filter (not . null . snd) $ xs
+  zs = insertType t $ ("api_sig", sign ys) : ys
+
+  sign ∷ [(String, String)] → String
+  sign = show . md5 . BS.pack . (++ s) . concatMap (uncurry (++)) . sortBy (compare `on` fst)
+
+
+-- Insert desired response type into query
+insertType ∷ ResponseType → [(String, String)] → [(String, String)]
+insertType XML = id
+insertType JSON = (("format", "json") :)
+
+
+-- Try to find error message in Lastfm response
+parseError ∷ ResponseType → ByteString → Maybe LastfmError
+parseError XML = xmlError
+parseError JSON = jsonError
+
+
+query ∷ (ByteString → Maybe LastfmError) → [(String, String)] → IO (Either LastfmError Response)
+query γ xs = do
+  (status, body) ← (respCurlCode &&& respBody) <$> curlResponse xs
+  return $ case status of
+    CurlOK → case γ body of
+               Nothing → Right body
+               Just n → Left n
+    s → Left $ CurlError s
+
+
+curlResponse ∷ [(String, String)] → IO (CurlResponse_ [(String, String)] ByteString)
+curlResponse xs = withCurlDo $ curlGetResponse_ "http://ws.audioscrobbler.com/2.0/?"
+  [ CurlPostFields . map (export . urlEncode) $ xs
+  , CurlFailOnError False
+  , CurlUserAgent "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0 Iceweasel/10.0"
+  , CurlConnectTimeout 10
+  ]
+
+
+-- Construct query parameter
+(#) ∷ Argument a ⇒ a → (String, String)
+(#) x = (key x, value x)
diff --git a/src/Network/Lastfm/JSON/Album.hs b/src/Network/Lastfm/JSON/Album.hs
--- a/src/Network/Lastfm/JSON/Album.hs
+++ b/src/Network/Lastfm/JSON/Album.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Album API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,52 +7,36 @@
   , getTopTags, removeTag, search, share
   ) where
 
-import Network.Lastfm
+#include "album.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Album as API
 
 $(json ["addTags", "getBuyLinks", "getInfo", "getShouts", "getTags", "getTopTags", "removeTag", "search", "share"])
 
--- | Tag an album using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/album.addTags>
+__addTags__
 addTags ∷ (Artist, Album) → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of Buy Links for a particular Album. It is required that you supply either the artist and track params or the mbid param.
---
--- More: <http://www.last.fm/api/show/album.getBuylinks>
+__getBuyLinks__
 getBuyLinks ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Country → APIKey → Lastfm Response
 
--- | Get the metadata for an album on Last.fm using the album name or a musicbrainz id. See playlist.fetch on how to get the album playlist.
---
--- More: <http://www.last.fm/api/show/album.getInfo>
+__getInfo__
 getInfo ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Maybe Language → Maybe Username → APIKey → Lastfm Response
 
--- | Get shouts for this album.
---
--- More: <http://www.last.fm/api/show/album.getShouts>
+__getShouts__
 getShouts ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to an album on Last.fm.
---
--- More: <http://www.last.fm/api/show/album.getTags>
+__getTags__
 getTags ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top tags for an album on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/album.getTopTags>
+__getTopTags__
 getTopTags ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Remove a user's tag from an album.
---
--- More: <http://www.last.fm/api/show/album.removeTag>
+__removeTag__
 removeTag ∷ Artist → Album → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Search for an album by name. Returns album matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/album.search>
+__search__
 search ∷ Album → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an album with one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/album.share>
+__share__
 share ∷ Artist → Album → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Artist.hs b/src/Network/Lastfm/JSON/Artist.hs
--- a/src/Network/Lastfm/JSON/Artist.hs
+++ b/src/Network/Lastfm/JSON/Artist.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Artist API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,97 +8,63 @@
   , getTopFans, getTopTags, getTopTracks, removeTag, search, share, shout
   ) where
 
-import Network.Lastfm
+#include "artist.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Artist as API
-  
+
 $(json ["addTags", "getCorrection", "getEvents", "getImages", "getInfo", "getPastEvents", "getPodcast", "getShouts", "getSimilar", "getTags", "getTopAlbums", "getTopFans", "getTopTags", "getTopTracks", "removeTag", "search", "share", "shout"])
 
--- | Tag an album using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/artist.addTags>
+__addTags__
 addTags ∷ Artist → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Use the last.fm corrections data to check whether the supplied artist has a correction to a canonical artist
---
--- More: <http://www.last.fm/api/show/artist.getCorrection>
+__getCorrection__
 getCorrection ∷ Artist → APIKey → Lastfm Response
 
--- | Get a list of upcoming events for this artist.
---
--- More: <http://www.last.fm/api/show/artist.getEvents>
+__getEvents__
 getEvents ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get Images for this artist in a variety of sizes.
---
--- More: <http://www.last.fm/api/show/artist.getImages>
+__getImages__
 getImages ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → Maybe Order → APIKey → Lastfm Response
 
--- | Get the metadata for an artist. Includes biography.
---
--- More: <http://www.last.fm/api/show/artist.getInfo>
+__getInfo__
 getInfo ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Language → Maybe Username → APIKey → Lastfm Response
 
--- | Get a paginated list of all the events this artist has played at in the past.
---
--- More: <http://www.last.fm/api/show/artist.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a podcast of free mp3s based on an artist.
---
--- More: <http://www.last.fm/api/show/artist.getPodcast>
+__getPodcast__
 getPodcast ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get shouts for this artist. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/artist.getShouts>
+__getShouts__
 getShouts ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get all the artists similar to this artist.
---
--- More: <http://www.last.fm/api/show/artist.getSimilar>
+__getSimilar__
 getSimilar ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to an artist on Last.fm. If accessed as an authenticated service /and/ you don't supply a user parameter then this service will return tags for the authenticated user.
---
--- More: <http://www.last.fm/api/show/artist.getTags>
+__getTags__
 getTags ∷ Either Artist Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top albums for an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top fans for an artist on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/artist.getTopFans>
+__getTopFans__
 getTopFans ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tags for an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopTags>
+__getTopTags__
 getTopTags ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tracks by an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Remove a user's tag from an artist.
---
--- More: <http://www.last.fm/api/show/artist.removeTag>
+__removeTag__
 removeTag ∷ Artist → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Search for an artist by name. Returns artist matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/artist.search>
+__search__
 search ∷ Artist → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an artist with Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/artist.share>
+__share__
 share ∷ Artist → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Shout in this artist's shoutbox.
---
--- More: <http://www.last.fm/api/show/artist.shout>
+__shout__
 shout ∷ Artist → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Chart.hs b/src/Network/Lastfm/JSON/Chart.hs
--- a/src/Network/Lastfm/JSON/Chart.hs
+++ b/src/Network/Lastfm/JSON/Chart.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Chart API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,37 +7,27 @@
   , getTopArtists, getTopTags, getTopTracks
   ) where
 
-import Network.Lastfm
+#include "chart.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Chart as API
 
 $(json ["getHypedArtists", "getHypedTracks", "getLovedTracks", "getTopArtists", "getTopTags", "getTopTracks"])
 
--- | Get the hyped artists chart.
---
--- More: <http://www.last.fm/api/show/chart.getHypedArtists>
+__getHypedArtists__
 getHypedArtists ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the hyped tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getHypedTracks>
+__getHypedTracks__
 getHypedTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the most loved tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getLovedTracks>
+__getLovedTracks__
 getLovedTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get top tags chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopTags>
+__getTopTags__
 getTopTags ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Event.hs b/src/Network/Lastfm/JSON/Event.hs
--- a/src/Network/Lastfm/JSON/Event.hs
+++ b/src/Network/Lastfm/JSON/Event.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Event API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,37 +6,27 @@
   ( attend, getAttendees, getInfo, getShouts, share, shout
   ) where
 
-import Network.Lastfm
+#include "event.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Event as API
 
 $(json ["attend", "getAttendees", "getInfo", "getShouts", "share", "shout"])
 
--- | Set a user's attendance status for an event.
---
--- More: <http://www.last.fm/api/show/event.attend>
+__attend__
 attend ∷ Event → Status → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of attendees for an event.
---
--- More: <http://www.last.fm/api/show/event.getAttendees>
+__getAttendees__
 getAttendees ∷ Event → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the metadata for an event on Last.fm. Includes attendance and lineup information.
---
--- More: <http://www.last.fm/api/show/event.getInfo>
+__getInfo__
 getInfo ∷ Event → APIKey → Lastfm Response
 
--- | Get shouts for this event.
---
--- More: <http://www.last.fm/api/show/event.getShouts>
+__getShouts__
 getShouts ∷ Event → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an event with one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/event.share>
+__share__
 share ∷ Event → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Shout in this event's shoutbox.
---
--- More: <http://www.last.fm/api/show/event.shout>
+__shout__
 shout ∷ Event → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Geo.hs b/src/Network/Lastfm/JSON/Geo.hs
--- a/src/Network/Lastfm/JSON/Geo.hs
+++ b/src/Network/Lastfm/JSON/Geo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Geo API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,14 +8,14 @@
   , getMetroWeeklyChartlist, getMetros, getTopArtists, getTopTracks
   ) where
 
-import Network.Lastfm
+#include "geo.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Geo as API
 
 $(json ["getEvents", "getMetroArtistChart", "getMetroHypeArtistChart", "getMetroHypeTrackChart", "getMetroTrackChart", "getMetroUniqueArtistChart", "getMetroUniqueTrackChart", "getMetroWeeklyChartlist", "getMetros", "getTopArtists", "getTopTracks"])
 
--- | Get all events in a specific location by country or city name.
---
--- More: <http://www.last.fm/api/show/geo.getEvents>
+__getEvents__
 getEvents ∷ Maybe Latitude
           → Maybe Longitude
           → Maybe Location
@@ -24,52 +25,32 @@
           → APIKey
           → Lastfm Response
 
--- | Get a chart of artists for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroArtistChart>
+__getMetroArtistChart__
 getMetroArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of hyped (up and coming) artists for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroHypeArtistChart>
+__getMetroHypeArtistChart__
 getMetroHypeArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of hyped (up and coming) tracks for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroHypeTrackChart>
+__getMetroHypeTrackChart__
 getMetroHypeTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of tracks for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroTrackChart>
+__getMetroTrackChart__
 getMetroTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of the artists which make that metro unique.
---
--- More: <http://www.last.fm/api/show/geo.getMetroUniqueArtistChart>
+__getMetroUniqueArtistChart__
 getMetroUniqueArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of the tracks which make that metro unique.
---
--- More: <http://www.last.fm/api/show/geo.getMetroUniqueTrackChart>
+__getMetroUniqueTrackChart__
 getMetroUniqueTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a list of available chart periods for this metro, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/geo.getMetroWeeklyChartlist>
+__getMetroWeeklyChartlist__
 getMetroWeeklyChartlist ∷ Metro → APIKey → Lastfm Response
 
--- | Get a list of valid countries and metros for use in the other webservices.
---
--- More: <http://www.last.fm/api/show/geo.getMetros>
+__getMetros__
 getMetros ∷ Maybe Country → APIKey → Lastfm Response
 
--- | Get the most popular artists on Last.fm by country.
---
--- More: <http://www.last.fm/api/show/geo.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Country → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the most popular tracks on Last.fm last week by country.
---
--- More: <http://www.last.fm/api/show/geo.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Country → Maybe Location → Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Group.hs b/src/Network/Lastfm/JSON/Group.hs
--- a/src/Network/Lastfm/JSON/Group.hs
+++ b/src/Network/Lastfm/JSON/Group.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Group API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,38 +6,27 @@
   ( getHype, getMembers, getWeeklyChartList, getWeeklyAlbumChart, getWeeklyArtistChart, getWeeklyTrackChart
   ) where
 
-import Network.Lastfm
+#include "group.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Group as API
 
 $(json ["getHype", "getMembers", "getWeeklyChartList", "getWeeklyAlbumChart", "getWeeklyArtistChart", "getWeeklyTrackChart"])
 
--- | Get the hype list for a group.
---
--- More: <http://www.last.fm/api/show/group.getHype>
+__getHype__
 getHype ∷ Group → APIKey → Lastfm Response
 
--- | Get a list of members for this group.
---
--- More: <http://www.last.fm/api/show/group.getMembers>
+__getMembers__
 getMembers ∷ Group → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an album chart for a group, for a given date range. If no date range is supplied, it will return the most recent album chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyAlbumChart>
+__getWeeklyChartList__
 getWeeklyChartList ∷ Group → APIKey → Lastfm Response
 
--- | Get an artist chart for a group, for a given date range. If no date range is supplied, it will return the most recent artist chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyArtistChart>
+__getWeeklyAlbumChart__
 getWeeklyAlbumChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get a list of available charts for this group, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyChartList>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
 
-
--- | Get a track chart for a group, for a given date range. If no date range is supplied, it will return the most recent track chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyTrackChart>
+__getWeeklyTrackChart__
 getWeeklyTrackChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Library.hs b/src/Network/Lastfm/JSON/Library.hs
--- a/src/Network/Lastfm/JSON/Library.hs
+++ b/src/Network/Lastfm/JSON/Library.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Library API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,57 +7,39 @@
   , removeAlbum, removeArtist, removeScrobble, removeTrack
   ) where
 
-import Network.Lastfm
+#include "library.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Library as API
-  
+
 $(json ["addAlbum", "addArtist", "addTrack", "getAlbums", "getArtists", "getTracks", "removeAlbum", "removeArtist", "removeScrobble", "removeTrack"])
 
--- | Add an album or collection of albums to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addAlbum>
+__addAlbum__
 addAlbum ∷ Artist → Album → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Add an artist to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addArtist>
+__addArtist__
 addArtist ∷ Artist → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Add a track to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addTrack>
+__addTrack__
 addTrack ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | A paginated list of all the albums in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getAlbums>
+__getAlbums__
 getAlbums ∷ User → Maybe Artist → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | A paginated list of all the artists in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getArtists>
+__getArtists__
 getArtists ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | A paginated list of all the tracks in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getTracks>
+__getTracks__
 getTracks ∷ User → Maybe Artist → Maybe Album → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Remove an album from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeAlbum>
+__removeAlbum__
 removeAlbum ∷ Artist → Album → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove an artist from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeArtist>
+__removeArtist__
 removeArtist ∷ Artist → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a scrobble from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeScrobble>
+__removeScrobble__
 removeScrobble ∷ Artist → Track → Timestamp → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a track from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeTrack>
+__removeTrack__
 removeTrack ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Playlist.hs b/src/Network/Lastfm/JSON/Playlist.hs
--- a/src/Network/Lastfm/JSON/Playlist.hs
+++ b/src/Network/Lastfm/JSON/Playlist.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Playlist API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,17 +6,15 @@
   ( addTrack, create
   ) where
 
-import Network.Lastfm
+#include "playlist.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Playlist as API
 
 $(json ["addTrack", "create"])
 
--- | Add a track to a Last.fm user's playlist.
---
--- More: <http://www.last.fm/api/show/playlist.addTrack>
+__addTrack__
 addTrack ∷ Playlist → Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Create a Last.fm playlist on behalf of a user.
---
--- More: <http://www.last.fm/api/show/playlist.create>
+__create__
 create ∷ Maybe Title → Maybe Description → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Radio.hs b/src/Network/Lastfm/JSON/Radio.hs
--- a/src/Network/Lastfm/JSON/Radio.hs
+++ b/src/Network/Lastfm/JSON/Radio.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Radio API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,14 +6,14 @@
   ( getPlaylist, search, tune
   ) where
 
-import Network.Lastfm
+#include "radio.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Radio as API
 
 $(json ["getPlaylist", "search", "tune"])
 
--- | Fetch new radio content periodically in an XSPF format.
---
--- More: <http://www.last.fm/api/show/radio.getPlaylist>
+__getPlaylist__
 getPlaylist ∷ Maybe Discovery
             → Maybe RTP
             → Maybe BuyLinks
@@ -23,12 +24,8 @@
             → Secret
             → Lastfm Response
 
--- | Resolve the name of a resource into a station depending on which resource it is most likely to represent.
---
--- More: <http://www.last.fm/api/show/radio.search>
+__search__
 search ∷ Name → APIKey → Lastfm Response
 
--- | Tune in to a Last.fm radio station.
---
--- More: <http://www.last.fm/api/show/radio.tune>
+__tune__
 tune ∷ Maybe Language → Station → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Tag.hs b/src/Network/Lastfm/JSON/Tag.hs
--- a/src/Network/Lastfm/JSON/Tag.hs
+++ b/src/Network/Lastfm/JSON/Tag.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Tag API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,52 +7,36 @@
   , getWeeklyArtistChart, getWeeklyChartList, search
   ) where
 
-import Network.Lastfm
+#include "tag.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Tag as API
 
 $(json ["getInfo", "getSimilar", "getTopAlbums", "getTopArtists", "getTopTags", "getTopTracks", "getWeeklyArtistChart", "getWeeklyChartList", "search"])
 
--- | Get the metadata for a tag.
---
--- More: <http://www.last.fm/api/show/tag.getInfo>
+__getInfo__
 getInfo ∷ Tag → Maybe Language → APIKey → Lastfm Response
 
--- | Search for tags similar to this one. Returns tags ranked by similarity, based on listening data.
---
--- More: <http://www.last.fm/api/show/tag.getSimilar>
+__getSimilar__
 getSimilar ∷ Tag → APIKey → Lastfm Response
 
--- | Get the top albums tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Fetches the top global tags on Last.fm, sorted by popularity (number of times used).
---
--- More: <http://www.last.fm/api/show/tag.getTopTags>
+__getTopTags__
 getTopTags ∷ APIKey → Lastfm Response
 
--- | Get the top tracks tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an artist chart for a tag, for a given date range. If no date range is supplied, it will return the most recent artist chart for this tag.
---
--- More: <http://www.last.fm/api/show/tag.getWeeklyArtistChart>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ Tag → Maybe From → Maybe To → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of available charts for this tag, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/tag.getWeeklyChartList>
+__getWeeklyChartList__
 getWeeklyChartList ∷ Tag → APIKey → Lastfm Response
 
--- | Search for a tag by name. Returns matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/tag.search>
+__search__
 search ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Tasteometer.hs b/src/Network/Lastfm/JSON/Tasteometer.hs
--- a/src/Network/Lastfm/JSON/Tasteometer.hs
+++ b/src/Network/Lastfm/JSON/Tasteometer.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Tasteometer API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,14 +6,14 @@
   ( compare
   ) where
 
+#include "tasteometer.docs"
+
 import Prelude hiding (compare)
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Tasteometer as API
 
 $(json ["compare"])
 
--- | Get a Tasteometer score from two inputs, along with a list of shared artists. If the input is a User some additional information is returned.
---
--- More: <http://www.last.fm/api/show/tasteometer.compare>
+__compare__
 compare ∷ Value → Value → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Track.hs b/src/Network/Lastfm/JSON/Track.hs
--- a/src/Network/Lastfm/JSON/Track.hs
+++ b/src/Network/Lastfm/JSON/Track.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Track API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,79 +8,53 @@
   , love, removeTag, scrobble, search, share, unban, unlove, updateNowPlaying
   ) where
 
-import Network.Lastfm
+#include "track.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Track as API
 
 $(json ["addTags", "ban", "getBuyLinks", "getCorrection", "getFingerprintMetadata", "getInfo", "getShouts", "getSimilar", "getTags", "getTopFans", "getTopTags", "love", "removeTag", "scrobble", "search", "share", "unban", "unlove", "updateNowPlaying"])
 
--- | Tag a track using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/track.addTags>
+__addTags__
 addTags ∷ Artist → Track → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Ban a track for a given user profile.
---
--- More: <http://www.last.fm/api/show/track.ban>
+__ban__
 ban ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of Buy Links for a particular track.
---
--- More: <http://www.last.fm/api/show/track.getBuylinks>
+__getBuyLinks__
 getBuyLinks ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Country → APIKey → Lastfm Response
 
--- | Use the last.fm corrections data to check whether the supplied track has a correction to a canonical track.
---
--- More: <http://www.last.fm/api/show/track.getCorrection>
+__getCorrection__
 getCorrection ∷ Artist → Track → APIKey → Lastfm Response
 
--- | Retrieve track metadata associated with a fingerprint id generated by the Last.fm Fingerprinter. Returns track elements, along with a 'rank' value between 0 and 1 reflecting the confidence for each match.
---
--- More: <http://www.last.fm/api/show/track.getFingerprintMetadata>
+__getFingerprintMetadata__
 getFingerprintMetadata ∷ Fingerprint → APIKey → Lastfm Response
 
--- | Get the metadata for a track on Last.fm.
---
--- More: <http://www.last.fm/api/show/track.getInfo>
+__getInfo__
 getInfo ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Username → APIKey → Lastfm Response
 
--- | Get shouts for this track. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/track.getShouts>
+__getShouts__
 getShouts ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the similar tracks for this track on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/track.getSimilar>
+__getSimilar__
 getSimilar ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to a track on Last.fm.
---
--- More: <http://www.last.fm/api/show/track.getTags>
+__getTags__
 getTags ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top fans for this track on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/track.getTopFans>
+__getTopFans__
 getTopFans ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tags for this track on Last.fm, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/track.getTopTags>
+__getTopTags__
 getTopTags ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Love a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.love>
+__love__
 love ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a user's tag from a track.
---
--- More: <http://www.last.fm/api/show/track.removeTag>
+__removeTag__
 removeTag ∷ Artist → Track → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Used to add a track-play to a user's profile.
---
--- More: <http://www.last.fm/api/show/track.scrobble>
+__scrobble__
 scrobble ∷ ( Timestamp, Maybe Album, Artist, Track, Maybe AlbumArtist
            , Maybe Duration, Maybe StreamId, Maybe ChosenByUser
            , Maybe Context, Maybe TrackNumber, Maybe Mbid )
@@ -88,30 +63,19 @@
          → Secret
          → Lastfm Response
 
--- | Search for a track by track name. Returns track matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/track.search>
+__search__
 search ∷ Track → Maybe Page → Maybe Limit → Maybe Artist → APIKey → Lastfm Response
 
--- | Share a track twith one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/track.share>
+__share__
 share ∷ Artist → Track → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Unban a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.unban>
+__unban__
 unban ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Unlove a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.unlove>
+__unlove__
 unlove ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
-
--- | Used to notify Last.fm that a user has started listening to a track. Parameter names are case sensitive.
---
--- More: <http://www.last.fm/api/show/track.updateNowPlaying>
+__updateNowPlaying__
 updateNowPlaying ∷ Artist
                  → Track
                  → Maybe Album
diff --git a/src/Network/Lastfm/JSON/User.hs b/src/Network/Lastfm/JSON/User.hs
--- a/src/Network/Lastfm/JSON/User.hs
+++ b/src/Network/Lastfm/JSON/User.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | User API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -9,132 +10,84 @@
   , getWeeklyChartList, getWeeklyTrackChart, shout
   ) where
 
-import Network.Lastfm
+#include "user.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.User as API
 
 $(json ["getArtistTracks", "getBannedTracks", "getEvents", "getFriends", "getInfo", "getLovedTracks", "getNeighbours", "getNewReleases", "getPastEvents", "getPersonalTags", "getPlaylists", "getRecentStations", "getRecentTracks", "getRecommendedArtists", "getRecommendedEvents", "getShouts", "getTopAlbums", "getTopArtists", "getTopTags", "getTopTracks", "getWeeklyAlbumChart", "getWeeklyArtistChart", "getWeeklyChartList", "getWeeklyTrackChart", "shout"])
 
--- | Get a list of tracks by a given artist scrobbled by this user, including scrobble time. Can be limited to specific timeranges, defaults to all time.
---
--- More: <http://www.last.fm/api/show/user.getArtistTracks>
+__getArtistTracks__
 getArtistTracks ∷ User → Artist → Maybe StartTimestamp → Maybe EndTimestamp → Maybe Page → APIKey → Lastfm Response
 
--- | Returns the tracks banned by the user.
---
--- More: <http://www.last.fm/api/show/user.getBannedTracks>
+__getBannedTracks__
 getBannedTracks ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of upcoming events that this user is attending.
---
--- Mpre: <http://www.last.fm/api/show/user.getEvents>
+__getEvents__
 getEvents ∷ User → Maybe Page → Maybe Limit → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get a list of the user's friends on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getFriends>
+__getFriends__
 getFriends ∷ User → Maybe RecentTracks → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get information about a user profile.
---
--- More: <http://www.last.fm/api/show/user.getInfo>
+__getInfo__
 getInfo ∷ Maybe User → APIKey → Lastfm Response
 
--- | Get tracks loved by a user.
---
--- More: <http://www.last.fm/api/show/user.getLovedTracks>
+__getLovedTracks__
 getLovedTracks ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of a user's neighbours on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getNeighbours>
+__getNeighbours__
 getNeighbours ∷ User → Maybe Limit → APIKey → Lastfm Response
 
--- | Gets a list of forthcoming releases based on a user's musical taste.
---
--- More: <http://www.last.fm/api/show/user.getNewReleases>
+__getNewReleases__
 getNewReleases ∷ User → Maybe UseRecs → APIKey → Lastfm Response
 
--- | Get a paginated list of all events a user has attended in the past.
---
--- More: <http://www.last.fm/api/show/user.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the user's personal tags.
---
--- More: <http://www.last.fm/api/show/user.getPersonalTags>
+__getPersonalTags__
 getPersonalTags ∷ User → Tag → TaggingType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of a user's playlists on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getPlaylists>
+__getPlaylists__
 getPlaylists ∷ User → APIKey → Lastfm Response
 
--- | Get a list of the recent Stations listened to by this user.
---
--- More: <http://www.last.fm/api/show/user.getRecentStations>
+__getRecentStations__
 getRecentStations ∷ User → Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of the recent tracks listened to by this user. Also includes the currently playing track with the nowplaying="true" attribute if the user is currently listening.
---
--- More: <http://www.last.fm/api/show/user.getRecentTracks>
+__getRecentTracks__
 getRecentTracks ∷ User → Maybe Page → Maybe Limit → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get Last.fm artist recommendations for a user.
---
--- Mpre: <http://www.last.fm/api/show/user.getRecommendedArtists>
+__getRecommendedArtists__
 getRecommendedArtists ∷ Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a paginated list of all events recommended to a user by Last.fm, based on their listening profile.
---
--- More: <http://www.last.fm/api/show/user.getRecommendedEvents>
+__getRecommendedEvents__
 getRecommendedEvents ∷ Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get shouts for this user. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/user.getShouts>
+__getShouts__
 getShouts ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top albums listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tags used by this user.
---
--- More: <http://www.last.fm/api/show/user.getTopTags>
+__getTopTags__
 getTopTags ∷ User → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tracks listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an album chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent album chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyAlbumChart>
+__getWeeklyAlbumChart__
 getWeeklyAlbumChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get an artist chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent artist chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyArtistChart>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get a list of available charts for this user, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyChartList>
+__getWeeklyChartList__
 getWeeklyChartList ∷ User → APIKey → Lastfm Response
 
--- | Get a track chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent track chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyTrackChart>
+__getWeeklyTrackChart__
 getWeeklyTrackChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Shout on this user's shoutbox.
---
--- More: <http://www.last.fm/api/show/user.shout>
+__shout__
 shout ∷ User → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/JSON/Venue.hs b/src/Network/Lastfm/JSON/Venue.hs
--- a/src/Network/Lastfm/JSON/Venue.hs
+++ b/src/Network/Lastfm/JSON/Venue.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Venue API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,22 +6,18 @@
   ( getEvents, getPastEvents, search
   ) where
 
-import Network.Lastfm
+#include "venue.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Venue as API
 
 $(json ["getEvents", "getPastEvents", "search"])
 
--- | Get a list of upcoming events at this venue.
---
--- More: <http://www.last.fm/api/show/venue.getEvents>
+__getEvents__
 getEvents ∷ Venue → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get a paginated list of all the events held at this venue in the past.
---
--- More: <http://www.last.fm/api/show/venue.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ Venue → Maybe FestivalsOnly → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Search for a venue by venue name.
---
--- More: <http://www.last.fm/api/show/venue.search>
+__search__
 search ∷ Venuename → Maybe Page → Maybe Limit → Maybe Country → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/TH.hs b/src/Network/Lastfm/TH.hs
--- a/src/Network/Lastfm/TH.hs
+++ b/src/Network/Lastfm/TH.hs
@@ -1,17 +1,44 @@
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE ViewPatterns #-}
-module Network.Lastfm.TH where
+module Network.Lastfm.TH
+  ( ResponseType(..)
+  , xml, json
+  , instances, newtypes
+  ) where
 
 import Language.Haskell.TH
 
+
+-- Desired type of Lastfm response
+data ResponseType = XML | JSON
+
+
+-- Construct XML wrapper to specified API function
+xml ∷ [String] → Q [Dec]
+xml = mapM func
+  where
+   func xs = funD (mkName xs) [clause [] (normalB $ appE (varE (mkName ("API." ++ xs))) [e| XML |]) []]
+
+
+-- Construct JSON wrapper to specified API function
+json ∷ [String] → Q [Dec]
+json = mapM func
+  where
+   func xs = funD (mkName xs) [clause [] (normalB $ appE (varE (mkName ("API." ++ xs))) [e| JSON |]) []]
+
+
 instances ∷ String → [(String, String)] → Q [Dec]
 instances f = mapM (instanceDeclaration "Argument")
-  where instanceDeclaration (mkName → tc) (mkName → n, m) = instanceD (cxt []) (appT (conT tc) (conT n)) [first, second]
-          where first = funD (mkName "key") [clause [] (normalB [e| const m |]) []]
-                second = let var = mkName "a"
-                             func = mkName f
-                         in funD (mkName "value") [clause [conP n [varP var]] (normalB $ appE (varE func) (varE var)) []] 
+  where
+   instanceDeclaration (mkName → tc) (mkName → n, m) = instanceD (cxt []) (appT (conT tc) (conT n)) [first, second]
+    where
+     first = funD (mkName "key") [clause [] (normalB [e| const m |]) []]
+     second = let var = mkName "a"
+                  func = mkName f
+              in funD (mkName "value") [clause [conP n [varP var]] (normalB $ appE (varE func) (varE var)) []]
 
+
 newtypes ∷ String → [String] → Q [Dec]
 newtypes (mkName → t) (map mkName → ns) = mapM newtypeDeclaration ns
-  where newtypeDeclaration n = newtypeD (cxt []) n [] (normalC n [strictType notStrict (conT t)]) []
+  where
+   newtypeDeclaration n = newtypeD (cxt []) n [] (normalC n [strictType notStrict (conT t)]) []
diff --git a/src/Network/Lastfm/Types.hs b/src/Network/Lastfm/Types.hs
deleted file mode 100644
--- a/src/Network/Lastfm/Types.hs
+++ /dev/null
@@ -1,162 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TemplateHaskell #-}
-module Network.Lastfm.Types where
-
-import Control.Applicative ((<$>), empty)
-import Control.Monad (liftM)
-import Data.Aeson ((.:), FromJSON, decode, parseJSON)
-import Data.ByteString.Lazy.Char8 (ByteString)
-import Data.List (intercalate)
-import Data.Maybe (fromJust)
-import qualified Data.Aeson
-
-import Network.Lastfm.TH
-
-newtype Secret = Secret String
-
-$(newtypes "String" ["Album", "AlbumArtist", "APIKey", "Artist", "AuthToken",
-  "Context", "Country", "Description", "Group", "Language", "Latitude",
-  "Location", "Longitude", "Mbid", "Message", "Method", "Metro", "Name",
-  "Recipient", "SessionKey", "Station", "StreamId", "Tag", "TaggingType",
-  "Title", "Token", "Track", "User", "Username", "Venuename", "ChosenByUser"])
-$(newtypes "Bool" ["Autocorrect", "BuyLinks", "Discovery", "FestivalsOnly", "Public", "RecentTracks", "RTP", "UseRecs"])
-$(newtypes "Int" ["Distance", "Duration", "Event", "Limit", "Page", "Playlist", "TrackNumber", "Venue"])
-$(newtypes "Integer" ["End", "EndTimestamp", "Fingerprint", "From", "Start", "StartTimestamp", "Timestamp", "To"])
-
-data Bitrate = B64 | B128
-data Multiplier = M1 | M2
-data Order = Popularity | DateAdded
-data Status = Yes | Maybe | No
-data Value = ValueUser User
-           | ValueArtists [Artist]
-data Period = Week | Quater | HalfYear | Year | Overall
-
-instance Show Value where
-  show (ValueUser _)    = "user"
-  show (ValueArtists _) = "artists"
-
-instance FromJSON Token where
-  parseJSON (Data.Aeson.Object v) = Token <$> v .: "token"
-  parseJSON _ = empty
-instance FromJSON SessionKey where
-  parseJSON (Data.Aeson.Object v) = SessionKey <$> ((v .: "session") >>= (.: "key"))
-  parseJSON _ = empty
-
-simple ∷ (FromJSON a, Monad m) ⇒ m ByteString → m a
-simple = liftM (fromJust . decode)
-
-class Argument a where
-  key ∷ a → String
-  value ∷ a → String
-
-(#) ∷ Argument a ⇒ a → (String, String)
-(#) x = (key x, value x)
-
-instance Argument a ⇒ Argument (Maybe a) where key = maybe "" key; value = maybe "" value
-instance Argument a ⇒ Argument [a] where
-  key (a:_) = key a ++ "s"
-  key [] = ""
-  value = intercalate "," . map value
-
-boolToString ∷ Bool → String
-boolToString True = "1"
-boolToString False = "0"
-
---instance Argument $first where key = const $second; value ($first a) = $func a
-$(instances "id"
-  [ ("Album","album")
-  , ("AlbumArtist", "albumartist")
-  , ("APIKey", "api_key")
-  , ("Artist", "artist")
-  , ("AuthToken", "authToken")
-  , ("ChosenByUser", "chosenByUser")
-  , ("Context", "context")
-  , ("Country", "country")
-  , ("Description", "description")
-  , ("Group", "group")
-  , ("Language", "lang")
-  , ("Latitude", "lat")
-  , ("Location", "location")
-  , ("Longitude", "long")
-  , ("Mbid", "mbid")
-  , ("Message", "message")
-  , ("Method", "method")
-  , ("Metro", "metro")
-  , ("Name", "name")
-  , ("Recipient", "recipient")
-  , ("SessionKey", "sk")
-  , ("Station", "station")
-  , ("StreamId", "streamId")
-  , ("Tag", "tag")
-  , ("TaggingType", "taggingtype")
-  , ("Title", "title")
-  , ("Token", "token")
-  , ("Track", "track")
-  , ("User", "user")
-  , ("Username", "username")
-  , ("Venuename", "venue")
-  ])
-
-$( instances "boolToString"
-  [ ("Autocorrect", "autocorrect")
-  , ("BuyLinks", "buylinks")
-  , ("Discovery", "discovery")
-  , ("FestivalsOnly", "festivalsonly")
-  , ("Public", "public")
-  , ("RecentTracks", "recenttracks")
-  , ("RTP", "rtp")
-  , ("UseRecs", "userecs")
-  ])
-
-$( instances "show"
-  [ ("Distance", "distance")
-  , ("Duration", "duration")
-  , ("Event", "event")
-  , ("Limit", "limit")
-  , ("Page", "page")
-  , ("Playlist", "playlistID")
-  , ("TrackNumber", "tracknumber")
-  , ("Venue", "venue")
-  , ("End", "end")
-  , ("EndTimestamp", "endTimestamp")
-  , ("Fingerprint", "fingerprintid")
-  , ("From", "from")
-  , ("Start", "start")
-  , ("StartTimestamp", "startTimestamp")
-  , ("Timestamp", "timestamp")
-  , ("To", "to")
-  ])
-
-instance Argument Bitrate where
-  key = const "bitrate"
-  value B64 = "64"
-  value B128 = "128"
-
-instance Argument Multiplier where
-  key = const "speed_multiplier"
-  value M1 = "1.0"
-  value M2 = "2.0"
-
-instance Argument Order where
-  key = const "order"
-  value Popularity = "popularity"
-  value DateAdded  = "dateadded"
-
-instance Argument Status where
-  key = const "status"
-  value Yes = "0"
-  value Maybe = "1"
-  value No = "2"
-
-instance Argument Value where
-  key = const "value"
-  value (ValueUser u)     = value u
-  value (ValueArtists as) = value as
-
-instance Argument Period where
-  key = const "period"
-  value Week     = "7day"
-  value Quater   = "3month"
-  value HalfYear = "6month"
-  value Year     = "12month"
-  value Overall  = "overall"
diff --git a/src/Network/Lastfm/XML/Album.hs b/src/Network/Lastfm/XML/Album.hs
--- a/src/Network/Lastfm/XML/Album.hs
+++ b/src/Network/Lastfm/XML/Album.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Album API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,52 +7,36 @@
   , getTopTags, removeTag, search, share
   ) where
 
-import Network.Lastfm
+#include "album.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Album as API
 
 $(xml ["addTags", "getBuyLinks", "getInfo", "getShouts", "getTags", "getTopTags", "removeTag", "search", "share"])
 
--- | Tag an album using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/album.addTags>
+__addTags__
 addTags ∷ (Artist, Album) → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of Buy Links for a particular Album. It is required that you supply either the artist and track params or the mbid param.
---
--- More: <http://www.last.fm/api/show/album.getBuylinks>
+__getBuyLinks__
 getBuyLinks ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Country → APIKey → Lastfm Response
 
--- | Get the metadata for an album on Last.fm using the album name or a musicbrainz id. See playlist.fetch on how to get the album playlist.
---
--- More: <http://www.last.fm/api/show/album.getInfo>
+__getInfo__
 getInfo ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Maybe Language → Maybe Username → APIKey → Lastfm Response
 
--- | Get shouts for this album.
---
--- More: <http://www.last.fm/api/show/album.getShouts>
+__getShouts__
 getShouts ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to an album on Last.fm.
---
--- More: <http://www.last.fm/api/show/album.getTags>
+__getTags__
 getTags ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top tags for an album on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/album.getTopTags>
+__getTopTags__
 getTopTags ∷ Either (Artist, Album) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Remove a user's tag from an album.
---
--- More: <http://www.last.fm/api/show/album.removeTag>
+__removeTag__
 removeTag ∷ Artist → Album → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Search for an album by name. Returns album matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/album.search>
+__search__
 search ∷ Album → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an album with one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/album.share>
+__share__
 share ∷ Artist → Album → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Artist.hs b/src/Network/Lastfm/XML/Artist.hs
--- a/src/Network/Lastfm/XML/Artist.hs
+++ b/src/Network/Lastfm/XML/Artist.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Artist API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,97 +8,63 @@
   , getTopFans, getTopTags, getTopTracks, removeTag, search, share, shout
   ) where
 
-import Network.Lastfm
+#include "artist.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Artist as API
-  
+
 $(xml ["addTags", "getCorrection", "getEvents", "getImages", "getInfo", "getPastEvents", "getPodcast", "getShouts", "getSimilar", "getTags", "getTopAlbums", "getTopFans", "getTopTags", "getTopTracks", "removeTag", "search", "share", "shout"])
 
--- | Tag an album using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/artist.addTags>
+__addTags__
 addTags ∷ Artist → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Use the last.fm corrections data to check whether the supplied artist has a correction to a canonical artist
---
--- More: <http://www.last.fm/api/show/artist.getCorrection>
+__getCorrection__
 getCorrection ∷ Artist → APIKey → Lastfm Response
 
--- | Get a list of upcoming events for this artist.
---
--- More: <http://www.last.fm/api/show/artist.getEvents>
+__getEvents__
 getEvents ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get Images for this artist in a variety of sizes.
---
--- More: <http://www.last.fm/api/show/artist.getImages>
+__getImages__
 getImages ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → Maybe Order → APIKey → Lastfm Response
 
--- | Get the metadata for an artist. Includes biography.
---
--- More: <http://www.last.fm/api/show/artist.getInfo>
+__getInfo__
 getInfo ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Language → Maybe Username → APIKey → Lastfm Response
 
--- | Get a paginated list of all the events this artist has played at in the past.
---
--- More: <http://www.last.fm/api/show/artist.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a podcast of free mp3s based on an artist.
---
--- More: <http://www.last.fm/api/show/artist.getPodcast>
+__getPodcast__
 getPodcast ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get shouts for this artist. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/artist.getShouts>
+__getShouts__
 getShouts ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get all the artists similar to this artist.
---
--- More: <http://www.last.fm/api/show/artist.getSimilar>
+__getSimilar__
 getSimilar ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to an artist on Last.fm. If accessed as an authenticated service /and/ you don't supply a user parameter then this service will return tags for the authenticated user.
---
--- More: <http://www.last.fm/api/show/artist.getTags>
+__getTags__
 getTags ∷ Either Artist Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top albums for an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top fans for an artist on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/artist.getTopFans>
+__getTopFans__
 getTopFans ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tags for an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopTags>
+__getTopTags__
 getTopTags ∷ Either Artist Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tracks by an artist on Last.fm, ordered by popularity.
---
--- More: <http://www.last.fm/api/show/artist.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Either Artist Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Remove a user's tag from an artist.
---
--- More: <http://www.last.fm/api/show/artist.removeTag>
+__removeTag__
 removeTag ∷ Artist → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Search for an artist by name. Returns artist matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/artist.search>
+__search__
 search ∷ Artist → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an artist with Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/artist.share>
+__share__
 share ∷ Artist → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Shout in this artist's shoutbox.
---
--- More: <http://www.last.fm/api/show/artist.shout>
+__shout__
 shout ∷ Artist → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Chart.hs b/src/Network/Lastfm/XML/Chart.hs
--- a/src/Network/Lastfm/XML/Chart.hs
+++ b/src/Network/Lastfm/XML/Chart.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Chart API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,37 +7,27 @@
   , getTopArtists, getTopTags, getTopTracks
   ) where
 
-import Network.Lastfm
+#include "chart.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Chart as API
 
 $(xml ["getHypedArtists", "getHypedTracks", "getLovedTracks", "getTopArtists", "getTopTags", "getTopTracks"])
 
--- | Get the hyped artists chart.
---
--- More: <http://www.last.fm/api/show/chart.getHypedArtists>
+__getHypedArtists__
 getHypedArtists ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the hyped tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getHypedTracks>
+__getHypedTracks__
 getHypedTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the most loved tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getLovedTracks>
+__getLovedTracks__
 getLovedTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get top tags chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopTags>
+__getTopTags__
 getTopTags ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tracks chart.
---
--- More: <http://www.last.fm/api/show/chart.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Event.hs b/src/Network/Lastfm/XML/Event.hs
--- a/src/Network/Lastfm/XML/Event.hs
+++ b/src/Network/Lastfm/XML/Event.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Event API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,37 +6,27 @@
   ( attend, getAttendees, getInfo, getShouts, share, shout
   ) where
 
-import Network.Lastfm
+#include "event.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Event as API
 
 $(xml ["attend", "getAttendees", "getInfo", "getShouts", "share", "shout"])
 
--- | Set a user's attendance status for an event.
---
--- More: <http://www.last.fm/api/show/event.attend>
+__attend__
 attend ∷ Event → Status → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of attendees for an event.
---
--- More: <http://www.last.fm/api/show/event.getAttendees>
+__getAttendees__
 getAttendees ∷ Event → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the metadata for an event on Last.fm. Includes attendance and lineup information.
---
--- More: <http://www.last.fm/api/show/event.getInfo>
+__getInfo__
 getInfo ∷ Event → APIKey → Lastfm Response
 
--- | Get shouts for this event.
---
--- More: <http://www.last.fm/api/show/event.getShouts>
+__getShouts__
 getShouts ∷ Event → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Share an event with one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/event.share>
+__share__
 share ∷ Event → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Shout in this event's shoutbox.
---
--- More: <http://www.last.fm/api/show/event.shout>
+__shout__
 shout ∷ Event → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Geo.hs b/src/Network/Lastfm/XML/Geo.hs
--- a/src/Network/Lastfm/XML/Geo.hs
+++ b/src/Network/Lastfm/XML/Geo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Geo API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,14 +8,14 @@
   , getMetroWeeklyChartlist, getMetros, getTopArtists, getTopTracks
   ) where
 
-import Network.Lastfm
+#include "geo.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Geo as API
 
 $(xml ["getEvents", "getMetroArtistChart", "getMetroHypeArtistChart", "getMetroHypeTrackChart", "getMetroTrackChart", "getMetroUniqueArtistChart", "getMetroUniqueTrackChart", "getMetroWeeklyChartlist", "getMetros", "getTopArtists", "getTopTracks"])
 
--- | Get all events in a specific location by country or city name.
---
--- More: <http://www.last.fm/api/show/geo.getEvents>
+__getEvents__
 getEvents ∷ Maybe Latitude
           → Maybe Longitude
           → Maybe Location
@@ -24,52 +25,32 @@
           → APIKey
           → Lastfm Response
 
--- | Get a chart of artists for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroArtistChart>
+__getMetroArtistChart__
 getMetroArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of hyped (up and coming) artists for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroHypeArtistChart>
+__getMetroHypeArtistChart__
 getMetroHypeArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of hyped (up and coming) tracks for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroHypeTrackChart>
+__getMetroHypeTrackChart__
 getMetroHypeTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of tracks for a metro.
---
--- More: <http://www.last.fm/api/show/geo.getMetroTrackChart>
+__getMetroTrackChart__
 getMetroTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of the artists which make that metro unique.
---
--- More: <http://www.last.fm/api/show/geo.getMetroUniqueArtistChart>
+__getMetroUniqueArtistChart__
 getMetroUniqueArtistChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a chart of the tracks which make that metro unique.
---
--- More: <http://www.last.fm/api/show/geo.getMetroUniqueTrackChart>
+__getMetroUniqueTrackChart__
 getMetroUniqueTrackChart ∷ Country → Metro → Maybe Start → Maybe End → APIKey → Lastfm Response
 
--- | Get a list of available chart periods for this metro, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/geo.getMetroWeeklyChartlist>
+__getMetroWeeklyChartlist__
 getMetroWeeklyChartlist ∷ Metro → APIKey → Lastfm Response
 
--- | Get a list of valid countries and metros for use in the other webservices.
---
--- More: <http://www.last.fm/api/show/geo.getMetros>
+__getMetros__
 getMetros ∷ Maybe Country → APIKey → Lastfm Response
 
--- | Get the most popular artists on Last.fm by country.
---
--- More: <http://www.last.fm/api/show/geo.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Country → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the most popular tracks on Last.fm last week by country.
---
--- More: <http://www.last.fm/api/show/geo.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Country → Maybe Location → Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Group.hs b/src/Network/Lastfm/XML/Group.hs
--- a/src/Network/Lastfm/XML/Group.hs
+++ b/src/Network/Lastfm/XML/Group.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Group API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,38 +6,27 @@
   ( getHype, getMembers, getWeeklyChartList, getWeeklyAlbumChart, getWeeklyArtistChart, getWeeklyTrackChart
   ) where
 
-import Network.Lastfm
+#include "group.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Group as API
 
 $(xml ["getHype", "getMembers", "getWeeklyChartList", "getWeeklyAlbumChart", "getWeeklyArtistChart", "getWeeklyTrackChart"])
 
--- | Get the hype list for a group.
---
--- More: <http://www.last.fm/api/show/group.getHype>
+__getHype__
 getHype ∷ Group → APIKey → Lastfm Response
 
--- | Get a list of members for this group.
---
--- More: <http://www.last.fm/api/show/group.getMembers>
+__getMembers__
 getMembers ∷ Group → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an album chart for a group, for a given date range. If no date range is supplied, it will return the most recent album chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyAlbumChart>
+__getWeeklyChartList__
 getWeeklyChartList ∷ Group → APIKey → Lastfm Response
 
--- | Get an artist chart for a group, for a given date range. If no date range is supplied, it will return the most recent artist chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyArtistChart>
+__getWeeklyAlbumChart__
 getWeeklyAlbumChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get a list of available charts for this group, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyChartList>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
 
-
--- | Get a track chart for a group, for a given date range. If no date range is supplied, it will return the most recent track chart for this group.
---
--- More: <http://www.last.fm/api/show/group.getWeeklyTrackChart>
+__getWeeklyTrackChart__
 getWeeklyTrackChart ∷ Group → Maybe From → Maybe To → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Library.hs b/src/Network/Lastfm/XML/Library.hs
--- a/src/Network/Lastfm/XML/Library.hs
+++ b/src/Network/Lastfm/XML/Library.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Library API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,57 +7,39 @@
   , removeAlbum, removeArtist, removeScrobble, removeTrack
   ) where
 
-import Network.Lastfm
+#include "library.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Library as API
-  
+
 $(xml ["addAlbum", "addArtist", "addTrack", "getAlbums", "getArtists", "getTracks", "removeAlbum", "removeArtist", "removeScrobble", "removeTrack"])
 
--- | Add an album or collection of albums to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addAlbum>
+__addAlbum__
 addAlbum ∷ Artist → Album → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Add an artist to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addArtist>
+__addArtist__
 addArtist ∷ Artist → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Add a track to a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.addTrack>
+__addTrack__
 addTrack ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | A paginated list of all the albums in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getAlbums>
+__getAlbums__
 getAlbums ∷ User → Maybe Artist → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | A paginated list of all the artists in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getArtists>
+__getArtists__
 getArtists ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | A paginated list of all the tracks in a user's library, with play counts and tag counts.
---
--- More: <http://www.last.fm/api/show/library.getTracks>
+__getTracks__
 getTracks ∷ User → Maybe Artist → Maybe Album → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Remove an album from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeAlbum>
+__removeAlbum__
 removeAlbum ∷ Artist → Album → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove an artist from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeArtist>
+__removeArtist__
 removeArtist ∷ Artist → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a scrobble from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeScrobble>
+__removeScrobble__
 removeScrobble ∷ Artist → Track → Timestamp → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a track from a user's Last.fm library.
---
--- More: <http://www.last.fm/api/show/library.removeTrack>
+__removeTrack__
 removeTrack ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Playlist.hs b/src/Network/Lastfm/XML/Playlist.hs
--- a/src/Network/Lastfm/XML/Playlist.hs
+++ b/src/Network/Lastfm/XML/Playlist.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Playlist API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,17 +6,15 @@
   ( addTrack, create
   ) where
 
-import Network.Lastfm
+#include "playlist.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Playlist as API
 
 $(xml ["addTrack", "create"])
 
--- | Add a track to a Last.fm user's playlist.
---
--- More: <http://www.last.fm/api/show/playlist.addTrack>
+__addTrack__
 addTrack ∷ Playlist → Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Create a Last.fm playlist on behalf of a user.
---
--- More: <http://www.last.fm/api/show/playlist.create>
+__create__
 create ∷ Maybe Title → Maybe Description → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Radio.hs b/src/Network/Lastfm/XML/Radio.hs
--- a/src/Network/Lastfm/XML/Radio.hs
+++ b/src/Network/Lastfm/XML/Radio.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Radio API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,14 +6,14 @@
   ( getPlaylist, search, tune
   ) where
 
-import Network.Lastfm
+#include "radio.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Radio as API
 
 $(xml ["getPlaylist", "search", "tune"])
 
--- | Fetch new radio content periodically in an XSPF format.
---
--- More: <http://www.last.fm/api/show/radio.getPlaylist>
+__getPlaylist__
 getPlaylist ∷ Maybe Discovery
             → Maybe RTP
             → Maybe BuyLinks
@@ -23,12 +24,8 @@
             → Secret
             → Lastfm Response
 
--- | Resolve the name of a resource into a station depending on which resource it is most likely to represent.
---
--- More: <http://www.last.fm/api/show/radio.search>
+__search__
 search ∷ Name → APIKey → Lastfm Response
 
--- | Tune in to a Last.fm radio station.
---
--- More: <http://www.last.fm/api/show/radio.tune>
+__tune__
 tune ∷ Maybe Language → Station → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Tag.hs b/src/Network/Lastfm/XML/Tag.hs
--- a/src/Network/Lastfm/XML/Tag.hs
+++ b/src/Network/Lastfm/XML/Tag.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Tag API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -6,52 +7,36 @@
   , getWeeklyArtistChart, getWeeklyChartList, search
   ) where
 
-import Network.Lastfm
+#include "tag.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Tag as API
 
 $(xml ["getInfo", "getSimilar", "getTopAlbums", "getTopArtists", "getTopTags", "getTopTracks", "getWeeklyArtistChart", "getWeeklyChartList", "search"])
 
--- | Get the metadata for a tag.
---
--- More: <http://www.last.fm/api/show/tag.getInfo>
+__getInfo__
 getInfo ∷ Tag → Maybe Language → APIKey → Lastfm Response
 
--- | Search for tags similar to this one. Returns tags ranked by similarity, based on listening data.
---
--- More: <http://www.last.fm/api/show/tag.getSimilar>
+__getSimilar__
 getSimilar ∷ Tag → APIKey → Lastfm Response
 
--- | Get the top albums tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Fetches the top global tags on Last.fm, sorted by popularity (number of times used).
---
--- More: <http://www.last.fm/api/show/tag.getTopTags>
+__getTopTags__
 getTopTags ∷ APIKey → Lastfm Response
 
--- | Get the top tracks tagged by this tag, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/tag.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an artist chart for a tag, for a given date range. If no date range is supplied, it will return the most recent artist chart for this tag.
---
--- More: <http://www.last.fm/api/show/tag.getWeeklyArtistChart>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ Tag → Maybe From → Maybe To → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of available charts for this tag, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/tag.getWeeklyChartList>
+__getWeeklyChartList__
 getWeeklyChartList ∷ Tag → APIKey → Lastfm Response
 
--- | Search for a tag by name. Returns matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/tag.search>
+__search__
 search ∷ Tag → Maybe Page → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Tasteometer.hs b/src/Network/Lastfm/XML/Tasteometer.hs
--- a/src/Network/Lastfm/XML/Tasteometer.hs
+++ b/src/Network/Lastfm/XML/Tasteometer.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Tasteometer API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,14 +6,14 @@
   ( compare
   ) where
 
+#include "tasteometer.docs"
+
 import Prelude hiding (compare)
 
-import Network.Lastfm
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Tasteometer as API
 
 $(xml ["compare"])
 
--- | Get a Tasteometer score from two inputs, along with a list of shared artists. If the input is a User some additional information is returned.
---
--- More: <http://www.last.fm/api/show/tasteometer.compare>
+__compare__
 compare ∷ Value → Value → Maybe Limit → APIKey → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Track.hs b/src/Network/Lastfm/XML/Track.hs
--- a/src/Network/Lastfm/XML/Track.hs
+++ b/src/Network/Lastfm/XML/Track.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Track API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -7,79 +8,53 @@
   , love, removeTag, scrobble, search, share, unban, unlove, updateNowPlaying
   ) where
 
-import Network.Lastfm
+#include "track.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Track as API
 
 $(xml ["addTags", "ban", "getBuyLinks", "getCorrection", "getFingerprintMetadata", "getInfo", "getShouts", "getSimilar", "getTags", "getTopFans", "getTopTags", "love", "removeTag", "scrobble", "search", "share", "unban", "unlove", "updateNowPlaying"])
 
--- | Tag a track using a list of user supplied tags.
---
--- More: <http://www.last.fm/api/show/track.addTags>
+__addTags__
 addTags ∷ Artist → Track → [Tag] → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Ban a track for a given user profile.
---
--- More: <http://www.last.fm/api/show/track.ban>
+__ban__
 ban ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of Buy Links for a particular track.
---
--- More: <http://www.last.fm/api/show/track.getBuylinks>
+__getBuyLinks__
 getBuyLinks ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Country → APIKey → Lastfm Response
 
--- | Use the last.fm corrections data to check whether the supplied track has a correction to a canonical track.
---
--- More: <http://www.last.fm/api/show/track.getCorrection>
+__getCorrection__
 getCorrection ∷ Artist → Track → APIKey → Lastfm Response
 
--- | Retrieve track metadata associated with a fingerprint id generated by the Last.fm Fingerprinter. Returns track elements, along with a 'rank' value between 0 and 1 reflecting the confidence for each match.
---
--- More: <http://www.last.fm/api/show/track.getFingerprintMetadata>
+__getFingerprintMetadata__
 getFingerprintMetadata ∷ Fingerprint → APIKey → Lastfm Response
 
--- | Get the metadata for a track on Last.fm.
---
--- More: <http://www.last.fm/api/show/track.getInfo>
+__getInfo__
 getInfo ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Username → APIKey → Lastfm Response
 
--- | Get shouts for this track. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/track.getShouts>
+__getShouts__
 getShouts ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the similar tracks for this track on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/track.getSimilar>
+__getSimilar__
 getSimilar ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the tags applied by an individual user to a track on Last.fm.
---
--- More: <http://www.last.fm/api/show/track.getTags>
+__getTags__
 getTags ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → Either User (SessionKey, Secret) → APIKey → Lastfm Response
 
--- | Get the top fans for this track on Last.fm, based on listening data.
---
--- More: <http://www.last.fm/api/show/track.getTopFans>
+__getTopFans__
 getTopFans ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Get the top tags for this track on Last.fm, ordered by tag count.
---
--- More: <http://www.last.fm/api/show/track.getTopTags>
+__getTopTags__
 getTopTags ∷ Either (Artist, Track) Mbid → Maybe Autocorrect → APIKey → Lastfm Response
 
--- | Love a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.love>
+__love__
 love ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Remove a user's tag from a track.
---
--- More: <http://www.last.fm/api/show/track.removeTag>
+__removeTag__
 removeTag ∷ Artist → Track → Tag → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Used to add a track-play to a user's profile.
---
--- More: <http://www.last.fm/api/show/track.scrobble>
+__scrobble__
 scrobble ∷ ( Timestamp, Maybe Album, Artist, Track, Maybe AlbumArtist
            , Maybe Duration, Maybe StreamId, Maybe ChosenByUser
            , Maybe Context, Maybe TrackNumber, Maybe Mbid )
@@ -88,30 +63,19 @@
          → Secret
          → Lastfm Response
 
--- | Search for a track by track name. Returns track matches sorted by relevance.
---
--- More: <http://www.last.fm/api/show/track.search>
+__search__
 search ∷ Track → Maybe Page → Maybe Limit → Maybe Artist → APIKey → Lastfm Response
 
--- | Share a track twith one or more Last.fm users or other friends.
---
--- More: <http://www.last.fm/api/show/track.share>
+__share__
 share ∷ Artist → Track → Recipient → Maybe Message → Maybe Public → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Unban a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.unban>
+__unban__
 unban ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Unlove a track for a user profile.
---
--- More: <http://www.last.fm/api/show/track.unlove>
+__unlove__
 unlove ∷ Artist → Track → APIKey → SessionKey → Secret → Lastfm Response
 
-
--- | Used to notify Last.fm that a user has started listening to a track. Parameter names are case sensitive.
---
--- More: <http://www.last.fm/api/show/track.updateNowPlaying>
+__updateNowPlaying__
 updateNowPlaying ∷ Artist
                  → Track
                  → Maybe Album
diff --git a/src/Network/Lastfm/XML/User.hs b/src/Network/Lastfm/XML/User.hs
--- a/src/Network/Lastfm/XML/User.hs
+++ b/src/Network/Lastfm/XML/User.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | User API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -9,132 +10,84 @@
   , getWeeklyChartList, getWeeklyTrackChart, shout
   ) where
 
-import Network.Lastfm
+#include "user.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.User as API
 
 $(xml ["getArtistTracks", "getBannedTracks", "getEvents", "getFriends", "getInfo", "getLovedTracks", "getNeighbours", "getNewReleases", "getPastEvents", "getPersonalTags", "getPlaylists", "getRecentStations", "getRecentTracks", "getRecommendedArtists", "getRecommendedEvents", "getShouts", "getTopAlbums", "getTopArtists", "getTopTags", "getTopTracks", "getWeeklyAlbumChart", "getWeeklyArtistChart", "getWeeklyChartList", "getWeeklyTrackChart", "shout"])
 
--- | Get a list of tracks by a given artist scrobbled by this user, including scrobble time. Can be limited to specific timeranges, defaults to all time.
---
--- More: <http://www.last.fm/api/show/user.getArtistTracks>
+__getArtistTracks__
 getArtistTracks ∷ User → Artist → Maybe StartTimestamp → Maybe EndTimestamp → Maybe Page → APIKey → Lastfm Response
 
--- | Returns the tracks banned by the user.
---
--- More: <http://www.last.fm/api/show/user.getBannedTracks>
+__getBannedTracks__
 getBannedTracks ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of upcoming events that this user is attending.
---
--- Mpre: <http://www.last.fm/api/show/user.getEvents>
+__getEvents__
 getEvents ∷ User → Maybe Page → Maybe Limit → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get a list of the user's friends on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getFriends>
+__getFriends__
 getFriends ∷ User → Maybe RecentTracks → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get information about a user profile.
---
--- More: <http://www.last.fm/api/show/user.getInfo>
+__getInfo__
 getInfo ∷ Maybe User → APIKey → Lastfm Response
 
--- | Get tracks loved by a user.
---
--- More: <http://www.last.fm/api/show/user.getLovedTracks>
+__getLovedTracks__
 getLovedTracks ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of a user's neighbours on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getNeighbours>
+__getNeighbours__
 getNeighbours ∷ User → Maybe Limit → APIKey → Lastfm Response
 
--- | Gets a list of forthcoming releases based on a user's musical taste.
---
--- More: <http://www.last.fm/api/show/user.getNewReleases>
+__getNewReleases__
 getNewReleases ∷ User → Maybe UseRecs → APIKey → Lastfm Response
 
--- | Get a paginated list of all events a user has attended in the past.
---
--- More: <http://www.last.fm/api/show/user.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the user's personal tags.
---
--- More: <http://www.last.fm/api/show/user.getPersonalTags>
+__getPersonalTags__
 getPersonalTags ∷ User → Tag → TaggingType → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get a list of a user's playlists on Last.fm.
---
--- More: <http://www.last.fm/api/show/user.getPlaylists>
+__getPlaylists__
 getPlaylists ∷ User → APIKey → Lastfm Response
 
--- | Get a list of the recent Stations listened to by this user.
---
--- More: <http://www.last.fm/api/show/user.getRecentStations>
+__getRecentStations__
 getRecentStations ∷ User → Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a list of the recent tracks listened to by this user. Also includes the currently playing track with the nowplaying="true" attribute if the user is currently listening.
---
--- More: <http://www.last.fm/api/show/user.getRecentTracks>
+__getRecentTracks__
 getRecentTracks ∷ User → Maybe Page → Maybe Limit → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get Last.fm artist recommendations for a user.
---
--- Mpre: <http://www.last.fm/api/show/user.getRecommendedArtists>
+__getRecommendedArtists__
 getRecommendedArtists ∷ Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get a paginated list of all events recommended to a user by Last.fm, based on their listening profile.
---
--- More: <http://www.last.fm/api/show/user.getRecommendedEvents>
+__getRecommendedEvents__
 getRecommendedEvents ∷ Maybe Page → Maybe Limit → APIKey → SessionKey → Secret → Lastfm Response
 
--- | Get shouts for this user. Also available as an rss feed.
---
--- More: <http://www.last.fm/api/show/user.getShouts>
+__getShouts__
 getShouts ∷ User → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top albums listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopAlbums>
+__getTopAlbums__
 getTopAlbums ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top artists listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopArtists>
+__getTopArtists__
 getTopArtists ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tags used by this user.
---
--- More: <http://www.last.fm/api/show/user.getTopTags>
+__getTopTags__
 getTopTags ∷ User → Maybe Limit → APIKey → Lastfm Response
 
--- | Get the top tracks listened to by a user. You can stipulate a time period. Sends the overall chart by default.
---
--- More: <http://www.last.fm/api/show/user.getTopTracks>
+__getTopTracks__
 getTopTracks ∷ User → Maybe Period → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Get an album chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent album chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyAlbumChart>
+__getWeeklyAlbumChart__
 getWeeklyAlbumChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get an artist chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent artist chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyArtistChart>
+__getWeeklyArtistChart__
 getWeeklyArtistChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Get a list of available charts for this user, expressed as date ranges which can be sent to the chart services.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyChartList>
+__getWeeklyChartList__
 getWeeklyChartList ∷ User → APIKey → Lastfm Response
 
--- | Get a track chart for a user profile, for a given date range. If no date range is supplied, it will return the most recent track chart for this user.
---
--- More: <http://www.last.fm/api/show/user.getWeeklyTrackChart>
+__getWeeklyTrackChart__
 getWeeklyTrackChart ∷ User → Maybe From → Maybe To → APIKey → Lastfm Response
 
--- | Shout on this user's shoutbox.
---
--- More: <http://www.last.fm/api/show/user.shout>
+__shout__
 shout ∷ User → Message → APIKey → SessionKey → Secret → Lastfm Response
diff --git a/src/Network/Lastfm/XML/Venue.hs b/src/Network/Lastfm/XML/Venue.hs
--- a/src/Network/Lastfm/XML/Venue.hs
+++ b/src/Network/Lastfm/XML/Venue.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 -- | Venue API module
 {-# OPTIONS_HADDOCK prune #-}
@@ -5,22 +6,18 @@
   ( getEvents, getPastEvents, search
   ) where
 
-import Network.Lastfm
+#include "venue.docs"
+
+import Network.Lastfm.Internal
 import qualified Network.Lastfm.API.Venue as API
 
 $(xml ["getEvents", "getPastEvents", "search"])
 
--- | Get a list of upcoming events at this venue.
---
--- More: <http://www.last.fm/api/show/venue.getEvents>
+__getEvents__
 getEvents ∷ Venue → Maybe FestivalsOnly → APIKey → Lastfm Response
 
--- | Get a paginated list of all the events held at this venue in the past.
---
--- More: <http://www.last.fm/api/show/venue.getPastEvents>
+__getPastEvents__
 getPastEvents ∷ Venue → Maybe FestivalsOnly → Maybe Page → Maybe Limit → APIKey → Lastfm Response
 
--- | Search for a venue by venue name.
---
--- More: <http://www.last.fm/api/show/venue.search>
+__search__
 search ∷ Venuename → Maybe Page → Maybe Limit → Maybe Country → APIKey → Lastfm Response
