diff --git a/docs/reference.txt b/docs/reference.txt
index b0606bd8db7b5a56704b6ca54af5b7b0e326ea76..e75363afa5e46efa496a2b2d787103c13cd02e78 100644
--- a/docs/reference.txt
+++ b/docs/reference.txt
@@ -13,5 +13,6 @@ Reference
    /reference/class/MongoDBCollection
    /reference/class/MongoDBGridFSBucket
    /reference/write-result-classes
+   /reference/result-classes
    /reference/enumeration-classes
    /reference/exception-classes
diff --git a/docs/reference/method/MongoDBChangeStream-current.txt b/docs/reference/method/MongoDBChangeStream-current.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1666fcd8602aa5b086698bdd51ef8d32438dd1c2
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-current.txt
@@ -0,0 +1,104 @@
+================================
+MongoDB\\ChangeStream::current()
+================================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::current()
+
+   Returns the current event in the change stream.
+
+   .. code-block:: php
+
+      function current(): array|object|null
+
+   The structure of each event document will vary based on the operation type.
+   See :manual:`Change Events </reference/change-events/>` in the MongoDB manual
+   for more information.
+
+Return Values
+-------------
+
+An array or object for the current event in the change stream, or ``null`` if
+there is no current event (i.e. :phpmethod:`MongoDB\\ChangeStream::valid()`
+returns ``false``). The return type will depend on the ``typeMap`` option for
+:phpmethod:`MongoDB\\Collection::watch()`.
+
+Examples
+--------
+
+This example reports events while iterating a change stream.
+
+.. code-block:: php
+
+   <?php
+
+   $uri = 'mongodb://rs1.example.com,rs2.example.com/?replicaSet=myReplicaSet';
+
+   $collection = (new MongoDB\Client($uri))->test->inventory;
+
+   $changeStream = $collection->watch();
+
+   for ($changeStream->rewind(); true; $changeStream->next()) {
+       if ( ! $changeStream->valid()) {
+           continue;
+       }
+
+       $event = $changeStream->current();
+
+       $ns = sprintf('%s.%s', $event['ns']['db'], $event['ns']['coll']);
+       $id = json_encode($event['documentKey']['_id']);
+
+       switch ($event['operationType']) {
+           case 'delete':
+               printf("Deleted document in %s with _id: %s\n\n", $ns, $id);
+               break;
+
+           case 'insert':
+               printf("Inserted new document in %s\n", $ns);
+               echo json_encode($event['fullDocument']), "\n\n";
+               break;
+
+           case 'replace':
+               printf("Replaced new document in %s with _id: %s\n", $ns, $id);
+               echo json_encode($event['fullDocument']), "\n\n";
+               break;
+
+           case 'update':
+               printf("Updated document in %s with _id: %s\n", $ns, $id);
+               echo json_encode($event['updateDescription']), "\n\n";
+               break;
+       }
+   }
+
+Assuming that a document was inserted, updated, and deleted while the above
+script was iterating the change stream, the output would then resemble:
+
+.. code-block:: none
+
+   Inserted new document in test.inventory
+   {"_id":{"$oid":"5a81fc0d6118fd1af1790d32"},"name":"Widget","quantity":5}
+
+   Updated document in test.inventory with _id: {"$oid":"5a81fc0d6118fd1af1790d32"}
+   {"updatedFields":{"quantity":4},"removedFields":[]}
+
+   Deleted document in test.inventory with _id: {"$oid":"5a81fc0d6118fd1af1790d32"}
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`Iterator::current() <iterator.current>`
+- :ref:`Tailable Cursor Iteration <php-tailable-cursor>`
+- :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
+- :manual:`Change Events </reference/change-events/>` documentation in the
+  MongoDB manual
\ No newline at end of file
diff --git a/docs/reference/method/MongoDBChangeStream-getCursorId.txt b/docs/reference/method/MongoDBChangeStream-getCursorId.txt
new file mode 100644
index 0000000000000000000000000000000000000000..769e2dca2c4ea0b76c67d59b40b8933b31d93d6d
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-getCursorId.txt
@@ -0,0 +1,58 @@
+====================================
+MongoDB\\ChangeStream::getCursorId()
+====================================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::getCursorId()
+
+   Returns the change stream cursor's ID.
+
+   .. code-block:: php
+
+      function getCursorId(): MongoDB\Driver\CursorId
+
+Return Values
+-------------
+
+A :php:`MongoDB\\Driver\\CursorId <class.mongodb-driver-cursorid>` object.
+
+Examples
+--------
+
+This example reports the cursor ID for a change stream.
+
+.. code-block:: php
+
+   <?php
+
+   $uri = 'mongodb://rs1.example.com,rs2.example.com/?replicaSet=myReplicaSet';
+
+   $collection = (new MongoDB\Client($uri))->test->inventory;
+
+   $changeStream = $collection->watch();
+
+   var_dump($changeStream->getCursorId());
+
+The output would then resemble::
+
+   object(MongoDB\Driver\CursorId)#5 (1) {
+     ["id"]=>
+     int(8462642181784669708)
+   }
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`MongoDB\\Driver\\CursorId <class.mongodb-driver-cursorid>`
+- :php:`MongoDB\\Driver\\Cursor::getId() <manual/en/mongodb-driver-cursor.getid.php>`
diff --git a/docs/reference/method/MongoDBChangeStream-key.txt b/docs/reference/method/MongoDBChangeStream-key.txt
new file mode 100644
index 0000000000000000000000000000000000000000..338961b7fe5ea4cb6402ffdc6dfbe6628c6d7947
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-key.txt
@@ -0,0 +1,74 @@
+============================
+MongoDB\\ChangeStream::key()
+============================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::key()
+
+   Returns the index of the current event in the change stream.
+
+   .. code-block:: php
+
+      function key(): integer|null
+
+   The index of the first event in a change stream starts at zero and will
+   increment by one for each subsequent event.
+
+Return Values
+-------------
+
+The index of the current event in the change stream, or ``null`` if there is no
+current event (i.e. :phpmethod:`MongoDB\\ChangeStream::valid()` returns
+``false``).
+
+Examples
+--------
+
+This example reports the index of events while iterating a change stream.
+
+.. code-block:: php
+
+   <?php
+
+   $uri = 'mongodb://rs1.example.com,rs2.example.com/?replicaSet=myReplicaSet';
+
+   $collection = (new MongoDB\Client($uri))->test->inventory;
+
+   $changeStream = $collection->watch();
+
+   for ($changeStream->rewind(); true; $changeStream->next()) {
+       if ( ! $changeStream->valid()) {
+           continue;
+       }
+
+       $event = $changeStream->current();
+
+       printf("%d: %s\n", $changeStream->key(), $event['operationType']);
+   }
+
+Assuming that a document was inserted, updated, and deleted while the above
+script was iterating the change stream, the output would then resemble:
+
+.. code-block:: none
+
+   0: insert
+   1: update
+   2: delete
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`Iterator::key() <iterator.key>`
+- :ref:`Tailable Cursor Iteration <php-tailable-cursor>`
+- :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
\ No newline at end of file
diff --git a/docs/reference/method/MongoDBChangeStream-next.txt b/docs/reference/method/MongoDBChangeStream-next.txt
new file mode 100644
index 0000000000000000000000000000000000000000..629fd14f3d1c87b9436b3737ae815535d51cbdff
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-next.txt
@@ -0,0 +1,42 @@
+=============================
+MongoDB\\ChangeStream::next()
+=============================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::next()
+
+   Advances the change stream and attempts to load the next event.
+
+   .. code-block:: php
+
+      function next(): void
+
+   .. note::
+
+      Advancing the change stream does not guarantee that there will be a
+      current event to access. You should still call
+      :phpmethod:`MongoDB\\ChangeStream::valid()` to check for a current event
+      at each step of iteration.
+
+Errors/Exceptions
+-----------------
+
+.. include:: /includes/extracts/error-driver-runtimeexception.rst
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`Iterator::next() <iterator.next>`
+- :ref:`Tailable Cursor Iteration <php-tailable-cursor>`
+- :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
diff --git a/docs/reference/method/MongoDBChangeStream-rewind.txt b/docs/reference/method/MongoDBChangeStream-rewind.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dbdeb1618eb43b583e635d67794de3aa1e641cb6
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-rewind.txt
@@ -0,0 +1,52 @@
+===============================
+MongoDB\\ChangeStream::rewind()
+===============================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::rewind()
+
+   Rewinds the change stream and attempts to load the first event.
+
+   .. code-block:: php
+
+      function rewind(): void
+
+   This method should be called at the start of change stream iteration.
+
+   .. note::
+
+      Rewinding the change stream does not guarantee that there will be a
+      current event to access. You should still call
+      :phpmethod:`MongoDB\\ChangeStream::valid()` to check for a current event
+      at each step of iteration. After initially rewinding the change stream,
+      :phpmethod:`MongoDB\\ChangeStream::next()` should be used to iterate
+      further.
+
+Errors/Exceptions
+-----------------
+
+:php:`MongoDB\\Driver\\Exception\\LogicException
+<mongodb-driver-exception-logicexception>` if this method is called after a call
+to :phpmethod:`MongoDB\\ChangeStream::next()` (i.e. the underlying
+:php:`MongoDB\\Driver\\Cursor <class.mongodb-driver-cursor>` has already been
+advanced).
+
+.. include:: /includes/extracts/error-driver-runtimeexception.rst
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`Iterator::rewind() <iterator.rewind>`
+- :ref:`Tailable Cursor Iteration <php-tailable-cursor>`
+- :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
diff --git a/docs/reference/method/MongoDBChangeStream-valid.txt b/docs/reference/method/MongoDBChangeStream-valid.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d5b0d84c4ec99c130cd92d2aa348fe9f6f8e4958
--- /dev/null
+++ b/docs/reference/method/MongoDBChangeStream-valid.txt
@@ -0,0 +1,40 @@
+==============================
+MongoDB\\ChangeStream::valid()
+==============================
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+Definition
+----------
+
+.. phpmethod:: MongoDB\\ChangeStream::valid()
+
+   Returns whether there is a current event in the change stream.
+
+   .. code-block:: php
+
+      function valid(): boolean
+
+   When manually iterating the change stream using
+   :php:`Iterator </manual/en/class.iterator.php>` methods, this method should
+   be used to determine if :phpmethod:`MongoDB\\ChangeStream::current()` and
+   :phpmethod:`MongoDB\\ChangeStream::key()` can be called.
+
+Return Values
+-------------
+
+A boolean indicating whether there is a current event in the change stream.
+
+See Also
+--------
+
+- :phpmethod:`MongoDB\\Collection::watch()`
+- :php:`Iterator::valid() <iterator.valid>`
+- :ref:`Tailable Cursor Iteration <php-tailable-cursor>`
+- :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
diff --git a/docs/reference/method/MongoDBCollection-watch.txt b/docs/reference/method/MongoDBCollection-watch.txt
index dee50024a046774c21cf404bed2f6be4d31cd372..b5688c6bc21bc29b6994d49661ad1e197f0ec463 100644
--- a/docs/reference/method/MongoDBCollection-watch.txt
+++ b/docs/reference/method/MongoDBCollection-watch.txt
@@ -46,9 +46,71 @@ Errors/Exceptions
 .. include:: /includes/extracts/error-invalidargumentexception.rst
 .. include:: /includes/extracts/error-driver-runtimeexception.rst
 
