diff --git a/amazonka-kinesis.cabal b/amazonka-kinesis.cabal
--- a/amazonka-kinesis.cabal
+++ b/amazonka-kinesis.cabal
@@ -1,5 +1,5 @@
 name:                  amazonka-kinesis
-version:               0.0.7
+version:               0.0.8
 synopsis:              Amazon Kinesis SDK.
 homepage:              https://github.com/brendanhay/amazonka
 license:               OtherLicense
@@ -46,12 +46,14 @@
         , Network.AWS.Kinesis.ListTagsForStream
         , Network.AWS.Kinesis.MergeShards
         , Network.AWS.Kinesis.PutRecord
+        , Network.AWS.Kinesis.PutRecords
         , Network.AWS.Kinesis.RemoveTagsFromStream
         , Network.AWS.Kinesis.SplitShard
         , Network.AWS.Kinesis.Types
+        , Network.AWS.Kinesis.Waiters
 
     other-modules:
 
     build-depends:
-          amazonka-core == 0.0.7.*
+          amazonka-core == 0.0.8.*
         , base          >= 4.7     && < 5
diff --git a/gen/Network/AWS/Kinesis.hs b/gen/Network/AWS/Kinesis.hs
--- a/gen/Network/AWS/Kinesis.hs
+++ b/gen/Network/AWS/Kinesis.hs
@@ -25,9 +25,11 @@
     , module Network.AWS.Kinesis.ListTagsForStream
     , module Network.AWS.Kinesis.MergeShards
     , module Network.AWS.Kinesis.PutRecord
+    , module Network.AWS.Kinesis.PutRecords
     , module Network.AWS.Kinesis.RemoveTagsFromStream
     , module Network.AWS.Kinesis.SplitShard
     , module Network.AWS.Kinesis.Types
+    , module Network.AWS.Kinesis.Waiters
     ) where
 
 import Network.AWS.Kinesis.AddTagsToStream
@@ -40,6 +42,8 @@
 import Network.AWS.Kinesis.ListTagsForStream
 import Network.AWS.Kinesis.MergeShards
 import Network.AWS.Kinesis.PutRecord
+import Network.AWS.Kinesis.PutRecords
 import Network.AWS.Kinesis.RemoveTagsFromStream
 import Network.AWS.Kinesis.SplitShard
 import Network.AWS.Kinesis.Types
+import Network.AWS.Kinesis.Waiters
diff --git a/gen/Network/AWS/Kinesis/CreateStream.hs b/gen/Network/AWS/Kinesis/CreateStream.hs
--- a/gen/Network/AWS/Kinesis/CreateStream.hs
+++ b/gen/Network/AWS/Kinesis/CreateStream.hs
@@ -31,10 +31,9 @@
 -- You specify and control the number of shards that a stream is composed of.
 -- Each open shard can support up to 5 read transactions per second, up to a
 -- maximum total of 2 MB of data read per second. Each shard can support up to
--- 1000 write transactions per second, up to a maximum total of 1 MB data
--- written per second. You can add shards to a stream if the amount of data
--- input increases and you can remove shards if the amount of data input
--- decreases.
+-- 1000 records written per second, up to a maximum total of 1 MB data written
+-- per second. You can add shards to a stream if the amount of data input
+-- increases and you can remove shards if the amount of data input decreases.
 --
 -- The stream name identifies the stream. The name is scoped to the AWS account
 -- used by the application. It is also scoped by region. That is, two streams in
diff --git a/gen/Network/AWS/Kinesis/DeleteStream.hs b/gen/Network/AWS/Kinesis/DeleteStream.hs
--- a/gen/Network/AWS/Kinesis/DeleteStream.hs
+++ b/gen/Network/AWS/Kinesis/DeleteStream.hs
@@ -32,8 +32,7 @@
 -- completes the deletion.
 --
 -- Note: Amazon Kinesis might continue to accept data read and write
--- operations, such as 'PutRecord' and 'GetRecords', on a stream in the 'DELETING'
--- state until the stream deletion is complete.
+-- operations, such as 'PutRecord', 'PutRecords', and 'GetRecords', on a stream in the 'DELETING' state until the stream deletion is complete.
 --
 -- When you delete a stream, any shards in that stream are also deleted, and
 -- any tags are dissociated from the stream.
