diff --git a/pyproject.toml b/pyproject.toml
index 17f7c0dcd7f2edf792887322230c29d91557c6fc..e4a7444a2d6374712c4792eb6ffe2b18f6a3d565 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -23,6 +23,7 @@ dependencies = [
 	'pydiffx~=1.1.0',
 	'texttable',
 	'typing_extensions>=4.3.0',
+	'typelets~=1.0.1',
 	'tqdm',
 
 	# importlib.metadata compatibility import.
diff --git a/rbtools/api/resource/__init__.py b/rbtools/api/resource/__init__.py
index f508535ff97676e3b41301e5ebec9d7bf534b24b..83b18241a6f6ad014ae096f01ae87ddf0e096f0b 100644
--- a/rbtools/api/resource/__init__.py
+++ b/rbtools/api/resource/__init__.py
@@ -18,21 +18,36 @@ from .diff import (
     DiffListResource,
     DiffResource,
 )
-from .diff_commit import DiffCommitItemResource
-from .diff_file_attachment import DiffFileAttachmentListResource
+from .diff_commit import DiffCommitItemResource, DiffCommitListResource
+from .diff_file_attachment import (
+    DiffFileAttachmentItemResource,
+    DiffFileAttachmentListResource,
+)
 from .draft_diff import DraftDiffResource
-from .draft_diff_commit import DraftDiffCommitItemResource
-from .draft_file_attachment import DraftFileAttachmentListResource
-from .draft_screenshot import DraftScreenshotListResource
-from .file_attachment import FileAttachmentListResource
-from .file_diff import FileDiffResource
+from .draft_diff_commit import (
+    DraftDiffCommitItemResource,
+    DraftDiffCommitListResource,
+)
+from .draft_file_attachment import (
+    DraftFileAttachmentItemResource,
+    DraftFileAttachmentListResource,
+)
+from .draft_screenshot import (
+    DraftScreenshotItemResource,
+    DraftScreenshotListResource,
+)
+from .file_attachment import (
+    FileAttachmentItemResource,
+    FileAttachmentListResource,
+)
+from .file_diff import FileDiffResource, FileDiffListResource
 from .mixins import (
     DiffUploaderMixin,
     GetPatchMixin,
 )
-from .review_request import ReviewRequestResource
+from .review_request import ReviewRequestResource, ReviewRequestListResource
 from .root import RootResource
-from .screenshot import ScreenshotListResource
+from .screenshot import ScreenshotItemResource, ScreenshotListResource
 from .validate_diff import ValidateDiffResource
 from .validate_diff_commit import ValidateDiffCommitResource
 
@@ -40,16 +55,23 @@ from .validate_diff_commit import ValidateDiffCommitResource
 __all__ = [
     'CountResource',
     'DiffCommitItemResource',
+    'DiffCommitListResource',
     'DiffFileAttachmentListResource',
     'DiffListResource',
     'DiffResource',
     'DiffUploaderMixin',
     'DraftDiffCommitItemResource',
+    'DraftDiffCommitListResource',
     'DraftDiffResource',
+    'DiffFileAttachmentItemResource',
+    'DraftFileAttachmentItemResource',
     'DraftFileAttachmentListResource',
+    'DraftScreenshotItemResource',
     'DraftScreenshotListResource',
+    'FileAttachmentItemResource',
     'FileAttachmentListResource',
     'FileDiffResource',
+    'FileDiffListResource',
     'GetPatchMixin',
     'ItemResource',
     'ListResource',
@@ -60,7 +82,9 @@ __all__ = [
     'ResourceLinkField',
     'ResourceListField',
     'ReviewRequestResource',
+    'ReviewRequestListResource',
     'RootResource',
+    'ScreenshotItemResource',
     'ScreenshotListResource',
     'ValidateDiffCommitResource',
     'ValidateDiffResource',
diff --git a/rbtools/api/resource/diff.py b/rbtools/api/resource/diff.py
index 0e569e3983875b01971669abc93f371ddbbad46d..052a66f71b1ee771512773143e2d5aaeb4d11e1b 100644
--- a/rbtools/api/resource/diff.py
+++ b/rbtools/api/resource/diff.py
@@ -7,6 +7,8 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import Optional, TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
 from rbtools.api.resource.base import (
@@ -16,26 +18,29 @@ from rbtools.api.resource.base import (
 )
 from rbtools.api.resource.mixins import DiffUploaderMixin, GetPatchMixin
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
 
 @resource_mimetype('application/vnd.reviewboard.org.diff')
 class DiffResource(GetPatchMixin, ItemResource):
-    """The Diff resource specific base class.
-
-    Provides the 'get_patch' method for retrieving the content of the
-    actual diff file itself.
-    """
+    """Item resource for diffs."""
 
     @request_method_decorator
-    def finalize_commit_series(self, cumulative_diff, validation_info,
-                               parent_diff=None):
+    def finalize_commit_series(
+        self,
+        cumulative_diff: bytes,
+        validation_info: str,
+        parent_diff: Optional[bytes] = None,
+    ) -> HttpRequest:
         """Finalize a commit series.
 
         Args:
             cumulative_diff (bytes):
                 The cumulative diff of the entire commit series.
 
-            validation_info (unicode):
-                The validation information returned by validatin the last
+            validation_info (str):
+                The validation information returned by validating the last
                 commit in the series with the
                 :py:class:`ValidateDiffCommitResource`.
 
@@ -49,17 +54,17 @@ class DiffResource(GetPatchMixin, ItemResource):
             The finalized diff resource.
         """
         if not isinstance(cumulative_diff, bytes):
-            raise TypeError('cumulative_diff must be byte string, not %s'
-                            % type(cumulative_diff))
+            raise TypeError(
+                f'cumulative_diff must be bytes, not {type(cumulative_diff)}')
 
         if parent_diff is not None and not isinstance(parent_diff, bytes):
-            raise TypeError('parent_diff must be byte string, not %s'
-                            % type(cumulative_diff))
+            raise TypeError(
+                f'parent_diff must be bytes, not {type(cumulative_diff)}')
 
-        request = HttpRequest(self.links['self']['href'],
+        request = HttpRequest(self._links['self']['href'],
                               method='PUT')
 
-        request.add_field('finalize_commit_series', True)
+        request.add_field('finalize_commit_series', '1')
         request.add_file('cumulative_diff', 'cumulative_diff',
                          cumulative_diff)
         request.add_field('validation_info', validation_info)
@@ -72,19 +77,41 @@ class DiffResource(GetPatchMixin, ItemResource):
 
 @resource_mimetype('application/vnd.reviewboard.org.diffs')
 class DiffListResource(DiffUploaderMixin, ListResource):
-    """The Diff List resource specific base class.
-
-    This resource provides functionality to assist in the uploading of new
-    diffs.
-    """
+    """List resource for diffs."""
 
     @request_method_decorator
-    def upload_diff(self, diff, parent_diff=None, base_dir=None,
-                    base_commit_id=None, **kwargs):
+    def upload_diff(
+        self,
+        diff: bytes,
+        parent_diff: Optional[bytes] = None,
+        base_dir: Optional[str] = None,
+        base_commit_id: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Upload a diff to the resource.
 
         The diff and parent_diff arguments should be strings containing the
         diff output.
+
+        Args:
+            diff (bytes):
+                The diff content.
+
+            parent_diff (bytes, optional):
+                The parent diff content, if present.
+
+            base_dir (str, optional):
+                The base directory for the diff, if present.
+
+            base_commit_id (str, optional):
+                The ID of the commit that the diff is against, if present.
+
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            DiffItemResource:
+            The newly-created diff.
         """
         return self.prepare_upload_diff_request(
             diff,
@@ -94,19 +121,23 @@ class DiffListResource(DiffUploaderMixin, ListResource):
             **kwargs)
 
     @request_method_decorator
-    def create_empty(self, base_commit_id=None, **kwargs):
+    def create_empty(
+        self,
+        base_commit_id: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Create an empty DiffSet that commits can be added to.
 
         Args:
-            base_commit_id (unicode, optional):
+            base_commit_id (str, optional):
                 The base commit ID of the diff.
 
-            **kwargs (dict):
-                Keyword arguments to encode into the querystring of the request
-                URL.
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
         Returns:
             DiffItemResource:
-            The created resource.
+            The newly-created diff.
         """
         request = HttpRequest(self._url, method='POST', query_args=kwargs)
 
diff --git a/rbtools/api/resource/diff_commit.py b/rbtools/api/resource/diff_commit.py
index 778ce93fbf67340b2228e61d74b03da97fd9df11..a8b446b952f99b22fa5dd98b93e3c1ebc6b65ee0 100644
--- a/rbtools/api/resource/diff_commit.py
+++ b/rbtools/api/resource/diff_commit.py
@@ -9,6 +9,7 @@ from __future__ import annotations
 
 from rbtools.api.resource.base import (
     ItemResource,
+    ListResource,
     resource_mimetype,
 )
 from rbtools.api.resource.mixins import GetPatchMixin
@@ -16,4 +17,13 @@ from rbtools.api.resource.mixins import GetPatchMixin
 
 @resource_mimetype('application/vnd.reviewboard.org.commit')
 class DiffCommitItemResource(GetPatchMixin, ItemResource):
-    """The commit resource-specific class."""
+    """Item resource for diff commits."""
+
+
+@resource_mimetype('application/vnd.reviewboard.org.commits')
+class DiffCommitListResource(GetPatchMixin, ListResource):
+    """List resource for diff commits.
+
+    Version Added:
+        6.0
+    """
diff --git a/rbtools/api/resource/diff_file_attachment.py b/rbtools/api/resource/diff_file_attachment.py
index 2407318aae9ab8a288ed12d7c18b97f3aec0f350..94be3995a45538636c01484539f750e2ee2fb657 100644
--- a/rbtools/api/resource/diff_file_attachment.py
+++ b/rbtools/api/resource/diff_file_attachment.py
@@ -10,15 +10,28 @@ from __future__ import annotations
 from typing import TYPE_CHECKING
 
 from rbtools.api.decorators import request_method_decorator
-from rbtools.api.resource.base import ListResource, resource_mimetype
+from rbtools.api.resource.base import (
+    ItemResource,
+    ListResource,
+    resource_mimetype,
+)
 
 if TYPE_CHECKING:
-    from rbtools.api.request import HttpRequest
+    from rbtools.api.request import HttpRequest, QueryArgs
+
+
+@resource_mimetype('application/vnd.reviewboard.org.diff-file-attachment')
+class DiffFileAttachmentItemResource(ItemResource):
+    """Item resource for diff file attachments.
+
+    Version Added:
+        6.0
+    """
 
 
 @resource_mimetype('application/vnd.reviewboard.org.diff-file-attachments')
 class DiffFileAttachmentListResource(ListResource):
-    """The Diff File Attachment List resource specific base class.
+    """List resource for diff file attachments.
 
     Version Added:
         5.0
@@ -32,7 +45,7 @@ class DiffFileAttachmentListResource(ListResource):
         content: bytes,
         filediff_id: str,
         source_file: bool = False,
-        **kwargs,
+        **kwargs: QueryArgs,
     ) -> HttpRequest:
         """Upload a new attachment.
 
@@ -49,12 +62,12 @@ class DiffFileAttachmentListResource(ListResource):
             source_file (bool, optional):
                 Whether to upload the source version of a file.
 
-            **kwargs (dict):
-                Additional keyword arguments to add to the request
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
 
         Returns:
-            rbtools.api.request.HttpRequest:
-            The request object.
+            DiffFileAttachmentItemResource:
+            The newly created diff file attachment.
         """
         request = self.create(query_args=kwargs, internal=True)
         request.add_file('path', filename, content)
diff --git a/rbtools/api/resource/draft_diff.py b/rbtools/api/resource/draft_diff.py
index 56b257ec0a6fba1fb067e9a4ca94860f62a686dd..243019b8e1b5deb475cbc06c43c4b799666b6e61 100644
--- a/rbtools/api/resource/draft_diff.py
+++ b/rbtools/api/resource/draft_diff.py
@@ -14,6 +14,9 @@ from rbtools.api.resource.base import (
 from rbtools.api.resource.mixins import GetPatchMixin
 
 
+# TODO: this resource/mimetype does not actually exist. This will be removed in
+# a future change.
+
 @resource_mimetype('application/vnd.reviewboard.org.draft-diff')
 class DraftDiffResource(GetPatchMixin, ItemResource):
     """The Draft Diff resource specific base class.
diff --git a/rbtools/api/resource/draft_diff_commit.py b/rbtools/api/resource/draft_diff_commit.py
index 2116bbd298bbe815da663b47815cacc50f340afb..81c086431936bdf7ae3c59cdecb1cd0226682060 100644
--- a/rbtools/api/resource/draft_diff_commit.py
+++ b/rbtools/api/resource/draft_diff_commit.py
@@ -8,6 +8,7 @@ Version Added:
 from __future__ import annotations
 
 import logging
+from typing import Optional, TYPE_CHECKING
 
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
@@ -18,13 +19,16 @@ from rbtools.api.resource.base import (
 )
 from rbtools.api.resource.mixins import GetPatchMixin
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
 
 logger = logging.getLogger(__name__)
 
 
 @resource_mimetype('application/vnd.reviewboard.org.draft-commit')
 class DraftDiffCommitItemResource(GetPatchMixin, ItemResource):
-    """The draft commit resource-specific class.
+    """Item resource for draft diff commits.
 
     Version Added:
         4.2
@@ -33,57 +37,68 @@ class DraftDiffCommitItemResource(GetPatchMixin, ItemResource):
 
 @resource_mimetype('application/vnd.reviewboard.org.draft-commits')
 class DraftDiffCommitListResource(ListResource):
-    """The draft commit list resource-specific class.
-
-    Provides additional functionality in the uploading of new commits.
-    """
+    """List resource for draft diff commits."""
 
     @request_method_decorator
-    def upload_commit(self, validation_info, diff, commit_id, parent_id,
-                      author_name, author_email, author_date, commit_message,
-                      committer_name=None, committer_email=None,
-                      committer_date=None, parent_diff=None, **kwargs):
+    def upload_commit(
+        self,
+        validation_info: str,
+        diff: bytes,
+        commit_id: str,
+        parent_id: str,
+        author_name: str,
+        author_email: str,
+        author_date: str,
+        commit_message: str,
+        committer_name: Optional[str] = None,
+        committer_email: Optional[str] = None,
+        committer_date: Optional[str] = None,
+        parent_diff: Optional[bytes] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Upload a commit.
 
         Args:
-            validation_info (unicode):
+            validation_info (str):
                 The validation info, or ``None`` if this is the first commit in
                 a series.
 
             diff (bytes):
                 The diff contents.
 
-            commit_id (unicode):
+            commit_id (str):
                 The ID of the commit being uploaded.
 
-            parent_id (unicode):
+            parent_id (str):
                 The ID of the parent commit.
 
-            author_name (unicode):
+            author_name (str):
                 The name of the author.
 
-            author_email (unicode):
+            author_email (str):
                 The e-mail address of the author.
 
-            author_date (unicode):
+            commit_message (str):
+                The commit message.
+
+            author_date (str):
                 The date and time the commit was authored in ISO 8601 format.
 
-            committer_name (unicode, optional):
+            committer_name (str, optional):
                 The name of the committer (if applicable).
 
-            committer_email (unicode, optional):
+            committer_email (str, optional):
                 The e-mail address of the committer (if applicable).
 
-            committer_date (unicode, optional):
+            committer_date (str, optional):
                 The date and time the commit was committed in ISO 8601 format
                 (if applicable).
 
             parent_diff (bytes, optional):
                 The contents of the parent diff.
 
-            **kwargs (dict):
-                Keyword argument used to build the querystring for the request
-                URL.
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
 
         Returns:
             DraftDiffCommitItemResource:
diff --git a/rbtools/api/resource/draft_file_attachment.py b/rbtools/api/resource/draft_file_attachment.py
index 8c8ee1b3bc7c1c5dfacf3cd520cdcdf050cbc6bf..40698ec5bd80d47d844ffedf839c346938181d9d 100644
--- a/rbtools/api/resource/draft_file_attachment.py
+++ b/rbtools/api/resource/draft_file_attachment.py
@@ -7,10 +7,19 @@ Version Added:
 
 from __future__ import annotations
 
-from rbtools.api.resource.base import resource_mimetype
+from rbtools.api.resource.base import ItemResource, resource_mimetype
 from rbtools.api.resource.file_attachment import FileAttachmentListResource
 
 
+@resource_mimetype('application/vnd.reviewboard.org.draft-file-attachment')
+class DraftFileAttachmentItemResource(ItemResource):
+    """Item resource for draft file attachments.
+
+    Version Added:
+        6.0
+    """
+
+
 @resource_mimetype('application/vnd.reviewboard.org.draft-file-attachments')
 class DraftFileAttachmentListResource(FileAttachmentListResource):
-    """The Draft File Attachment List resource specific base class."""
+    """List resource for draft file attachments."""
diff --git a/rbtools/api/resource/draft_screenshot.py b/rbtools/api/resource/draft_screenshot.py
index 93428701191a3746f601f2556c8ef8901c9432e0..cdaf68dc6d042f1e966bd3d79bb740736eba6842 100644
--- a/rbtools/api/resource/draft_screenshot.py
+++ b/rbtools/api/resource/draft_screenshot.py
@@ -7,10 +7,19 @@ Version Added:
 
 from __future__ import annotations
 
-from rbtools.api.resource.base import resource_mimetype
+from rbtools.api.resource.base import ItemResource, resource_mimetype
 from rbtools.api.resource.screenshot import ScreenshotListResource
 
 
+@resource_mimetype('application/vnd.reviewboard.org.draft-screenshot')
+class DraftScreenshotItemResource(ItemResource):
+    """Item resource for draft screenshots.
+
+    Version Added:
+        6.0
+    """
+
+
 @resource_mimetype('application/vnd.reviewboard.org.draft-screenshots')
 class DraftScreenshotListResource(ScreenshotListResource):
-    """The Draft Screenshot List resource specific base class."""
+    """List resource for draft screenshots."""
diff --git a/rbtools/api/resource/file_attachment.py b/rbtools/api/resource/file_attachment.py
index 5e6df0d245ecb332fa0662449f271234923c7a9a..52459f545ef2ce80eac8febf2bfc56011aaaafa2 100644
--- a/rbtools/api/resource/file_attachment.py
+++ b/rbtools/api/resource/file_attachment.py
@@ -7,17 +7,33 @@ Version Added:
 
 from __future__ import annotations
 
-from typing import Optional
+from typing import Optional, TYPE_CHECKING
 
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
-from rbtools.api.resource.base import ListResource, resource_mimetype
+from rbtools.api.resource.base import (
+    ItemResource,
+    ListResource,
+    resource_mimetype,
+)
+
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
+
+@resource_mimetype('application/vnd.reviewboard.org.file-attachment')
+class FileAttachmentItemResource(ItemResource):
+    """Item resource for file attachments.
+
+    Version Added:
+        6.0
+    """
 
 
 @resource_mimetype('application/vnd.reviewboard.org.file-attachments')
 @resource_mimetype('application/vnd.reviewboard.org.user-file-attachments')
 class FileAttachmentListResource(ListResource):
-    """The File Attachment List resource specific base class."""
+    """List resource for file attachments."""
 
     @request_method_decorator
     def upload_attachment(
@@ -26,7 +42,7 @@ class FileAttachmentListResource(ListResource):
         content: bytes,
         caption: Optional[str] = None,
         attachment_history: Optional[str] = None,
-        **kwargs,
+        **kwargs: QueryArgs,
     ) -> HttpRequest:
         """Upload a new attachment.
 
@@ -43,9 +59,14 @@ class FileAttachmentListResource(ListResource):
             attachment_history (str, optional):
                 The ID of the FileAttachmentHistory to add this attachment to.
 
-            **kwargs (dict):
-                Additional keyword arguments to add to the request.
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            FileAttachmentItemResource:
+            The newly-created file attachment.
         """
+        assert self._url is not None
         request = HttpRequest(self._url, method='POST', query_args=kwargs)
         request.add_file('path', filename, content)
 
diff --git a/rbtools/api/resource/file_diff.py b/rbtools/api/resource/file_diff.py
index 33785d44c5ce467821f63d00cd8f7803a90d251e..7da17cc797d87ee0903bc8860e40e36d2af2a5b8 100644
--- a/rbtools/api/resource/file_diff.py
+++ b/rbtools/api/resource/file_diff.py
@@ -7,19 +7,49 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
-from rbtools.api.resource.base import ItemResource, resource_mimetype
+from rbtools.api.resource.base import (
+    ItemResource,
+    ListResource,
+    resource_mimetype,
+)
 from rbtools.api.resource.mixins import GetPatchMixin
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
 
 @resource_mimetype('application/vnd.reviewboard.org.file')
 class FileDiffResource(GetPatchMixin, ItemResource):
-    """The File Diff resource specific base class."""
+    """Item resource for file diffs."""
 
     @request_method_decorator
-    def get_diff_data(self, **kwargs):
-        """Retrieves the actual raw diff data for the file."""
+    def get_diff_data(
+        self,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
+        """Retrieve the actual raw diff data for the file.
+
+        Args:
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            rbtools.api.resource.ItemResource:
+            A resource wrapping the diff data.
+        """
         return HttpRequest(self._url, query_args=kwargs, headers={
             'Accept': 'application/vnd.reviewboard.org.diff.data+json',
         })
+
+
+@resource_mimetype('application/vnd.reviewboard.org.files')
+class FileDiffListResource(ListResource):
+    """List resource for file diffs.
+
+    Version Added:
+        6.0
+    """
diff --git a/rbtools/api/resource/mixins.py b/rbtools/api/resource/mixins.py
index 8e87d635e03739998484d1bc80494716629663ec..ff269f699982002638540abaa45f40f7f9ea38d9 100644
--- a/rbtools/api/resource/mixins.py
+++ b/rbtools/api/resource/mixins.py
@@ -7,20 +7,52 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import Optional, TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
 
 class DiffUploaderMixin:
     """A mixin for uploading diffs to a resource."""
 
-    def prepare_upload_diff_request(self, diff, parent_diff=None,
-                                    base_dir=None, base_commit_id=None,
-                                    **kwargs):
+    _url: str
+
+    def prepare_upload_diff_request(
+        self,
+        diff: bytes,
+        parent_diff: Optional[bytes] = None,
+        base_dir: Optional[str] = None,
+        base_commit_id: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Create a request that can be used to upload a diff.
 
         The diff and parent_diff arguments should be strings containing the
         diff output.
+
+        Args:
+            diff (bytes):
+                The diff content.
+
+            parent_diff (bytes, optional):
+                The parent diff content, if present.
+
+            base_dir (str, optional):
+                The base directory for the diff, if present.
+
+            base_commit_id (str, optional):
+                The ID of the commit that the diff is against, if present.
+
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            rbtools.api.request.HttpRequest:
+            The API request.
         """
         request = HttpRequest(self._url, method='POST', query_args=kwargs)
         request.add_file('path', 'diff', diff)
@@ -44,19 +76,23 @@ class GetPatchMixin:
         4.2
     """
 
+    _url: str
+
     @request_method_decorator
-    def get_patch(self, **kwargs):
+    def get_patch(
+        self,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Retrieve the diff file contents.
 
         Args:
-            **kwargs (dict):
-                Query args to pass to
-                :py:meth:`~rbtools.api.request.HttpRequest.__init__`.
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
 
         Returns:
-            ItemResource:
-            A resource payload whose :py:attr:`~ItemResource.data` attribute is
-            the requested patch.
+            rbtools.api.resource.ItemResource:
+            A resource containing the patch. The patch data will be in the
+            ``data`` attribute.
         """
         return HttpRequest(self._url, query_args=kwargs, headers={
             'Accept': 'text/x-patch',
diff --git a/rbtools/api/resource/review_request.py b/rbtools/api/resource/review_request.py
index c302119aad20947de8df4ffacaedaf98c652746d..c1c06bd5a0a3261684b7191dcdcd278473821926 100644
--- a/rbtools/api/resource/review_request.py
+++ b/rbtools/api/resource/review_request.py
@@ -8,45 +8,80 @@ Version Added:
 from __future__ import annotations
 
 from collections import defaultdict, deque
+from typing import Optional, TYPE_CHECKING
 from urllib.parse import urljoin
 
+from typing_extensions import Self
+
 from rbtools.api.decorators import request_method_decorator
-from rbtools.api.resource.base import ItemResource, resource_mimetype
+from rbtools.api.resource.base import (
+    ItemResource,
+    ListResource,
+    resource_mimetype,
+)
 from rbtools.utils.graphs import path_exists
 
+if TYPE_CHECKING:
+    from rbtools.api.request import HttpRequest, QueryArgs
+
 
 @resource_mimetype('application/vnd.reviewboard.org.review-request')
 class ReviewRequestResource(ItemResource):
-    """The Review Request resource specific base class."""
+    """Item resource for review requests."""
 
     @property
-    def absolute_url(self):
-        """Returns the absolute URL for the Review Request.
+    def absolute_url(self) -> str:
+        """The absolute URL for the Review Request.
 
-        The value of absolute_url is returned if it's defined.
-        Otherwise the absolute URL is generated and returned.
+        The value of absolute_url is returned if it's defined. Otherwise the
+        absolute URL is generated and returned.
+
+        Type:
+            str
         """
         if 'absolute_url' in self._fields:
             return self._fields['absolute_url']
         else:
+            assert self._url is not None
+
             base_url = self._url.split('/api/')[0]
             return urljoin(base_url, self.url)
 
     @property
-    def url(self):
-        """Returns the relative URL to the Review Request.
+    def url(self) -> str:
+        """The relative URL to the Review Request.
 
         The value of 'url' is returned if it's defined. Otherwise, a relative
         URL is generated and returned.
 
         This provides compatibility with versions of Review Board older
         than 1.7.8, which do not have a 'url' field.
+
+        Type:
+            str
         """
-        return self._fields.get('url', '/r/%s/' % self.id)
+        return self._fields.get('url', f'/r/{self.id}/')
 
     @request_method_decorator
-    def submit(self, description=None, changenum=None):
-        """Submit a review request"""
+    def submit(
+        self,
+        description: Optional[str] = None,
+        changenum: Optional[str] = None,
+    ) -> HttpRequest:
+        """Submit a review request.
+
+        Args:
+            description (str, optional):
+                The close description text to include.
+
+            changenum (str, optional):
+                The change number (commit ID) for the review request now that
+                the code has been submitted.
+
+        Returns:
+            ReviewRequestResource:
+            The updated review request.
+        """
         data = {
             'status': 'submitted',
         }
@@ -60,7 +95,20 @@ class ReviewRequestResource(ItemResource):
         return self.update(data=data, internal=True)
 
     @request_method_decorator
-    def get_or_create_draft(self, **kwargs):
+    def get_or_create_draft(
+        self,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
+        """Retrieve or create a draft.
+
+        Args:
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            rbtools.api.resource.ItemResource:
+            The review request draft.
+        """
         request = self.get_draft(internal=True)
         request.method = 'POST'
 
@@ -69,7 +117,9 @@ class ReviewRequestResource(ItemResource):
 
         return request
 
-    def build_dependency_graph(self):
+    def build_dependency_graph(
+        self,
+    ) -> defaultdict[Self, set[Self]]:
         """Build the dependency graph for the review request.
 
         Only review requests in the same repository as this one will be in the
@@ -77,7 +127,7 @@ class ReviewRequestResource(ItemResource):
 
         A ValueError is raised if the graph would contain cycles.
         """
-        def get_url(resource):
+        def get_url(resource: Self) -> str:
             """Get the URL of the resource."""
             if hasattr(resource, 'href'):
                 return resource.href
@@ -91,7 +141,9 @@ class ReviewRequestResource(ItemResource):
         review_requests_by_url = {}
         review_requests_by_url[self.absolute_url] = self
 
-        def get_review_request_resource(resource):
+        def get_review_request_resource(
+            resource: Self,
+        ) -> Self:
             url = get_url(resource)
 
             if url not in review_requests_by_url:
@@ -131,4 +183,14 @@ class ReviewRequestResource(ItemResource):
                     unvisited.append(tail)
 
         graph.default_factory = None
+
         return graph
+
+
+@resource_mimetype('application/vnd.reviewboard.org.review-requests')
+class ReviewRequestListResource(ListResource):
+    """List resource for review requests.
+
+    Version Added:
+        6.0
+    """
diff --git a/rbtools/api/resource/root.py b/rbtools/api/resource/root.py
index d86f405b4338be8539bd119fe75e6fd2b95a728a..ef232b4662f9f057f8bb19070d01ddb87219cd80 100644
--- a/rbtools/api/resource/root.py
+++ b/rbtools/api/resource/root.py
@@ -8,8 +8,10 @@ Version Added:
 from __future__ import annotations
 
 import re
+from typing import Optional, TYPE_CHECKING, cast
 
 from packaging.version import parse as parse_version
+from typelets.json import JSONDict
 
 from rbtools.api.cache import MINIMUM_VERSION
 from rbtools.api.decorators import request_method_decorator
@@ -20,6 +22,10 @@ from rbtools.api.resource.base import (
     resource_mimetype,
 )
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+    from rbtools.api.transport import Transport
+
 
 @resource_mimetype('application/vnd.reviewboard.org.root')
 class RootResource(ItemResource):
@@ -38,12 +44,34 @@ class RootResource(ItemResource):
     _excluded_attrs = ['uri_templates']
     _TEMPLATE_PARAM_RE = re.compile(r'\{(?P<key>[A-Za-z_0-9]*)\}')
 
-    def __init__(self, transport, payload, url, **kwargs):
-        super(RootResource, self).__init__(transport, payload, url, token=None)
+    def __init__(
+        self,
+        transport: Transport,
+        payload: JSONDict,
+        url: str,
+        **kwargs,
+    ) -> None:
+        """Initialize the resource.
+
+        Args:
+            transport (rbtools.api.transport.Transport):
+                The API transport.
+
+            payload (dict):
+                The resource payload.
+
+            url (str):
+                The resource URL.
+
+            **kwargs (dict, unused):
+                Unused keyword arguments.
+        """
+        super().__init__(transport, payload, url, token=None)
+
         # Generate methods for accessing resources directly using
         # the uri-templates.
         for name, url in payload['uri_templates'].items():
-            attr_name = 'get_%s' % name
+            attr_name = f'get_{name}'
 
             if not hasattr(self, attr_name):
                 setattr(self,
@@ -51,7 +79,8 @@ class RootResource(ItemResource):
                         lambda resource=self, url=url, **kwargs: (
                             self._get_template_request(url, **kwargs)))
 
-        server_version = payload.get('product', {}).get('package_version')
+        product = cast(JSONDict, payload.get('product', {}))
+        server_version = cast(Optional[str], product.get('package_version'))
 
         if (server_version is None or
             parse_version(server_version) < parse_version(MINIMUM_VERSION)):
@@ -60,21 +89,46 @@ class RootResource(ItemResource):
             transport.disable_cache()
 
     @request_method_decorator
-    def _get_template_request(self, url_template, values={}, **kwargs):
+    def _get_template_request(
+        self,
+        url_template: str,
+        values: Optional[dict[str, str]] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Generate an HttpRequest from a uri-template.
 
         This will replace each '{variable}' in the template with the
         value from kwargs['variable'], or if it does not exist, the
         value from values['variable']. The resulting url is used to
         create an HttpRequest.
+
+        Args:
+            url_template (str):
+                The URL template.
+
+            values (dict, optional):
+                The values to use for replacing template variables.
+
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            rbtools.api.resource.Resource:
+            The resource at the given URL.
         """
-        def get_template_value(m):
+        if values is None:
+            values = {}
+
+        def get_template_value(
+            m: re.Match[str],
+        ) -> str:
+            key = m.group('key')
+
             try:
-                return str(kwargs.pop(m.group('key'), None) or
-                           values[m.group('key')])
+                return str(kwargs.pop(key, None) or values[key])
             except KeyError:
-                raise ValueError('Template was not provided a value for "%s"' %
-                                 m.group('key'))
+                raise ValueError(
+                    f'Template was not provided a value for "{key}"')
 
         url = self._TEMPLATE_PARAM_RE.sub(get_template_value, url_template)
         return HttpRequest(url, query_args=kwargs)
diff --git a/rbtools/api/resource/screenshot.py b/rbtools/api/resource/screenshot.py
index 8c39bcb9d1282bd278e2f2f1bbf6c58aab535e71..9bbed4bc9e5557c80dc708a3c58f330e70e965f0 100644
--- a/rbtools/api/resource/screenshot.py
+++ b/rbtools/api/resource/screenshot.py
@@ -7,22 +7,65 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import Optional, TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
-from rbtools.api.resource.base import ListResource, resource_mimetype
+from rbtools.api.resource.base import (
+    ItemResource,
+    ListResource,
+    resource_mimetype,
+)
+
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
+
+@resource_mimetype('application/vnd.reviewboard.org.screenshot')
+class ScreenshotItemResource(ItemResource):
+    """Item resource for screenshots.
+
+    Version Added:
+        6.0
+    """
 
 
 @resource_mimetype('application/vnd.reviewboard.org.screenshots')
 class ScreenshotListResource(ListResource):
-    """The Screenshot List resource specific base class."""
+    """List resource for screenshots."""
 
     @request_method_decorator
-    def upload_screenshot(self, filename, content, caption=None, **kwargs):
-        """Uploads a new screenshot.
+    def upload_screenshot(
+        self,
+        filename: str,
+        content: bytes,
+        caption: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
+        """Upload a new screenshot.
 
         The content argument should contain the body of the screenshot
         to be uploaded, in string format.
+
+        Args:
+            filename (str):
+                The filename of the screenshot.
+
+            content (bytes):
+                The image file content.
+
+            caption (str, optional):
+                The caption to add to the screenshot.
+
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            ScreenshotItemResource:
+            The newly-created screenshot.
         """
+        assert self._url is not None
+
         request = HttpRequest(self._url, method='POST', query_args=kwargs)
         request.add_file('path', filename, content)
 
diff --git a/rbtools/api/resource/validate_diff.py b/rbtools/api/resource/validate_diff.py
index c5942c4ddd40d86fa34ba84c9b4b3f167d24075c..ef2d77ffdbdb01eb521122538784aff930073534 100644
--- a/rbtools/api/resource/validate_diff.py
+++ b/rbtools/api/resource/validate_diff.py
@@ -7,22 +7,55 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import Optional, TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.resource.base import ItemResource, resource_mimetype
 from rbtools.api.resource.mixins import DiffUploaderMixin
 
+if TYPE_CHECKING:
+    from rbtools.api.request import HttpRequest, QueryArgs
+
 
 @resource_mimetype('application/vnd.reviewboard.org.diff-validation')
 class ValidateDiffResource(DiffUploaderMixin, ItemResource):
-    """The Validate Diff resource specific base class.
-
-    Provides additional functionality to assist in the validation of diffs.
-    """
+    """Singleton resource for diff validation."""
 
     @request_method_decorator
-    def validate_diff(self, repository, diff, parent_diff=None, base_dir=None,
-                      base_commit_id=None, **kwargs):
-        """Validate a diff."""
+    def validate_diff(
+        self,
+        repository: str,
+        diff: bytes,
+        parent_diff: Optional[bytes] = None,
+        base_dir: Optional[str] = None,
+        base_commit_id: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
+        """Validate a diff.
+
+        Args:
+            repository (str):
+                The repository name.
+
+            diff (bytes):
+                The diff content.
+
+            parent_diff (bytes, optional):
+                The parent diff content, if present.
+
+            base_dir (str, optional):
+                The base directory for the diff, if present.
+
+            base_commit_id (str, optional):
+                The ID of the commit that the diff is against, if present.
+
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
+
+        Returns:
+            ValidateDiffResource:
+            The validation response.
+        """
         request = self.prepare_upload_diff_request(
             diff,
             parent_diff=parent_diff,
diff --git a/rbtools/api/resource/validate_diff_commit.py b/rbtools/api/resource/validate_diff_commit.py
index 77690232aa00ce8d41667f1d9bda5a5f9a4c3b3d..860244494874467a284731811b8e44c4d24ae98e 100644
--- a/rbtools/api/resource/validate_diff_commit.py
+++ b/rbtools/api/resource/validate_diff_commit.py
@@ -7,50 +7,65 @@ Version Added:
 
 from __future__ import annotations
 
+from typing import Optional, TYPE_CHECKING
+
 from rbtools.api.decorators import request_method_decorator
 from rbtools.api.request import HttpRequest
 from rbtools.api.resource.base import ItemResource, resource_mimetype
 
+if TYPE_CHECKING:
+    from rbtools.api.request import QueryArgs
+
 
 @resource_mimetype('application/vnd.reviewboard.org.commit-validation')
 class ValidateDiffCommitResource(ItemResource):
-    """The commit validation resource specific base class."""
+    """Singleton resource for commit validation."""
 
     @request_method_decorator
-    def validate_commit(self, repository, diff, commit_id, parent_id,
-                        parent_diff=None, base_commit_id=None,
-                        validation_info=None, **kwargs):
+    def validate_commit(
+        self,
+        repository: str,
+        diff: bytes,
+        commit_id: str,
+        parent_id: str,
+        parent_diff: Optional[bytes] = None,
+        base_commit_id: Optional[str] = None,
+        validation_info: Optional[str] = None,
+        **kwargs: QueryArgs,
+    ) -> HttpRequest:
         """Validate the diff for a commit.
 
         Args:
-            repository (unicode):
+            repository (str):
                 The name of the repository.
 
             diff (bytes):
                 The contents of the diff to validate.
 
-            commit_id (unicode):
+            commit_id (str):
                 The ID of the commit being validated.
 
-            parent_id (unicode):
+            parent_id (str):
                 The ID of the parent commit.
 
             parent_diff (bytes, optional):
                 The contents of the parent diff.
 
-            base_commit_id (unicode, optional):
+            base_commit_id (str, optional):
                 The base commit ID.
 
-            validation_info (unicode, optional):
+            validation_info (str, optional):
                 Validation information from a previous call to this resource.
 
-            **kwargs (dict):
-                Keyword arguments used to build the querystring.
+            **kwargs (rbtools.api.request.QueryArgs):
+                Query arguments to include with the request.
 
         Returns:
             ValidateDiffCommitResource:
             The validation result.
         """
+        assert self._url is not None
+
         request = HttpRequest(self._url, method='POST', query_args=kwargs)
         request.add_file('diff', 'diff', diff)
         request.add_field('repository', repository)