+Examples
+--------
+
+This example reports events while iterating a change stream.
+
+.. code-block:: php
+
+   <?php
+
+   $uri = 'mongodb://rs1.example.com,rs2.example.com/?replicaSet=myReplicaSet';
+
+   $collection = (new MongoDB\Client($uri))->test->inventory;
+
+   $changeStream = $collection->watch();
+
+   for ($changeStream->rewind(); true; $changeStream->next()) {
+       if ( ! $changeStream->valid()) {
+           continue;
+       }
+
+       $event = $changeStream->current();
+
+       $ns = sprintf('%s.%s', $event['ns']['db'], $event['ns']['coll']);
+       $id = json_encode($event['documentKey']['_id']);
+
+       switch ($event['operationType']) {
+           case 'delete':
+               printf("Deleted document in %s with _id: %s\n\n", $ns, $id);
+               break;
+
+           case 'insert':
+               printf("Inserted new document in %s\n", $ns);
+               echo json_encode($event['fullDocument']), "\n\n";
+               break;
+
+           case 'replace':
+               printf("Replaced new document in %s with _id: %s\n", $ns, $id);
+               echo json_encode($event['fullDocument']), "\n\n";
+               break;
+
+           case 'update':
+               printf("Updated document in %s with _id: %s\n", $ns, $id);
+               echo json_encode($event['updateDescription']), "\n\n";
+               break;
+       }
+   }
+
+Assuming that a document was inserted, updated, and deleted while the above
+script was iterating the change stream, the output would then resemble:
+
+.. code-block:: none
+
+   Inserted new document in test.inventory
+   {"_id":{"$oid":"5a81fc0d6118fd1af1790d32"},"name":"Widget","quantity":5}
+
+   Updated document in test.inventory with _id: {"$oid":"5a81fc0d6118fd1af1790d32"}
+   {"updatedFields":{"quantity":4},"removedFields":[]}
+
+   Deleted document in test.inventory with _id: {"$oid":"5a81fc0d6118fd1af1790d32"}
+
 See Also
 --------
 
 - :manual:`Aggregation Pipeline </core/aggregation-pipeline>` documentation in
   the MongoDB Manual
 - :manual:`Change Streams </changeStreams>` documentation in the MongoDB manual
