diff --git a/circleci/api.py b/circleci/api.py
index cf8a7ab..84ea9c6 100644
--- a/circleci/api.py
+++ b/circleci/api.py
@@ -259,7 +259,7 @@ class Api():
         resp = self._request('GET', endpoint)
         return resp
 
-    def retry_build(self, username, project, build_num, vcs_type='github'):
+    def retry_build(self, username, project, build_num, ssh=False, vcs_type='github'):
         """Retries the build.
 
         Args:
@@ -269,6 +269,8 @@ class Api():
                 case sensitive repo name
             build_num (str):
                 build number
+            ssh: retry a build with SSH enabled
+                defaults to False
             vcs_type (str):
                 defaults to github
                 on circleci.com you can also pass in bitbucket
@@ -276,12 +278,20 @@ class Api():
         Endpoint:
             POST: /project/:vcs-type/:username/:project/:build_num/retry
         """
-        endpoint = 'project/{0}/{1}/{2}/{3}/retry'.format(
-            vcs_type,
-            username,
-            project,
-            build_num
-        )
+        if ssh:
+            endpoint = 'project/{0}/{1}/{2}/{3}/ssh'.format(
+                vcs_type,
+                username,
+                project,
+                build_num
+            )
+        else:
+            endpoint = 'project/{0}/{1}/{2}/{3}/retry'.format(
+                vcs_type,
+                username,
+                project,
+                build_num
+            )
         resp = self._request('POST', endpoint)
         return resp
 

Update retry method to include retry with SSH
We have retry, and we also have retry without cache via the Experimental API. We should also include an option to retry with SSH as [described here](https://circleci.com/docs/api/v1-reference/#retry-build)
diff --git a/tests/circle/test_api.py b/tests/circle/test_api.py
index 347223b..33c0ee0 100644
--- a/tests/circle/test_api.py
+++ b/tests/circle/test_api.py
@@ -92,6 +92,11 @@ class TestCircleCIApi(unittest.TestCase):
 
         self.assertEqual(resp['reponame'], 'MOCK+testing')
 
+        # with SSH
+        resp = json.loads(self.c.retry_build('ccie-tester', 'testing', '1', ssh=True))
+
+        self.assertEqual(resp['reponame'], 'MOCK+testing')
+
     def test_cancel_build(self):
         self.loadMock('mock_cancel_build_response')
         resp = json.loads(self.c.cancel_build('ccie-tester', 'testing', '11'))
@@ -194,6 +199,12 @@ class TestCircleCIApi(unittest.TestCase):
 
         self.assertEqual(resp[0]['path'],'circleci-docs/index.html')
 
+        resp = json.loads(self.c.get_latest_artifact('levlaz', 'circleci-sandbox', 'master'))
+        self.assertEqual(resp[0]['path'],'circleci-docs/index.html')
+
+        with self.assertRaises(InvalidFilterError):
+            self.c.get_latest_artifact('levlaz', 'circleci-sandbox', 'master', 'invalid')
+
     # def test_helper(self):
     #     resp = self.c.get_latest_artifact('circleci', 'circleci-docs')
     #     print(resp)
diff --git a/tests/circle/test_error.py b/tests/circle/test_error.py
index bab58d1..c907ad2 100644
--- a/tests/circle/test_error.py
+++ b/tests/circle/test_error.py
@@ -11,7 +11,7 @@ class TestCircleCIError(unittest.TestCase):
         self.key = BadKeyError('fake')
         self.verb = BadVerbError('fake')
         self.filter = InvalidFilterError('fake', 'status')
-
+        self.afilter = InvalidFilterError('fake', 'artifacts')
     def test_error_implements_str(self):
         self.assertTrue(self.base.__str__ is not object.__str__)
 
@@ -26,5 +26,6 @@ class TestCircleCIError(unittest.TestCase):
         self.assertIn('deploy-key', self.key.message)
 
     def test_filter_message(self):
-        print(self.filter)
-        self.assertIn('running', self.filter.message)
\ No newline at end of file
+        self.assertIn('running', self.filter.message)
+
+        self.assertIn('completed', self.afilter.message)
\ No newline at end of file

pip install -e .
parse_log_pytest
pytest
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi==2025.1.31
chardet==3.0.4
-e git+https://github.com/levlaz/circleci.py.git@873f151b4c378dec7333c68f9f5e5279e0899532#egg=circleci
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
idna==2.6
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pytest @ file:///croot/pytest_1738938843180/work
requests==2.18.4
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
urllib3==1.22

name: circleci.py
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2025.1.31
      - chardet==3.0.4
      - idna==2.6
      - requests==2.18.4
      - urllib3==1.22
prefix: /opt/conda/envs/circleci.py

tests/circle/test_api.py::TestCircleCIApi::test_retry_build
tests/circle/test_api.py::TestCircleCIApi::test_add_envvar tests/circle/test_api.py::TestCircleCIApi::test_add_ssh_user tests/circle/test_api.py::TestCircleCIApi::test_bad_verb tests/circle/test_api.py::TestCircleCIApi::test_cancel_build tests/circle/test_api.py::TestCircleCIApi::test_clear_cache tests/circle/test_api.py::TestCircleCIApi::test_create_checkout_key tests/circle/test_api.py::TestCircleCIApi::test_delete_checkout_key tests/circle/test_api.py::TestCircleCIApi::test_delete_envvar tests/circle/test_api.py::TestCircleCIApi::test_follow_project tests/circle/test_api.py::TestCircleCIApi::test_get_artifacts tests/circle/test_api.py::TestCircleCIApi::test_get_build_info tests/circle/test_api.py::TestCircleCIApi::test_get_checkout_key tests/circle/test_api.py::TestCircleCIApi::test_get_envvar tests/circle/test_api.py::TestCircleCIApi::test_get_latest_artifact tests/circle/test_api.py::TestCircleCIApi::test_get_project_build_summary tests/circle/test_api.py::TestCircleCIApi::test_get_projects tests/circle/test_api.py::TestCircleCIApi::test_get_recent_builds tests/circle/test_api.py::TestCircleCIApi::test_get_test_metadata tests/circle/test_api.py::TestCircleCIApi::test_get_user_info tests/circle/test_api.py::TestCircleCIApi::test_list_checkout_keys tests/circle/test_api.py::TestCircleCIApi::test_list_envvars tests/circle/test_api.py::TestCircleCIApi::test_trigger_build tests/circle/test_error.py::TestCircleCIError::test_error_implements_str tests/circle/test_error.py::TestCircleCIError::test_filter_message tests/circle/test_error.py::TestCircleCIError::test_key_message tests/circle/test_error.py::TestCircleCIError::test_verb_message
circleci/api.py
circleci/api.py