diff --git a/gen/Network/AWS/Kinesis/GetRecords.hs b/gen/Network/AWS/Kinesis/GetRecords.hs
--- a/gen/Network/AWS/Kinesis/GetRecords.hs
+++ b/gen/Network/AWS/Kinesis/GetRecords.hs
@@ -43,10 +43,11 @@
 --
 -- Each data record can be up to 50 KB in size, and each shard can read up to 2
 -- MB per second. You can ensure that your calls don't exceed the maximum
--- supported size or throughput by specifying the maximum number of records that 'GetRecords' can return in the 'Limit' parameter. Consider your average record
--- size when determining this limit. For example, if your average record size is
--- 40 KB, you can limit the data returned to about 1 MB per call by specifying
--- 25 as the limit.
+-- supported size or throughput by using the 'Limit' parameter to specify the
+-- maximum number of records that 'GetRecords' can return. Consider your average
+-- record size when determining this limit. For example, if your average record
+-- size is 40 KB, you can limit the data returned to about 1 MB per call by
+-- specifying 25 as the limit.
 --
 -- The size of the data returned by 'GetRecords' will vary depending on the
 -- utilization of the shard. The maximum size of data that 'GetRecords' can return
@@ -61,8 +62,8 @@
 --
 -- To detect whether the application is falling behind in processing, add a
 -- timestamp to your records and note how long it takes to process them. You can
--- also monitor how much data is in a stream using the CloudWatch metrics for 'PutRecord'. For more information, see <http://docs.aws.amazon.com/kinesis/latest/dev/monitoring_with_cloudwatch.html Monitoring Amazon Kinesis with Amazon CloudWatch>
--- in the /Amazon Kinesis Developer Guide/.
+-- also monitor how much data is in a stream using the CloudWatch metrics for
+-- write operations ('PutRecord' and 'PutRecords'). For more information, see <http://docs.aws.amazon.com/kinesis/latest/dev/monitoring_with_cloudwatch.html Monitoring Amazon Kinesis with Amazon CloudWatch> in the /Amazon Kinesis Developer Guide/.
 --
 -- <http://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html>
 module Network.AWS.Kinesis.GetRecords
diff --git a/gen/Network/AWS/Kinesis/GetShardIterator.hs b/gen/Network/AWS/Kinesis/GetShardIterator.hs
--- a/gen/Network/AWS/Kinesis/GetShardIterator.hs
+++ b/gen/Network/AWS/Kinesis/GetShardIterator.hs
@@ -34,12 +34,12 @@
 -- You must specify the shard iterator type. For example, you can set the 'ShardIteratorType' parameter to read exactly from the position denoted by a specific sequence
 -- number by using the 'AT_SEQUENCE_NUMBER' shard iterator type, or right after
 -- the sequence number by using the 'AFTER_SEQUENCE_NUMBER' shard iterator type,
--- using sequence numbers returned by earlier calls to 'PutRecord', 'GetRecords', or 'DescribeStream'. You can specify the shard iterator type 'TRIM_HORIZON' in the
--- request to cause 'ShardIterator' to point to the last untrimmed record in the
--- shard in the system, which is the oldest data record in the shard. Or you can
--- point to just after the most recent record in the shard, by using the shard
--- iterator type 'LATEST', so that you always read the most recent data in the
--- shard.
+-- using sequence numbers returned by earlier calls to 'PutRecord', 'PutRecords', 'GetRecords', or 'DescribeStream'. You can specify the shard iterator type 'TRIM_HORIZON' in
+-- the request to cause 'ShardIterator' to point to the last untrimmed record in
+-- the shard in the system, which is the oldest data record in the shard. Or you
+-- can point to just after the most recent record in the shard, by using the
+-- shard iterator type 'LATEST', so that you always read the most recent data in
+-- the shard.
 --
 -- When you repeatedly read from an Amazon Kinesis stream use a 'GetShardIterator'
 -- request to get the first shard iterator to to use in your first 'GetRecords'
diff --git a/gen/Network/AWS/Kinesis/PutRecord.hs b/gen/Network/AWS/Kinesis/PutRecord.hs
--- a/gen/Network/AWS/Kinesis/PutRecord.hs
+++ b/gen/Network/AWS/Kinesis/PutRecord.hs
@@ -22,19 +22,23 @@
 --
 -- Derived from AWS service descriptions, licensed under Apache 2.0.
 