+- :manual:`Change Events </reference/change-events/>` documentation in the
+  MongoDB manual
diff --git a/docs/reference/result-classes.txt b/docs/reference/result-classes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f751b9a2cbb7cb457bec69c56730b1cb327f5c2e
--- /dev/null
+++ b/docs/reference/result-classes.txt
@@ -0,0 +1,42 @@
+==============
+Result Classes
+==============
+
+.. default-domain:: mongodb
+
+.. contents:: On this page
+   :local:
+   :backlinks: none
+   :depth: 1
+   :class: singlecol
+
+MongoDB\\ChangeStream
+---------------------
+
+.. versionadded:: 1.3
+
+Definition
+~~~~~~~~~~
+
+.. phpclass:: MongoDB\\ChangeStream
+
+   This class extends PHP's :php:`Iterator <manual/en/class.iterator.php>`
+   interface. An instance of this class is returned by
+   :phpmethod:`MongoDB\\Collection::watch()`.
+
+   This class allows for iteration of events in a change stream. It also allows
+   iteration to automatically resume after certain errors, such as a replica set
+   failover.
+
+Methods
+~~~~~~~
+
+.. toctree::
+   :titlesonly:
+
+   /reference/method/MongoDBChangeStream-current
+   /reference/method/MongoDBChangeStream-getCursorId
+   /reference/method/MongoDBChangeStream-key
+   /reference/method/MongoDBChangeStream-next
+   /reference/method/MongoDBChangeStream-rewind
+   /reference/method/MongoDBChangeStream-valid
diff --git a/docs/tutorial/tailable-cursor.txt b/docs/tutorial/tailable-cursor.txt
index 3496ad602195f8a9e0a5a79ab9a160ac70e3daa8..c4ff3b0eb52eb16afc344c7b78d8c0908a773f7e 100644
--- a/docs/tutorial/tailable-cursor.txt
+++ b/docs/tutorial/tailable-cursor.txt
@@ -1,3 +1,5 @@
+.. _php-tailable-cursor:
+
 =========================
 Tailable Cursor Iteration
 =========================