diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -10,10 +10,10 @@
 
 > If you’ve ever argued with your team about the way your JSON responses should
 > be formatted, JSON API can be your anti-bikeshedding tool.
-> 
+>
 > By following shared conventions, you can increase productivity, take advantage
 > of generalized tooling, and focus on what matters: your application.
-> 
+>
 > Clients built around JSON API are able to take advantage of its features around
 > efficiently caching responses, sometimes eliminating network requests entirely.
 
@@ -111,13 +111,86 @@
 for more robust representations of resourceful payloads. Here, you'll start to
 see the more comprehensive benefits of a discoverable API.
 
+##### Pagination Example
 
+Let's use the same example User record:
 
-#### Example Project
+```Haskell
+data User = User
+  { userId        :: Int
+  , userFirstName :: String
+  , userLastName  :: String
+  } deriving (Eq, Show)
 
-There is an [example project](https://github.com/toddmohney/json-api/tree/master/example) illustrating how the library can be used in the context of a web server.
+$(deriveJSON defaultOptions ''User)
+```
 
+Suppose we now have a list of 2 users;
 
+```Haskell
+let usrs =
+  [ User 1 "Isaac" "Newton"
+  , User 2 "Albert" "Einstein"
+  ]
+```
+
+From this, we can use the `json-api` package to produce a payload for a collection with pagination links conformant
+to the [JSON-API pagination specification](https://jsonapi.org/format/#fetching-pagination) like so:
+
+```Haskell
+let paginate = Pagination (PageIndex 1) (PageSize 1) (ResourceCount $ toEnum (length usrs))
+let resourceLink = (fromJust . importURL) "/users"
+let paginationLinks = mkPaginationLinks PageStrategy resourceLink paginate
+let doc = mkDocument [head usrs] (Just paginationLinks) Nothing
+```
+
+When delivered as a response from a web server, for example, we get a payload
+that looks like this:
+
+```JSON
+{
+  "data": [
+    {
+      "attributes": {
+        "userFirstName": "Isaac",
+        "userLastName": "Newton",
+        "userId": 1
+      },
+      "relationships": null,
+      "id": "1",
+      "meta": null,
+      "type": "users",
+      "links": null
+    }
+  ],
+  "meta": null,
+  "included": [
+  ],
+  "links": {
+    "next": "/users?page%5bsize%5d=1&page%5bnumber%5d=2",
+    "first": "/users?page%5bsize%5d=1&page%5bnumber%5d=1",
+    "last": "/users?page%5bsize%5d=1&page%5bnumber%5d=2"
+  }
+}
+```
+
+The key function in the code example is `mkPaginationLinks` which has the following signature;
+
+```Haskell
+mkPaginationLinks :: Strategy -> URL -> Pagination -> Links
+```
+
+`Strategy` is a sum type that represents the different paging strategies as laid out in the [JSON-API pagination specification](https://jsonapi.org/format/#fetching-pagination). At the time of writing this README, the library only supports 2 paging strategies Offset and Page. Offset is a 0 index based approach unlike Page, i.e. `page[offset]` 0 is the same as `page[number]` 1.
+
+The `URL` type is used to build the links that appear in the JSON payload. The `Pagination` type contains the requisite information for the `mkPaginationLinks` function to generate the paging links.
+
+So let's break this example down. To get started we need to create a `Pagination` record. The first attribute of the record is `PageIndex`. This attribute informs the caller that the page we are looking at is the first in the entire collection (`PageIndex` is either a 0 based index or 1 based index depending on the `Strategy`). So in our example as we are using `PageStrategy`, `PageIndex 1` implies we are after the first page. The second attribute of the record is `PageSize`. This atrribute tells the caller how many items can appear in the list at most. So in our example seeing there are only 2 users, a `PageSize` of 1 would mean that in total we have 2 pages. The third attribute is `ResourceCount`. This attribute is required by the function `mkPaginationLinks` to figure out which links to generate.
+
+The links object in the JSON payload can have 4 attributes `next`, `prev`, `first` and `last`. This library only generates valid links. For example if the request is for the first page of a list, then the `prev` link is not present.
+
+#### Example Project
+
+There is an [example project](https://github.com/toddmohney/json-api/tree/master/example) illustrating how the library can be used in the context of a web server.
 
 #### Hackage
 
diff --git a/json-api.cabal b/json-api.cabal
--- a/json-api.cabal
+++ b/json-api.cabal
@@ -1,16 +1,15 @@
 name:                json-api
-version:             0.1.1.2
+version:             0.1.2.0
 homepage:            https://github.com/toddmohney/json-api
 bug-reports:         https://github.com/toddmohney/json-api/issues
 license:             MIT
 license-file:        LICENSE
 author:              Todd Mohney
-maintainer:          toddmohney@gmail.com
+maintainer:          Todd Mohney <toddmohney@gmail.com>
 copyright:           2016 Todd Mohney
 category:            Network
 build-type:          Simple
 cabal-version:       >=1.10
-maintainer:          Todd Mohney <toddmohney@gmail.com>
 stability:           experimental
 tested-with:         GHC == 7.10.3
 synopsis:            Utilities for generating JSON-API payloads
@@ -61,6 +60,7 @@
     Network.JSONApi.Meta
     Network.JSONApi.Link
     Network.JSONApi.Resource
+    Network.JSONApi.Pagination
 
   other-modules:
 
@@ -109,6 +109,7 @@
     Network.JSONApi.DocumentSpec
     Network.JSONApi.IdentifierSpec
     Network.JSONApi.MetaSpec
+    Network.JSONApi.PaginationSpec
     Network.JSONApi.ResourceSpec
     TestHelpers
 
diff --git a/src/Network/JSONApi.hs b/src/Network/JSONApi.hs
--- a/src/Network/JSONApi.hs
+++ b/src/Network/JSONApi.hs
@@ -13,10 +13,16 @@
 , R.ResourcefulEntity (..)
 , I.HasIdentifier (..)
 , I.Identifier (..)
-, L.Links
+, L.Links (..)
 , M.Meta
 , M.MetaObject (..)
 , L.mkLinks
+, P.Pagination (..)
+, P.PageIndex (..)
+, P.PageSize (..)
+, P.ResourceCount (..)
+, P.Strategy (..)
+, P.mkPaginationLinks
 , R.mkRelationship
 , R.mkRelationships
 , D.mkDocument
@@ -34,5 +40,6 @@
 import qualified Network.JSONApi.Identifier as I
 import qualified Network.JSONApi.Link as L
 import qualified Network.JSONApi.Meta as M
+import qualified Network.JSONApi.Pagination as P
 import qualified Network.JSONApi.Resource as R
 
diff --git a/src/Network/JSONApi/Link.hs b/src/Network/JSONApi/Link.hs
--- a/src/Network/JSONApi/Link.hs
+++ b/src/Network/JSONApi/Link.hs
@@ -4,7 +4,7 @@
 Specification: <http://jsonapi.org/format/#document-links>
 -}
 module Network.JSONApi.Link
-( Links
+( Links (..)
 , Rel
 , Href
 , mkLinks
diff --git a/src/Network/JSONApi/Pagination.hs b/src/Network/JSONApi/Pagination.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/JSONApi/Pagination.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Network.JSONApi.Pagination (
+    Pagination (..)
+  , PageIndex (..)
+  , PageSize (..)
+  , ResourceCount (..)
+  , Strategy (..)
+  , mkPaginationLinks
+) where
+
+import Network.JSONApi.Link (Links, Rel, mkLinks)
+import Network.URL (URL, add_param)
+
+{- |
+Wrapper type for the various components of pagination being page size, page index
+and the number of resources in total.
+-}
+data Pagination = Pagination {
+                      getPaginationPageIndex :: PageIndex
+                    , getPaginationPageSize :: PageSize
+                    , getPaginationResourceCount :: ResourceCount
+                  }
+
+{- |
+We can specify limits on the number of rows we would like back from the database
+-}
+newtype PageSize = PageSize {
+  getPageSize :: Word
+} deriving Show
+
+newtype PageIndex = PageIndex {
+  getPageIndex :: Word
+} deriving Show
+
+newtype ResourceCount = ResourceCount {
+  getResourceCount :: Word
+} deriving Show
+
+{- |
+Pagination strategies are commonly implemented by the server of which Page and Offset
+are commonly used.
+-}
+data Strategy = PageStrategy | OffsetStrategy
+
+{- |
+Helper function to build relative links for a collection of resources of type ResourceEntity.
+
+This helper function assumes that the first page is always page 0.
+-}
+mkPaginationLinks :: Strategy -> URL -> Pagination -> Links
+mkPaginationLinks strategy baseUrl page =
+  mkLinks (baseLinks ++ nextLinks ++ prevLinks)
+    where
+      pgIndex    = getPageIndex $ getPaginationPageIndex page
+      pgSize     = getPageSize $ getPaginationPageSize page
+      baseLinks  = [mkPaginationLink strategy "first" baseUrl (firstPageIndex strategy) pgSize
+                  , mkPaginationLink strategy "last" baseUrl (lastPageIndex strategy page) pgSize]
+      nextLinks  = [mkPaginationLink strategy "next" baseUrl (pgIndex + 1) pgSize | shouldGenNextLink strategy page]
+      prevLinks  = [mkPaginationLink strategy "prev" baseUrl (pgIndex - 1) pgSize | shouldGenPrevLink strategy page]
+
+{- |
+If we are at the last page then we do not generate a next link. This function tells us whether to
+generate a next link based on the page strategy.
+-}
+shouldGenNextLink :: Strategy -> Pagination -> Bool
+shouldGenNextLink PageStrategy pagination =
+  (getPageIndex . getPaginationPageIndex) pagination < numberOfPagesInPageList pagination
+shouldGenNextLink OffsetStrategy pagination =
+  (getPageIndex . getPaginationPageIndex) pagination < numberOfPagesInPageList pagination - 1
+
+{- |
+If we on the first page then we do not generate a prev link. This function tells us whether we can generate
+a prev link.
+-}
+shouldGenPrevLink :: Strategy -> Pagination -> Bool
+shouldGenPrevLink strategy pagination =
+  (getPageIndex . getPaginationPageIndex) pagination > firstPageIndex strategy
+
+{- |
+This function calculates the number of pages in the list.
+-}
+numberOfPagesInPageList :: Pagination -> Word
+numberOfPagesInPageList (Pagination _ pageSize resourceCount) =
+  if resCount `mod` pgSize == 0
+  then resCount `quot` pgSize
+  else (resCount `quot` pgSize) + 1
+    where
+      pgSize     = getPageSize pageSize
+      resCount   = getResourceCount resourceCount
+
+{- |
+Helper function used to generate a single pagination link.
+-}
+mkPaginationLink :: Strategy -> Rel -> URL -> Word -> Word -> (Rel, URL)
+mkPaginationLink strategy key baseUrl pageNo pageSize =
+  (key, link)
+    where
+      pageNoUrl = add_param baseUrl (strategyToQueryStringNumberKey strategy, show pageNo)
+      link      = add_param pageNoUrl (strategyToQueryStringSizeKey strategy, show pageSize)
+
+{- |
+In the page strategy page numbering starts at 1, where as in the case of offset the numbering
+starts at 0.
+-}
+firstPageIndex :: Strategy -> Word
+firstPageIndex PageStrategy = 1
+firstPageIndex OffsetStrategy = 0
+
+lastPageIndex :: Strategy -> Pagination -> Word
+lastPageIndex PageStrategy page = numberOfPagesInPageList page
+lastPageIndex OffsetStrategy page = numberOfPagesInPageList page - 1
+
+{- |
+Simple pattern matcher than translates a Strategy to a query string element name.
+-}
+strategyToQueryStringNumberKey :: Strategy -> String
+strategyToQueryStringNumberKey PageStrategy = "page[number]"
+strategyToQueryStringNumberKey OffsetStrategy = "page[offset]"
+
+strategyToQueryStringSizeKey :: Strategy -> String
+strategyToQueryStringSizeKey PageStrategy = "page[size]"
+strategyToQueryStringSizeKey OffsetStrategy = "page[limit]"
diff --git a/test/Network/JSONApi/PaginationSpec.hs b/test/Network/JSONApi/PaginationSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/JSONApi/PaginationSpec.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Network.JSONApi.PaginationSpec where
+
+import Data.Map (toList)
+import Data.Maybe (fromJust)
+import Network.JSONApi
+import Network.URL (importURL)
+import Test.Hspec
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec =
+  describe "Pagination" $ do
+    it "should return mandatory keys" $ do
+      let p = Pagination (PageIndex 2) (PageSize 10) (ResourceCount 30)
+      let results = mkPaginationLinks PageStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          map fst links `shouldBe` ["first", "last", "next", "prev"]
+
+    it "should return proper hrefs for paging strategy" $ do
+      let p = Pagination (PageIndex 2) (PageSize 10) (ResourceCount 30)
+      let results = mkPaginationLinks PageStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          links `shouldBe` [("first", "/users?page%5bsize%5d=10&page%5bnumber%5d=1"),
+                            ("last", "/users?page%5bsize%5d=10&page%5bnumber%5d=3"),
+                            ("next", "/users?page%5bsize%5d=10&page%5bnumber%5d=3"),
+                            ("prev", "/users?page%5bsize%5d=10&page%5bnumber%5d=1")]
+
+    it "should return proper hrefs for offset strategy" $ do
+      let p = Pagination (PageIndex 1) (PageSize 10) (ResourceCount 30)
+      let results = mkPaginationLinks OffsetStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          links `shouldBe` [("first", "/users?page%5blimit%5d=10&page%5boffset%5d=0"),
+                            ("last", "/users?page%5blimit%5d=10&page%5boffset%5d=2"),
+                            ("next", "/users?page%5blimit%5d=10&page%5boffset%5d=2"),
+                            ("prev", "/users?page%5blimit%5d=10&page%5boffset%5d=0")]
+
+    it "should support the page strategy" $ do
+      let p = Pagination (PageIndex 0) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks PageStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          (snd . head) links `shouldBe` "/users?page%5bsize%5d=10&page%5bnumber%5d=1"
+
+    it "should support the offset strategy" $ do
+      let p = Pagination (PageIndex 0) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks OffsetStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          (snd . head) links `shouldBe` "/users?page%5blimit%5d=10&page%5boffset%5d=0"
+
+    it "should omit prev when we are on the first page of a PageStrategy" $ do
+      let p = Pagination (PageIndex 1) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks PageStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          map fst links `shouldBe` ["first", "last", "next"]
+
+    it "should omit next when we are on the last page of a PageStrategy" $ do
+      let p = Pagination (PageIndex 2) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks PageStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          map fst links `shouldBe` ["first", "last", "prev"]
+
+    it "should omit prev when we are on the first page of a OffsetStrategy" $ do
+      let p = Pagination (PageIndex 0) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks OffsetStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          map fst links `shouldBe` ["first", "last", "next"]
+
+    it "should omit next when we are on the last page of a OffsetStrategy" $ do
+      let p = Pagination (PageIndex 1) (PageSize 10) (ResourceCount 20)
+      let results = mkPaginationLinks OffsetStrategy (fromJust $ importURL "/users") p
+      case results of
+        Links lm -> do
+          let links = toList lm
+          map fst links `shouldBe` ["first", "last", "prev"]
diff --git a/test/Network/JSONApi/ResourceSpec.hs b/test/Network/JSONApi/ResourceSpec.hs
--- a/test/Network/JSONApi/ResourceSpec.hs
+++ b/test/Network/JSONApi/ResourceSpec.hs
@@ -41,14 +41,14 @@
   resourceMetaData _ = Just myResourceMetaData
   resourceRelationships _ = Just myRelationshipss
 
-data Pagination = Pagination
+data PaginationMetaObject = PaginationMetaObject
   { currentPage :: Int
   , totalPages :: Int
   } deriving (Show, Generic)
 
-instance AE.ToJSON Pagination
-instance AE.FromJSON Pagination
-instance MetaObject Pagination where
+instance AE.ToJSON PaginationMetaObject
+instance AE.FromJSON PaginationMetaObject
+instance MetaObject PaginationMetaObject where
   typeName _ = "pagination"
 
 myRelationshipss :: Relationships
@@ -74,7 +74,7 @@
           ]
 
 myResourceMetaData :: Meta
-myResourceMetaData = mkMeta (Pagination 1 14)
+myResourceMetaData = mkMeta (PaginationMetaObject 1 14)
 
 toURL :: String -> URL
 toURL = fromJust . importURL
