diff --git a/Web/GooglePlus.hs b/Web/GooglePlus.hs
--- a/Web/GooglePlus.hs
+++ b/Web/GooglePlus.hs
@@ -23,7 +23,7 @@
 -- > doStuff :: GooglePlusM ()
 -- > doStuff = do
 -- >   Right person <- getPerson Me
--- >   Right feed   <- getActivityFeed Me PublicCollection
+-- >   Right feed   <- getLatestActivityFeed Me PublicCollection
 -- >   -- ...
 -- >   return ()
 -- > 
@@ -34,48 +34,159 @@
 -- 
 --------------------------------------------------------------------
 
-{-# LANGUAGE OverloadedStrings #-}
-module Web.GooglePlus (getPerson, getActivity, getActivityFeed) where
+{-# LANGUAGE OverloadedStrings, FlexibleContexts, TypeSynonymInstances #-}
+module Web.GooglePlus (getPerson,
+                       getActivity,
+                       getLatestActivityFeed,
+                       enumActivityFeed,
+                       enumActivities) where
 
 import Web.GooglePlus.Types
 import Web.GooglePlus.Monad
 
+import           Control.Applicative ((<$>), (<*>))
 import           Control.Monad.IO.Class (liftIO)
 import           Control.Monad.Reader (asks)
-import           Data.Aeson (json, FromJSON, fromJSON, Result(..))
+import           Control.Monad.Trans.Class (lift)
+import           Data.Aeson (json,
+                             FromJSON,
+                             fromJSON,
+                             parseJSON,
+                             Result(..),
+                             (.:?),
+                             Value(Object))
+import           Data.Aeson.Types (typeMismatch)
 import           Data.Attoparsec.Lazy (parse, eitherResult)
-import           Data.ByteString (ByteString)
+import           Data.ByteString (ByteString, append)
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Char8 as BS8
 import qualified Data.ByteString.Lazy as LBS
-import           Data.ByteString (append)
+import           Data.Enumerator (Enumerator,
+                                  joinI,
+                                  checkContinue1,
+                                  continue,
+                                  Stream (Chunks),
+                                  (>>==),
+                                  ($=),
+                                  ($$))
+import qualified Data.Enumerator.List as EL
+import           Data.Maybe (fromMaybe)
 import           Data.Text (Text, pack)
 import           Data.Text.Encoding (encodeUtf8, decodeUtf8)
 import           Network.HTTP.Enumerator
 import           Network.HTTP.Types (Ascii, Query, QueryItem)
 
 -- | Get a person who matches the given identifier
-getPerson :: PersonID -> GooglePlusM (Either Text Person)
+getPerson :: PersonID -- ^ Identifier for the person to fetch
+             -> GooglePlusM (Either Text Person)
 getPerson pid = genericGet pth []
   where pth = personIdPath pid
 
 
 -- | Get an activity who matches the given activity ID
-getActivity :: ID -> GooglePlusM (Either Text Activity)
+getActivity :: ID -- ^ Specific ID to fetch
+               -> GooglePlusM (Either Text Activity)
 getActivity aid = genericGet pth []
   where pth = append "/plus/v1/activities/" $ encodeUtf8 aid
 
---TODO: pagetoken, pagination, limits, enumerator?
-
 -- | Get an activity who matches the given activity ID and collection to use.
--- Currently uses the default page size (20) and only fetches the first page. I
--- plan to add pagination fairly soon and possibly an enumerator a bit later
-getActivityFeed :: PersonID -> ActivityCollection -> GooglePlusM (Either Text ActivityFeed)
-getActivityFeed pid coll = genericGet pth []
+-- Default page size is (20) and only fetches the first page.
+-- You will receive an error from the server if the page size exceeds 100.
+getLatestActivityFeed :: PersonID              -- ^ Feed owner ID
+                         -> ActivityCollection -- ^ Indicates what type of feed to retrieve
+                         -> Maybe Integer      -- ^ Page size. Should be between 1 and 100. Default 20.
+                         -> GooglePlusM (Either Text ActivityFeed)
+getLatestActivityFeed pid coll perPage = do
+  feed <- getActivityFeedPage pid coll (perPage' perPage) Nothing
+  return $ fst `fmap` feed
+
+-- | Paginating enumerator to consume a user's activity stream. Each chunk will
+-- end up being an array with a single ActivityFeed in it with 1 page of data
+-- in it. This weirdness about the chunks only containing 1 element is mostly
+-- to maintain the metadata available on ActivityFeed and have it available in
+-- each chunk. For a more natural chunking of just Activities if you don't need
+-- that additional metadata, see enumActivities. Note that this Enumerator will
+-- abort if it encounters an error from the server, thus cutting the list
+-- short.
+enumActivityFeed :: PersonID              -- ^ Feed owner ID
+                    -> ActivityCollection -- ^ Indicates what type of feed to retrieve
+                    -> Maybe Integer      -- ^ Page size. Should be between 1 and 100. Defualt 20
+                    -> Enumerator ActivityFeed GooglePlusM b
+enumActivityFeed pid coll perPage = EL.unfoldM depaginate FirstPage
+  where depaginate = depaginateActivityFeed pid coll $ perPage' perPage
+
+-- | Paginating enumerator yielding a Chunk for each page. Use this if you
+-- don't need the feed metadata that enumActivityFeed provides.
+enumActivities :: PersonID              -- ^ Feed owner ID
+                  -> ActivityCollection -- ^ Indicates what type of feed to retrieve
+                  -> Maybe Integer      -- ^ Page size. Should be between 1 and 100. Defualt 20
+                  -> Enumerator Activity GooglePlusM b
+enumActivities pid coll perPage = unfoldListM depaginate FirstPage
+  where depaginate = depaginateActivities pid coll (perPage' perPage)
+
+---- Helpers
+
+perPage' :: Maybe Integer -> Integer
+perPage' = fromMaybe defaultPageSize
+
+defaultPageSize :: Integer
+defaultPageSize = 20
+
+type PageToken             = Text
+type PaginatedActivityFeed = (ActivityFeed, Maybe PageToken)
+
+instance FromJSON PaginatedActivityFeed where
+  parseJSON (Object v) = (,) <$> parseJSON (Object v)
+                             <*> v .:? "nextPageToken"
+  parseJSON v          = typeMismatch "PaginatedActivityFeed" v
+
+data DepaginationState     = FirstPage |
+                             MorePages PageToken |
+                             NoMorePages
+
+-- Exactly the same as unfoldM but takes the result of the stateful function
+-- and uses it as the chunks, rather than a Chunks with a singleton list
+unfoldListM :: Monad m => (s -> m (Maybe ([a], s))) -> s -> Enumerator a m b
+unfoldListM f = checkContinue1 $ \loop s k -> do
+	fs <- lift (f s)
+	case fs of
+		Nothing -> continue k
+		Just (as, s') -> k (Chunks as) >>== loop s'
+
+depaginateActivities:: PersonID -> ActivityCollection -> Integer -> DepaginationState -> GooglePlusM (Maybe ([Activity], DepaginationState))
+depaginateActivities pid coll perPage state = (return . (fmap unwrap)) =<< depaginateActivityFeed pid coll perPage state
+  where unwrap (feed, s) = (activityFeedItems feed, s)
+
+depaginateActivityFeed :: PersonID -> ActivityCollection -> Integer -> DepaginationState -> GooglePlusM (Maybe (ActivityFeed, DepaginationState))
+depaginateActivityFeed pid coll perPage FirstPage       = do
+ page <- getFirstFeedPage pid coll perPage
+ return $ paginatedFeedState `fmap` page
+depaginateActivityFeed pid coll perPage (MorePages tok) = do
+ page <- getActivityFeedPage pid coll perPage $ Just tok
+ return $ paginatedFeedState `fmap` eitherMaybe page
+depaginateActivityFeed _ _ _ NoMorePages                = return Nothing
+
+paginatedFeedState :: PaginatedActivityFeed -> (ActivityFeed, DepaginationState)
+paginatedFeedState (feed, token) = (feed, maybe NoMorePages MorePages token)
+
+getFirstFeedPage :: PersonID -> ActivityCollection -> Integer -> GooglePlusM (Maybe PaginatedActivityFeed)
+getFirstFeedPage pid coll perPage = do
+  page <- getActivityFeedPage pid coll perPage Nothing
+  return $ eitherMaybe page
+
+getActivityFeedPage :: PersonID -> ActivityCollection -> Integer -> Maybe PageToken -> GooglePlusM (Either Text PaginatedActivityFeed)
+getActivityFeedPage pid coll perPage tok = genericGet pth params
   where pth  = append pidP actP
         pidP = personIdPath pid
         actP = append "/activities/" $ collectionPath coll
+        pageParam = BS8.pack . show $ perPage
+        params = case tok of
+                  Nothing -> [("maxResults", Just pageParam)]
+                  Just t  -> [("maxResults", Just pageParam), ("pageToken", Just $ encodeUtf8 t)]
 
----- Helpers
+eitherMaybe :: Either a b -> Maybe b
+eitherMaybe (Left _)  = Nothing
+eitherMaybe (Right x) = Just x
 
 genericGet :: FromJSON a => Ascii -> Query -> GooglePlusM (Either Text a)
 genericGet pth qs = withEnv $ \auth -> do
@@ -96,15 +207,14 @@
   where req = genRequest auth pth q
 
 genRequest :: GooglePlusAuth -> Ascii -> Query -> Request m
-genRequest auth pth q = def { host = h,
-                              path = pth,
-                              port = 443,
-                              secure = True,
+genRequest auth pth q = def { host        = h,
+                              path        = pth,
+                              port        = 443,
+                              secure      = True,
                               queryString = q' }
   where h     = "www.googleapis.com"
         authq = authParam auth
         q'    = authq:q
-
 
 authParam :: GooglePlusAuth -> QueryItem
 authParam (APIKey key)     = ("key", Just $ encodeUtf8 key)
diff --git a/Web/GooglePlus/Types.hs b/Web/GooglePlus/Types.hs
--- a/Web/GooglePlus/Types.hs
+++ b/Web/GooglePlus/Types.hs
@@ -42,7 +42,6 @@
                              Place(..),
                              RelationshipStatus(..)) where
 
-import           Data.Aeson.Types (Parser, typeMismatch)
 import           Control.Applicative ((<$>), (<*>), pure)
 import           Data.Aeson (Value(..),
                              Object,
@@ -50,6 +49,7 @@
                              parseJSON,
                              (.:),
                              (.:?))
+import           Data.Aeson.Types (Parser, typeMismatch)
 import qualified Data.Map as M
 import           Data.Time.Calendar (Day(..))
 import           Data.Time.LocalTime (ZonedTime(..), zonedTimeToUTC)
@@ -100,7 +100,6 @@
                            activityPlaceName       :: Maybe Text
                          } deriving (Show, Eq)
 
---TODO: activities
 instance FromJSON Activity where
   parseJSON (Object v) = Activity <$> v .:? "placeholder"
                                   <*> v .:  "title"
diff --git a/googleplus.cabal b/googleplus.cabal
--- a/googleplus.cabal
+++ b/googleplus.cabal
@@ -1,5 +1,5 @@
 name: googleplus
-version: 0.1.0
+version: 0.2.1
 synopsis: Haskell implementation of the Google+ API
 description:
    Will implement the Google+ REST API. Google+ is a social network made by
@@ -26,18 +26,19 @@
  Ghc-Options:     -Wall
  build-depends:   base            >= 4        && < 5,
                   aeson           >= 0.3.1.1  && < 0.4,
-                  bytestring      >= 0.9.1.10 && < 0.10,
-                  text            >= 0.11.0.5 && < 0.12,
                   attoparsec      >= 0.9.1.2  && < 0.10,
+                  containers      >= 0.4.0.0  && < 0.5,
+                  bytestring      >= 0.9.1.10 && < 0.10,
+                  enumerator      >= 0.4.9    && < 0.5,
+                  haskell98       >= 1.1.0.1  && < 1.2,
                   http-enumerator >= 0.7.0    && < 0.8,
+                  http-types      >= 0.6.0    && < 0.7,
                   mtl             >= 2.0.1.0  && < 2.1,
                   rfc3339         >= 1.0.4    && < 1.1,
+                  text            >= 0.11.0.5 && < 0.12,
                   time            >= 1.2.0.3  && < 1.5,
                   transformers    >= 0.2.2.0  && < 0.3,
-                  http-types      >= 0.6.0    && < 0.7,
-                  url             >= 2.1.2    && < 2.3,
-                  haskell98       >= 1.1.0.1  && < 1.2,
-                  containers      >= 0.4.0.0  && < 0.5
+                  url             >= 2.1.2    && < 2.3
 
 source-repository head
   type:     git