--- | Puts a data record from a producer into an Amazon Kinesis stream. You must
--- call 'PutRecord' to send data from the producer into the Amazon Kinesis stream
--- for real-time ingestion and subsequent processing. You must specify the name
--- of the stream that captures, stores, and transports the data; a partition
--- key; and the data blob itself. The data blob could be a segment from a log
--- file, geographic/location data, website clickstream data, or any other data
--- type.
+-- | Puts (writes) a single data record from a producer into an Amazon Kinesis
+-- stream. Call 'PutRecord' to send data from the producer into the Amazon Kinesis
+-- stream for real-time ingestion and subsequent processing, one record at a
+-- time. Each shard can support up to 1000 records written per second, up to a
+-- maximum total of 1 MB data written per second.
 --
--- The partition key is used to distribute data across shards. Amazon Kinesis
--- segregates the data records that belong to a data stream into multiple
--- shards, using the partition key associated with each data record to determine
--- which shard a given data record belongs to.
+-- You must specify the name of the stream that captures, stores, and
+-- transports the data; a partition key; and the data blob itself.
 --
+-- The data blob can be any type of data; for example, a segment from a log
+-- file, geographic/location data, website clickstream data, and so on.
+--
+-- The partition key is used by Amazon Kinesis to distribute data across
+-- shards. Amazon Kinesis segregates the data records that belong to a data
+-- stream into multiple shards, using the partition key associated with each
+-- data record to determine which shard a given data record belongs to.
+--
 -- Partition keys are Unicode strings, with a maximum length limit of 256
 -- bytes. An MD5 hash function is used to map partition keys to 128-bit integer
 -- values and to map associated data records to shards using the hash key ranges
@@ -117,9 +121,9 @@
     , _prSequenceNumberForOrdering = Nothing
     }
 
--- | The data blob to put into the record, which is Base64-encoded when the blob
+-- | The data blob to put into the record, which is base64-encoded when the blob
 -- is serialized. The maximum size of the data blob (the payload before
--- Base64-encoding) is 50 kilobytes (KB)
+-- base64-encoding) is 50 kilobytes (KB)
 prData :: Lens' PutRecord Base64
 prData = lens _prData (\s a -> s { _prData = a })
 
