diff --git a/avers-api.cabal b/avers-api.cabal
--- a/avers-api.cabal
+++ b/avers-api.cabal
@@ -1,5 +1,5 @@
 name:                avers-api
-version:             0.0.1
+version:             0.0.2
 synopsis:            Types describing the core and extended Avers APIs
 description:         See README
 homepage:            http://github.com/wereHamster/avers-api
diff --git a/src/Avers/API.hs b/src/Avers/API.hs
--- a/src/Avers/API.hs
+++ b/src/Avers/API.hs
@@ -6,6 +6,8 @@
 module Avers.API
     ( AversCoreAPI, AversSessionAPI, AversBlobAPI, AversAccountAPI
 
+    , CacheValidationToken, Cacheable
+
     , module Avers.API.Types
     , module Avers.API.Credentials
     ) where
@@ -27,6 +29,34 @@
 
 
 --------------------------------------------------------------------------------
+-- General structure of endpoint definitions
+--
+-- The definition of an endpoint would be too much to put on a single line,
+-- so it is split into multiple lines according to a fixed schema. Each line
+-- represents a particular aspect of the request/response. Lines can be omitted
+-- if they don't apply to the endpoint.
+--
+--  <path> including any captured components
+--  <credentials>
+--  <cache validation token>
+--  <request body>
+--  <method and response>
+
+
+
+-- | The cache validator token when passed in the request. The server will
+-- use it to determine if the cached response on the client can be reused
+-- or not.
+type CacheValidationToken = Header "If-None-Match" Text
+
+
+-- | Includes @Cache-Control@ and @ETag@ headers in the response to mark
+-- it as cacheable by the client.
+type Cacheable a = Headers '[Header "Cache-Control" Text, Header "ETag" Text] a
+
+
+
+--------------------------------------------------------------------------------
 -- | The Core API to manipulate objects, patches, releases etc.
 
 type AversCoreAPI
@@ -42,7 +72,8 @@
   -- LookupObject
   :<|> "objects" :> Capture "objId" ObjId
     :> Credentials
-    :> Get '[JSON] LookupObjectResponse
+    :> CacheValidationToken
+    :> Get '[JSON] (Cacheable LookupObjectResponse)
 
   ------------------------------------------------------------------------------
   -- PatchObject
@@ -61,7 +92,8 @@
   -- LookupPatch
   :<|> "objects" :> Capture "objId" ObjId :> Capture "revId" RevId
     :> Credentials
-    :> Get '[JSON] LookupPatchResponse
+    :> CacheValidationToken
+    :> Get '[JSON] (Cacheable LookupPatchResponse)
 
   ------------------------------------------------------------------------------
   -- ObjectChanges
@@ -80,13 +112,15 @@
   -- LookupRelease
   :<|> "objects" :> Capture "objId" ObjId :> "releases" :> Capture "revId" RevId
     :> Credentials
-    :> Get '[JSON] LookupReleaseResponse
+    :> CacheValidationToken
+    :> Get '[JSON] (Cacheable LookupReleaseResponse)
 
   ------------------------------------------------------------------------------
   -- LookupLatestRelease
   :<|> "objects" :> Capture "objId" ObjId :> "releases" :> "_latest"
     :> Credentials
-    :> Get '[JSON] LookupLatestReleaseResponse
+    :> CacheValidationToken
+    :> Get '[JSON] (Cacheable LookupLatestReleaseResponse)
 
   ------------------------------------------------------------------------------
   -- ChangeSecret
diff --git a/src/Avers/API/Types.hs b/src/Avers/API/Types.hs
--- a/src/Avers/API/Types.hs
+++ b/src/Avers/API/Types.hs
@@ -1,7 +1,10 @@
+{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Avers.API.Types where
 
+import GHC.Generics
+
 import Data.Text (Text)
 import Data.Aeson as A
 import Data.Time
@@ -16,7 +19,7 @@
 data CreateObjectBody = CreateObjectBody
     { cobType :: !Text
     , cobContent :: !Value
-    }
+    } deriving (Generic)
 
 instance FromJSON CreateObjectBody where
     parseJSON (A.Object o) = CreateObjectBody <$> o .: "type" <*> o .: "content"
