diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000..7c0da30a1
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,58 @@
+name: Build and publish docs
+
+on:
+ push:
+ branches: [master]
+
+permissions:
+ contents: write
+ pull-requests: write
+
+# Serialize docs regen runs so a new push doesn't rewrite the docs-update
+# branch mid-flight for a prior run that hasn't finished opening its PR.
+concurrency:
+ group: docs-publish
+ cancel-in-progress: false
+
+jobs:
+ build-and-pr:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.13"
+
+ - name: Install docs dependencies
+ run: pip install -e ".[docs]"
+
+ - name: Build Sphinx docs
+ run: sphinx-build -b html docs sphinx_build
+
+ - name: Checkout gh-pages
+ uses: actions/checkout@v4
+ with:
+ ref: gh-pages
+ path: gh-pages
+ fetch-depth: 0
+
+ - name: Copy Sphinx output into gh-pages/sphinx
+ run: |
+ rm -rf gh-pages/sphinx
+ cp -r sphinx_build gh-pages/sphinx
+
+ # delete-branch: true removes the docs-update branch after its PR is
+ # merged/closed. Without it, an unmerged prior PR's branch gets
+ # force-updated on the next run and any review comments on it are
+ # stranded.
+ - name: Create PR to gh-pages
+ uses: peter-evans/create-pull-request@v6
+ with:
+ path: gh-pages
+ branch: docs-update
+ base: gh-pages
+ delete-branch: true
+ title: "docs: update generated API reference"
+ body: "Automated update of Sphinx-generated API reference from master."
+ commit-message: "docs: regenerate Sphinx API reference"
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 000000000..96209fd5a
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,25 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version, and other tools you might need
+build:
+ os: ubuntu-24.04
+ tools:
+ python: "3.13"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+
+# Optionally, but recommended,
+# declare the Python requirements required to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+python:
+ install:
+ - method: pip
+ path: .
+ extra_requirements:
+ - docs
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 000000000..f9fcbf1bc
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,66 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+
+# -- Project information -----------------------------------------------------
+# Source - https://stackoverflow.com/a/75396624
+# Posted by Jan, modified by community. See post 'Timeline' for change history
+# Retrieved 2026-06-19, License - CC BY-SA 4.0
+
+# conf.py
+
+try:
+ import tomllib
+except ImportError:
+ import tomli as tomllib
+
+from pathlib import Path
+import importlib.metadata
+
+with open(Path(__file__).parent.parent / "pyproject.toml", "rb") as f:
+ toml = tomllib.load(f)
+
+# -- Project information -----------------------------------------------------
+
+project = toml["project"]["name"]
+release = importlib.metadata.version(project)
+version = ".".join(release.split(".")[:2])
+
+# -- General configuration ---------------------------------------------------
+# -- General configuration
+
+extensions = [
+ "sphinx.ext.duration",
+ "sphinx.ext.doctest",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.autosummary",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.napoleon",
+]
+
+intersphinx_mapping = {
+ "rtd": ("https://docs.readthedocs.io/en/stable/", None),
+ "python": ("https://docs.python.org/3/", None),
+ "sphinx": ("https://www.sphinx-doc.org/en/master/", None),
+}
+intersphinx_disabled_domains = ["std"]
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = "furo"
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 000000000..5db81bfd0
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,10 @@
+tableauserverclient
+===================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+.. automodule:: tableauserverclient
+ :members:
+ :imported-members:
diff --git a/pyproject.toml b/pyproject.toml
index e5a330c39..c2a8e93d8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -35,6 +35,7 @@ repository = "https://github.com/tableau/server-client-python"
[project.optional-dependencies]
test = ["black==26.5.1", "build", "mypy==2.3.0", "pytest>=7.0", "pytest-cov", "pytest-subtests",
"pytest-xdist", "requests-mock>=1.0,<2.0", "types-requests>=2.32.4.20250913"]
+docs = ["sphinx>=7,<9", "furo>=2024,<2027", "tomli; python_version < '3.11'"]
[tool.setuptools.package-data]
# Only include data for tableauserverclient, not for samples, test, docs
diff --git a/tableauserverclient/models/connection_item.py b/tableauserverclient/models/connection_item.py
index fa4b8cf9f..0dbadeda6 100644
--- a/tableauserverclient/models/connection_item.py
+++ b/tableauserverclient/models/connection_item.py
@@ -150,16 +150,7 @@ def from_response(cls, resp, ns) -> list["ConnectionItem"]:
@classmethod
def from_xml_element(cls, parsed_response, ns) -> list["ConnectionItem"]:
- """
-
-
-
-
-
-
-
-
- """
+ """Parse connection items from an XML ```` element."""
all_connection_items: list["ConnectionItem"] = list()
all_connection_xml = parsed_response.findall(".//t:connection", namespaces=ns)
diff --git a/tableauserverclient/models/site_item.py b/tableauserverclient/models/site_item.py
index 382ca63db..8cea6a7ab 100644
--- a/tableauserverclient/models/site_item.py
+++ b/tableauserverclient/models/site_item.py
@@ -52,10 +52,13 @@ class SiteItem:
cause an error.
tier_explorer_capacity: int
+ (Optional) The maximum number of licenses for users with the Explorer role allowed on a site.
+
tier_creator_capacity: int
+ (Optional) The maximum number of licenses for users with the Creator role allowed on a site.
+
tier_viewer_capacity: int
- (Optional) The maximum number of licenses for users with the Creator,
- Explorer, or Viewer role, respectively, allowed on a site.
+ (Optional) The maximum number of licenses for users with the Viewer role allowed on a site.
storage_quota: int
(Optional) Specifies the maximum amount of space for the new site, in