diff --git a/gen/Network/AWS/Kinesis/PutRecords.hs b/gen/Network/AWS/Kinesis/PutRecords.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/Kinesis/PutRecords.hs
@@ -0,0 +1,184 @@
+{-# LANGUAGE DataKinds                   #-}
+{-# LANGUAGE DeriveGeneric               #-}
+{-# LANGUAGE FlexibleInstances           #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
+{-# LANGUAGE LambdaCase                  #-}
+{-# LANGUAGE NoImplicitPrelude           #-}
+{-# LANGUAGE OverloadedStrings           #-}
+{-# LANGUAGE RecordWildCards             #-}
+{-# LANGUAGE TypeFamilies                #-}
+
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+-- Module      : Network.AWS.Kinesis.PutRecords
+-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
+-- License     : This Source Code Form is subject to the terms of
+--               the Mozilla Public License, v. 2.0.
+--               A copy of the MPL can be found in the LICENSE file or
+--               you can obtain it at http://mozilla.org/MPL/2.0/.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+--
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+-- | Puts (writes) multiple data records from a producer into an Amazon Kinesis
+-- stream in a single call (also referred to as a 'PutRecords' request). Use this
+-- operation to send data from a data producer into the Amazon Kinesis stream
+-- for real-time ingestion and processing. Each shard can support up to 1000
+-- records written per second, up to a maximum total of 1 MB data written per
+-- second.
+--
+-- You must specify the name of the stream that captures, stores, and
+-- transports the data; and an array of request 'Records', with each record in the
+-- array requiring a partition key and data blob.
+--
+-- The data blob can be any type of data; for example, a segment from a log
+-- file, geographic/location data, website clickstream data, and so on.
+--
+-- The partition key is used by Amazon Kinesis as input to a hash function that
+-- maps the partition key and associated data to a specific shard. An MD5 hash
+-- function is used to map partition keys to 128-bit integer values and to map
+-- associated data records to shards. As a result of this hashing mechanism, all
+-- data records with the same partition key map to the same shard within the
+-- stream. For more information, see <http://docs.aws.amazon.com/kinesis/latest/dev/kinesis-using-api-java.html#kinesis-using-api-defn-partition-key Partition Key> in the /Amazon KinesisDeveloper Guide/.
+--
+-- Each record in the 'Records' array may include an optional parameter, 'ExplicitHashKey', which overrides the partition key to shard mapping. This parameter allows a
+-- data producer to determine explicitly the shard where the record is stored.
+-- For more information, see <http://docs.aws.amazon.com/kinesis/latest/dev/kinesis-using-api-java.html#kinesis-using-api-putrecords Adding Multiple Records with PutRecords> in the /Amazon Kinesis Developer Guide/.
+--
+-- The 'PutRecords' response includes an array of response 'Records'. Each record
+-- in the response array directly correlates with a record in the request array
+-- using natural ordering, from the top to the bottom of the request and
+-- response. The response 'Records' array always includes the same number of
+-- records as the request array.
+--
+-- The response 'Records' array includes both successfully and unsuccessfully
+-- processed records. Amazon Kinesis attempts to process all records in each 'PutRecords' request. A single record failure does not stop the processing of subsequent
+-- records.
+--
+-- A successfully-processed record includes 'ShardId' and 'SequenceNumber' values.
+-- The 'ShardId' parameter identifies the shard in the stream where the record is
+-- stored. The 'SequenceNumber' parameter is an identifier assigned to the put
+-- record, unique to all records in the stream.
+--
+-- An unsuccessfully-processed record includes 'ErrorCode' and 'ErrorMessage'
+-- values. 'ErrorCode' reflects the type of error and can be one of the following
+-- values: 'ProvisionedThroughputExceededException' or 'InternalFailure'. 'ErrorMessage' provides more detailed information about the 'ProvisionedThroughputExceededException' exception including the account ID, stream name, and shard ID of the record
+-- that was throttled.
+--
+-- Data records are accessible for only 24 hours from the time that they are
+-- added to an Amazon Kinesis stream.
+--
+-- <http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html>
+module Network.AWS.Kinesis.PutRecords
+    (
+    -- * Request
+      PutRecords
+    -- ** Request constructor
+    , putRecords
+    -- ** Request lenses
+    , pr1Records
+    , pr1StreamName
+
+    -- * Response
+    , PutRecordsResponse
+    -- ** Response constructor
+    , putRecordsResponse
+    -- ** Response lenses
+    , prrFailedRecordCount
+    , prrRecords
+    ) where
+
+import Network.AWS.Prelude
+import Network.AWS.Request.JSON
+import Network.AWS.Kinesis.Types
+import qualified GHC.Exts
+
+data PutRecords = PutRecords
+    { _pr1Records    :: List1 "Records" PutRecordsRequestEntry
+    , _pr1StreamName :: Text
+    } deriving (Eq, Show)
+
+-- | 'PutRecords' constructor.
+--
+-- The fields accessible through corresponding lenses are:
+--
+-- * 'pr1Records' @::@ 'NonEmpty' 'PutRecordsRequestEntry'
+--
+-- * 'pr1StreamName' @::@ 'Text'
+--
+putRecords :: NonEmpty PutRecordsRequestEntry -- ^ 'pr1Records'
+           -> Text -- ^ 'pr1StreamName'
+           -> PutRecords
+putRecords p1 p2 = PutRecords
+    { _pr1Records    = withIso _List1 (const id) p1
+    , _pr1StreamName = p2
+    }
+
+-- | The records associated with the request.
+pr1Records :: Lens' PutRecords (NonEmpty PutRecordsRequestEntry)
+pr1Records = lens _pr1Records (\s a -> s { _pr1Records = a }) . _List1
+
+-- | The stream name associated with the request.
+pr1StreamName :: Lens' PutRecords Text
+pr1StreamName = lens _pr1StreamName (\s a -> s { _pr1StreamName = a })
+
+data PutRecordsResponse = PutRecordsResponse
+    { _prrFailedRecordCount :: Maybe Nat
+    , _prrRecords           :: List1 "Records" PutRecordsResultEntry
+    } deriving (Eq, Show)
+
+-- | 'PutRecordsResponse' constructor.
+--
+-- The fields accessible through corresponding lenses are:
+--
+-- * 'prrFailedRecordCount' @::@ 'Maybe' 'Natural'
+--
+-- * 'prrRecords' @::@ 'NonEmpty' 'PutRecordsResultEntry'
+--
+putRecordsResponse :: NonEmpty PutRecordsResultEntry -- ^ 'prrRecords'
+                   -> PutRecordsResponse
+putRecordsResponse p1 = PutRecordsResponse
+    { _prrRecords           = withIso _List1 (const id) p1
+    , _prrFailedRecordCount = Nothing
+    }
+
+-- | The number of unsuccessfully processed records in a 'PutRecords' request.
+prrFailedRecordCount :: Lens' PutRecordsResponse (Maybe Natural)
+prrFailedRecordCount =
+    lens _prrFailedRecordCount (\s a -> s { _prrFailedRecordCount = a })
+        . mapping _Nat
+
+-- | An array of successfully and unsuccessfully processed record results,
+-- correlated with the request by natural ordering. A record that is
+-- successfully added to your Amazon Kinesis stream includes 'SequenceNumber' and 'ShardId' in the result. A record that fails to be added to your Amazon Kinesis stream
+-- includes 'ErrorCode' and 'ErrorMessage' in the result.
+prrRecords :: Lens' PutRecordsResponse (NonEmpty PutRecordsResultEntry)
+prrRecords = lens _prrRecords (\s a -> s { _prrRecords = a }) . _List1
+
+instance ToPath PutRecords where
+    toPath = const "/"
+
+instance ToQuery PutRecords where
+    toQuery = const mempty
+
+instance ToHeaders PutRecords
+
+instance ToJSON PutRecords where
+    toJSON PutRecords{..} = object
+        [ "Records"    .= _pr1Records
+        , "StreamName" .= _pr1StreamName
+        ]
+
+instance AWSRequest PutRecords where
+    type Sv PutRecords = Kinesis
+    type Rs PutRecords = PutRecordsResponse
+
+    request  = post "PutRecords"
+    response = jsonResponse
+
+instance FromJSON PutRecordsResponse where
+    parseJSON = withObject "PutRecordsResponse" $ \o -> PutRecordsResponse
+        <$> o .:? "FailedRecordCount"
+        <*> o .:  "Records"
diff --git a/gen/Network/AWS/Kinesis/Types.hs b/gen/Network/AWS/Kinesis/Types.hs
--- a/gen/Network/AWS/Kinesis/Types.hs
+++ b/gen/Network/AWS/Kinesis/Types.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE OverloadedStrings           #-}
 {-# LANGUAGE RecordWildCards             #-}
 {-# LANGUAGE TypeFamilies                #-}
+{-# LANGUAGE ViewPatterns                #-}
 
 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
 
@@ -53,6 +54,21 @@
     , sdStreamName
     , sdStreamStatus
 
+    -- * PutRecordsResultEntry
+    , PutRecordsResultEntry
+    , putRecordsResultEntry
+    , prreErrorCode
+    , prreErrorMessage
+    , prreSequenceNumber
+    , prreShardId
+
+    -- * PutRecordsRequestEntry
+    , PutRecordsRequestEntry
+    , putRecordsRequestEntry
+    , prreData
+    , prreExplicitHashKey
+    , prrePartitionKey
+
     -- * StreamStatus
     , StreamStatus (..)
 
@@ -79,8 +95,6 @@
     , ShardIteratorType (..)
     ) where
 
-import Data.Char (isUpper)
-import Network.AWS.Error
 import Network.AWS.Prelude
 import Network.AWS.Signing
 import qualified GHC.Exts
@@ -92,16 +106,40 @@
     type Sg Kinesis = V4
     type Er Kinesis = JSONError
 
-    service = Service
-        { _svcAbbrev       = "Kinesis"
-        , _svcPrefix       = "kinesis"
-        , _svcVersion      = "2013-12-02"
-        , _svcTargetPrefix = Just "Kinesis_20131202"
-        , _svcJSONVersion  = Just "1.1"
-        }
+    service = service'
+      where
+        service' :: Service Kinesis
+        service' = Service
+            { _svcAbbrev       = "Kinesis"
+            , _svcPrefix       = "kinesis"
+            , _svcVersion      = "2013-12-02"
+            , _svcTargetPrefix = Just "Kinesis_20131202"
+            , _svcJSONVersion  = Just "1.1"
+            , _svcHandle       = handle
+            , _svcRetry        = retry
+            }
 
-    handle = jsonError statusSuccess
+        handle :: Status
+               -> Maybe (LazyByteString -> ServiceError JSONError)
+        handle = jsonError statusSuccess service'
 
+        retry :: Retry Kinesis
+        retry = Exponential
+            { _retryBase     = 0.05
+            , _retryGrowth   = 2
+            , _retryAttempts = 5
+            , _retryCheck    = check
+            }
+
+        check :: Status
+              -> JSONError
+              -> Bool
+        check (statusCode -> s) (awsErrorCode -> e)
+            | s == 500  = True -- General Server Error
+            | s == 509  = True -- Limit Exceeded
+            | s == 503  = True -- Service Unavailable
+            | otherwise = False
+
 data Shard = Shard
     { _sAdjacentParentShardId :: Maybe Text
     , _sHashKeyRange          :: HashKeyRange
@@ -301,6 +339,127 @@
         , "HasMoreShards" .= _sdHasMoreShards
         ]
 
+data PutRecordsResultEntry = PutRecordsResultEntry
+    { _prreErrorCode      :: Maybe Text
+    , _prreErrorMessage   :: Maybe Text
+    , _prreSequenceNumber :: Maybe Text
+    , _prreShardId        :: Maybe Text
+    } deriving (Eq, Ord, Show)
+
+-- | 'PutRecordsResultEntry' constructor.
+--
+-- The fields accessible through corresponding lenses are:
+--
+-- * 'prreErrorCode' @::@ 'Maybe' 'Text'
+--
+-- * 'prreErrorMessage' @::@ 'Maybe' 'Text'
+--
+-- * 'prreSequenceNumber' @::@ 'Maybe' 'Text'
+--
+-- * 'prreShardId' @::@ 'Maybe' 'Text'
+--
+putRecordsResultEntry :: PutRecordsResultEntry
+putRecordsResultEntry = PutRecordsResultEntry
+    { _prreSequenceNumber = Nothing
+    , _prreShardId        = Nothing
+    , _prreErrorCode      = Nothing
+    , _prreErrorMessage   = Nothing
+    }
+
+-- | The error code for an individual record result. 'ErrorCodes' can be either 'ProvisionedThroughputExceededException' or 'InternalFailure'.
+prreErrorCode :: Lens' PutRecordsResultEntry (Maybe Text)
+prreErrorCode = lens _prreErrorCode (\s a -> s { _prreErrorCode = a })
+
+-- | The error message for an individual record result. An 'ErrorCode' value of 'ProvisionedThroughputExceededException' has an error message that includes the account ID, stream name, and shard
+-- ID. An 'ErrorCode' value of 'InternalFailure' has the error message '"InternalService Failure"'.
+prreErrorMessage :: Lens' PutRecordsResultEntry (Maybe Text)
+prreErrorMessage = lens _prreErrorMessage (\s a -> s { _prreErrorMessage = a })
+
+-- | The sequence number for an individual record result.
+prreSequenceNumber :: Lens' PutRecordsResultEntry (Maybe Text)
+prreSequenceNumber =
+    lens _prreSequenceNumber (\s a -> s { _prreSequenceNumber = a })
+
+-- | The shard ID for an individual record result.
+prreShardId :: Lens' PutRecordsResultEntry (Maybe Text)
+prreShardId = lens _prreShardId (\s a -> s { _prreShardId = a })
+
+instance FromJSON PutRecordsResultEntry where
+    parseJSON = withObject "PutRecordsResultEntry" $ \o -> PutRecordsResultEntry
+        <$> o .:? "ErrorCode"
+        <*> o .:? "ErrorMessage"
+        <*> o .:? "SequenceNumber"
+        <*> o .:? "ShardId"
+
+instance ToJSON PutRecordsResultEntry where
+    toJSON PutRecordsResultEntry{..} = object
+        [ "SequenceNumber" .= _prreSequenceNumber
+        , "ShardId"        .= _prreShardId
+        , "ErrorCode"      .= _prreErrorCode
+        , "ErrorMessage"   .= _prreErrorMessage
+        ]
+
+data PutRecordsRequestEntry = PutRecordsRequestEntry
+    { _prreData            :: Base64
+    , _prreExplicitHashKey :: Maybe Text
+    , _prrePartitionKey    :: Text
+    } deriving (Eq, Show)
+
+-- | 'PutRecordsRequestEntry' constructor.
+--
+-- The fields accessible through corresponding lenses are:
+--
+-- * 'prreData' @::@ 'Base64'
+--
+-- * 'prreExplicitHashKey' @::@ 'Maybe' 'Text'
+--
+-- * 'prrePartitionKey' @::@ 'Text'
+--
+putRecordsRequestEntry :: Base64 -- ^ 'prreData'
+                       -> Text -- ^ 'prrePartitionKey'
+                       -> PutRecordsRequestEntry
+putRecordsRequestEntry p1 p2 = PutRecordsRequestEntry
+    { _prreData            = p1
+    , _prrePartitionKey    = p2
+    , _prreExplicitHashKey = Nothing
+    }
+
+-- | The data blob to put into the record, which is base64-encoded when the blob
+-- is serialized. The maximum size of the data blob (the payload before
+-- base64-encoding) is 50 kilobytes (KB)
+prreData :: Lens' PutRecordsRequestEntry Base64
+prreData = lens _prreData (\s a -> s { _prreData = a })
+
+-- | The hash value used to determine explicitly the shard that the data record is
+-- assigned to by overriding the partition key hash.
+prreExplicitHashKey :: Lens' PutRecordsRequestEntry (Maybe Text)
+prreExplicitHashKey =
+    lens _prreExplicitHashKey (\s a -> s { _prreExplicitHashKey = a })
+
+-- | Determines which shard in the stream the data record is assigned to.
+-- Partition keys are Unicode strings with a maximum length limit of 256 bytes.
+-- Amazon Kinesis uses the partition key as input to a hash function that maps
+-- the partition key and associated data to a specific shard. Specifically, an
+-- MD5 hash function is used to map partition keys to 128-bit integer values and
+-- to map associated data records to shards. As a result of this hashing
+-- mechanism, all data records with the same partition key map to the same shard
+-- within the stream.
+prrePartitionKey :: Lens' PutRecordsRequestEntry Text
+prrePartitionKey = lens _prrePartitionKey (\s a -> s { _prrePartitionKey = a })
+
+instance FromJSON PutRecordsRequestEntry where
+    parseJSON = withObject "PutRecordsRequestEntry" $ \o -> PutRecordsRequestEntry
+        <$> o .:  "Data"
+        <*> o .:? "ExplicitHashKey"
+        <*> o .:  "PartitionKey"
+
+instance ToJSON PutRecordsRequestEntry where
+    toJSON PutRecordsRequestEntry{..} = object
+        [ "Data"            .= _prreData
+        , "ExplicitHashKey" .= _prreExplicitHashKey
+        , "PartitionKey"    .= _prrePartitionKey
+        ]
+
 data StreamStatus
     = Active   -- ^ ACTIVE
     | Creating -- ^ CREATING
@@ -406,7 +565,7 @@
 -- | The data blob. The data in the blob is both opaque and immutable to the
 -- Amazon Kinesis service, which does not inspect, interpret, or change the data
 -- in the blob in any way. The maximum size of the data blob (the payload before
--- Base64-encoding) is 50 kilobytes (KB)
+-- base64-encoding) is 50 kilobytes (KB)
 rData :: Lens' Record Base64
 rData = lens _rData (\s a -> s { _rData = a })
 
diff --git a/gen/Network/AWS/Kinesis/Waiters.hs b/gen/Network/AWS/Kinesis/Waiters.hs
new file mode 100644
--- /dev/null
+++ b/gen/Network/AWS/Kinesis/Waiters.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies      #-}
+
+-- Module      : Network.AWS.Kinesis.Waiters
+-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
+-- License     : This Source Code Form is subject to the terms of
+--               the Mozilla Public License, v. 2.0.
+--               A copy of the MPL can be found in the LICENSE file or
+--               you can obtain it at http://mozilla.org/MPL/2.0/.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+--
+-- Derived from AWS service descriptions, licensed under Apache 2.0.
+
+module Network.AWS.Kinesis.Waiters where
+
+import Network.AWS.Kinesis.DescribeStream
+import Network.AWS.Kinesis.Types
+import Network.AWS.Waiters
+
+streamExists :: Wait DescribeStream
+streamExists = Wait
+    { _waitName      = "StreamExists"
+    , _waitAttempts  = 18
+    , _waitDelay     = 10
+    , _waitAcceptors =
+        [ matchAll Active AcceptSuccess
+            (dsrStreamDescription . sdStreamStatus)
+        ]
+    }