@@ -27,7 +30,7 @@
     { corId :: !ObjId
     , corType :: !Text
     , corContent :: !Value
-    }
+    } deriving (Generic)
 
 instance ToJSON CreateObjectResponse where
     toJSON x = object
@@ -48,7 +51,7 @@
     , lorCreatedBy :: !ObjId
     , lorRevisionId :: !RevId
     , lorContent :: !Value
-    }
+    } deriving (Generic)
 
 instance ToJSON LookupObjectResponse where
     toJSON x = object
@@ -72,7 +75,7 @@
 
     , pobOperations :: ![Operation]
       -- ^ The operations which the client wants to store in the database.
-    }
+    } deriving (Generic)
 
 instance FromJSON PatchObjectBody where
     parseJSON (A.Object o) = PatchObjectBody <$> o .: "revisionId" <*> o .: "operations"
@@ -94,7 +97,7 @@
       -- ^ Out of the submitted operations, these are the patches which were
       -- actually applied and stored in the database. This list may be shorter
       -- if some operations were dropped (because redundant or conflicting).
-    }
+    } deriving (Generic)
 
 instance ToJSON PatchObjectResponse where
     toJSON x = object
@@ -111,6 +114,7 @@
 data ObjectChangeNotification
     = PatchNotification !Patch
       -- ^ A new patch was created.
+    deriving (Generic)
 
     -- | LatestReleaseNotification !Release
       -- ^ A new release was created.
@@ -133,7 +137,7 @@
 
 data CreateReleaseBody = CreateReleaseBody
     {
-    }
+    } deriving (Generic)
 
 instance FromJSON CreateReleaseBody where
     parseJSON = undefined
@@ -141,7 +145,7 @@
 
 data CreateReleaseResponse = CreateReleaseResponse
     {
-    }
+    } deriving (Generic)
 
 instance ToJSON CreateReleaseResponse where
     toJSON = undefined
@@ -153,7 +157,7 @@
 
 data LookupReleaseResponse = LookupReleaseResponse
     {
-    }
+    } deriving (Generic)
 
 instance ToJSON LookupReleaseResponse where
     toJSON = undefined
@@ -165,7 +169,7 @@
 
 data LookupLatestReleaseResponse = LookupLatestReleaseResponse
     {
-    }
+    } deriving (Generic)
 
 instance ToJSON LookupLatestReleaseResponse where
     toJSON = undefined
@@ -178,7 +182,7 @@
 data CreateSessionBody = CreateSessionBody
     { csbLogin :: !SecretId
     , csbSecret :: !Text
-    }
+    } deriving (Generic)
 
 instance FromJSON CreateSessionBody where
     parseJSON (A.Object o) = CreateSessionBody <$> o .: "login" <*> o .: "secret"
@@ -188,7 +192,7 @@
 data CreateSessionResponse = CreateSessionResponse
     { csrSessionId :: !SessionId
     , csrSessionObjId :: !ObjId
-    }
+    } deriving (Generic)
 
 instance ToJSON CreateSessionResponse where
     toJSON x = object
@@ -204,7 +208,7 @@
 data LookupSessionResponse = LookupSessionResponse
     { lsrSessionId :: !SessionId
     , lsrSessionObjId :: !ObjId
-    }
+    } deriving (Generic)
 
 instance ToJSON LookupSessionResponse where
     toJSON x = object
@@ -218,7 +222,7 @@
 
 data ChangeSecretBody = ChangeSecretBody
     { csbNewSecret :: !Text
-    }
+    } deriving (Generic)
 
 instance FromJSON ChangeSecretBody where
     parseJSON (A.Object o) = ChangeSecretBody <$> o .: "secret"
@@ -231,7 +235,7 @@
 
 data UploadBlobResponse = UploadBlobResponse
     {
-    }
+    } deriving (Generic)
 
 
 
@@ -240,7 +244,7 @@
 
 data LookupBlobResponse = LookupBlobResponse
     {
-    }
+    } deriving (Generic)
 
 
 
@@ -249,14 +253,14 @@
 
 data SignupBody = SignupBody
     {
-    }
+    } deriving (Generic)
 
 instance FromJSON SignupBody where
     parseJSON = undefined
 
 data SignupResponse = SignupResponse
     {
-    }
+    } deriving (Generic)
 
 instance ToJSON SignupResponse where
     toJSON = undefined
