Tapi 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. tapi/__init__.py +2 -0
  2. tapi/api/__init__.py +46 -0
  3. tapi/api/action/__init__.py +7 -0
  4. tapi/api/action/actions.py +106 -0
  5. tapi/api/action/events.py +33 -0
  6. tapi/api/action/logs.py +34 -0
  7. tapi/api/admin/__init__.py +12 -0
  8. tapi/api/admin/action_egress_control_rules.py +87 -0
  9. tapi/api/admin/admin.py +43 -0
  10. tapi/api/admin/ip_access_control.py +76 -0
  11. tapi/api/admin/job.py +42 -0
  12. tapi/api/admin/scim.py +27 -0
  13. tapi/api/admin/template.py +86 -0
  14. tapi/api/admin/user.py +104 -0
  15. tapi/api/audit_log/__init__.py +5 -0
  16. tapi/api/audit_log/audit_logs.py +24 -0
  17. tapi/api/case/__init__.py +20 -0
  18. tapi/api/case/actions.py +90 -0
  19. tapi/api/case/activities.py +35 -0
  20. tapi/api/case/assignees.py +21 -0
  21. tapi/api/case/blocks.py +112 -0
  22. tapi/api/case/cases.py +132 -0
  23. tapi/api/case/comments.py +102 -0
  24. tapi/api/case/fields.py +69 -0
  25. tapi/api/case/files.py +77 -0
  26. tapi/api/case/inputs.py +64 -0
  27. tapi/api/case/linked_cases.py +57 -0
  28. tapi/api/case/metadata.py +65 -0
  29. tapi/api/case/notes.py +78 -0
  30. tapi/api/case/records.py +54 -0
  31. tapi/api/case/subscribers.py +56 -0
  32. tapi/api/credential/__init__.py +1 -0
  33. tapi/api/credential/credentials.py +240 -0
  34. tapi/api/event/__init__.py +1 -0
  35. tapi/api/event/events.py +44 -0
  36. tapi/api/folder/__init__.py +1 -0
  37. tapi/api/folder/folders.py +71 -0
  38. tapi/api/note/__init__.py +5 -0
  39. tapi/api/note/notes.py +76 -0
  40. tapi/api/record/__init__.py +7 -0
  41. tapi/api/record/artifacts.py +17 -0
  42. tapi/api/record/records.py +85 -0
  43. tapi/api/record/types.py +52 -0
  44. tapi/api/report/__init__.py +5 -0
  45. tapi/api/report/reporting.py +41 -0
  46. tapi/api/resource/__init__.py +1 -0
  47. tapi/api/resource/resources.py +152 -0
  48. tapi/api/story/__init__.py +10 -0
  49. tapi/api/story/change_requests.py +64 -0
  50. tapi/api/story/drafts.py +45 -0
  51. tapi/api/story/groups.py +38 -0
  52. tapi/api/story/runs.py +43 -0
  53. tapi/api/story/stories.py +162 -0
  54. tapi/api/story/versions.py +65 -0
  55. tapi/api/team/__init__.py +4 -0
  56. tapi/api/team/members.py +62 -0
  57. tapi/api/team/teams.py +60 -0
  58. tapi/api/tenant.py +68 -0
  59. tapi/client/__init__.py +1 -0
  60. tapi/client/client.py +55 -0
  61. tapi/utils/helpers.py +9 -0
  62. tapi/utils/http.py +8 -0
  63. tapi/utils/testing_decorators.py +5 -0
  64. tapi/utils/types.py +300 -0
  65. tapi-0.1.2.dist-info/METADATA +2487 -0
  66. tapi-0.1.2.dist-info/RECORD +69 -0
  67. tapi-0.1.2.dist-info/WHEEL +5 -0
  68. tapi-0.1.2.dist-info/licenses/LICENSE +674 -0
  69. tapi-0.1.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,152 @@
1
+ from tapi.client import Client
2
+ from typing import Optional, Dict, List, Union, Any, Literal
3
+
4
+
5
+ class ResourcesAPI(Client):
6
+ def __init__(self, domain: str, apiKey: str):
7
+ super().__init__(domain, apiKey)
8
+ self.base_endpoint = "global_resources"
9
+
10
+ def create(
11
+ self,
12
+ name: str,
13
+ value: Union[str, Dict[str, Any], List[Union[int, str, Dict[str, Any]]]],
14
+ team_id: int = None,
15
+ folder_id: Optional[int] = None,
16
+ read_access: Literal["TEAM", "GLOBAL", "SPECIFIC_TEAMS"] = "TEAM",
17
+ shared_team_slugs: Optional[List[str]] = None,
18
+ description: Optional[str] = None,
19
+ live_resource_id: Optional[int] = None,
20
+
21
+ ):
22
+ return self._http_request(
23
+ "POST",
24
+ self.base_endpoint,
25
+ json = {key: value for key, value in locals().items() if value is not None and key != "self"}
26
+ )
27
+
28
+ def get(
29
+ self,
30
+ resource_id: int
31
+ ):
32
+ return self._http_request(
33
+ "GET",
34
+ f"{self.base_endpoint}/{resource_id}"
35
+ )
36
+
37
+ def update(
38
+ self,
39
+ resource_id: int,
40
+ value: Union[str, Dict[str, Any], List[Dict[str, Any]]],
41
+ name: Optional[str] = None,
42
+ folder_id: Optional[int] = None,
43
+ read_access: Optional[Literal["TEAM", "GLOBAL", "SPECIFIC_TEAMS"]] = None,
44
+ shared_team_slugs: Optional[List[str]] = None,
45
+ description: Optional[str] = None,
46
+ test_resource_enabled: Optional[bool] = None,
47
+ is_test: Optional[bool] = None
48
+ ):
49
+ return self._http_request(
50
+ "PUT",
51
+ f"{self.base_endpoint}/{resource_id}",
52
+ json = {key: value for key, value in locals().items()
53
+ if value is not None and key not in ("self", "resource_id")}
54
+ )
55
+
56
+ def list(
57
+ self,
58
+ team_id: Optional[int] = None,
59
+ folder_id: Optional[int] = None,
60
+ per_page: int = 10,
61
+ page: int = 1,
62
+ ):
63
+ return self._http_request(
64
+ "GET",
65
+ self.base_endpoint,
66
+ params = {key: value for key, value in locals().items() if value is not None and key != "self"}
67
+ )
68
+
69
+ def remove_element(
70
+ self,
71
+ resource_id: int,
72
+ key: Optional[str] = None,
73
+ index: Optional[int] = None,
74
+ is_test: Optional[bool] = None
75
+ ):
76
+ if not key and not index:
77
+ raise ValueError("Please specify either 'key' or 'index'.")
78
+ elif key and index:
79
+ raise ValueError("Please specify only one of 'key' or 'index', not both.")
80
+
81
+ return self._http_request(
82
+ "POST",
83
+ f"{self.base_endpoint}/{resource_id}/remove",
84
+ json = {key: value for key, value in locals().items()
85
+ if value is not None and key not in ("self", "resource_id")}
86
+ )
87
+
88
+ def delete(
89
+ self,
90
+ resource_id: int
91
+ ):
92
+ return self._http_request(
93
+ "DELETE",
94
+ f"{self.base_endpoint}/{resource_id}"
95
+ )
96
+
97
+ def append_element(
98
+ self,
99
+ resource_id: int,
100
+ value: Union[str, List],
101
+ is_test: Optional[bool] = None
102
+ ):
103
+ return self._http_request(
104
+ "POST",
105
+ f"{self.base_endpoint}/{resource_id}/append",
106
+ json = {key: value for key, value in locals().items()
107
+ if value is not None and key not in ("self", "resource_id")}
108
+ )
109
+
110
+ def replace_element(
111
+ self,
112
+ resource_id: int,
113
+ value: str,
114
+ key: Optional[str] = None,
115
+ index: Optional[str] = None,
116
+ is_test: Optional[bool] = None
117
+ ):
118
+ if not key and not index:
119
+ raise ValueError("Please specify either 'key' or 'index'.")
120
+ elif key and index:
121
+ raise ValueError("Please specify only one of 'key' or 'index', not both.")
122
+
123
+ return self._http_request(
124
+ "POST",
125
+ f"{self.base_endpoint}/{resource_id}/append",
126
+ json = {key: value for key, value in locals().items()
127
+ if value is not None and key not in ("self", "resource_id")}
128
+ )
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
@@ -0,0 +1,10 @@
1
+ from .runs import RunsAPI
2
+ from .groups import GroupsAPI
3
+ from .drafts import DraftsAPI
4
+ from .stories import StoriesAPI
5
+ from .versions import VersionsAPI
6
+ from .change_requests import ChangeRequestAPI
7
+
8
+ __all__ = [
9
+ "RunsAPI", "StoriesAPI", "VersionsAPI", "ChangeRequestAPI", "GroupsAPI", "DraftsAPI"
10
+ ]
@@ -0,0 +1,64 @@
1
+ from tapi.client import Client
2
+ from typing import Optional
3
+
4
+
5
+ class ChangeRequestAPI(Client):
6
+ def __init__(self, domain: str, apiKey: str):
7
+ super().__init__(domain, apiKey)
8
+ self.base_endpoint = "stories"
9
+
10
+ def create(
11
+ self,
12
+ story_id: int,
13
+ title: Optional[str] = None,
14
+ description: Optional[str] = None
15
+ ):
16
+ return self._http_request(
17
+ "POST",
18
+ f"{self.base_endpoint}/{story_id}/change_request",
19
+ json={key: value for key, value in locals().items() if
20
+ value is not None and key not in ("self", "story_id")}
21
+ )
22
+
23
+ def approve(
24
+ self,
25
+ story_id: int,
26
+ change_request_id: int
27
+ ):
28
+ return self._http_request(
29
+ "POST",
30
+ f"{self.base_endpoint}/{story_id}/change_request/approve",
31
+ json={"change_request_id": change_request_id}
32
+ )
33
+
34
+ def cancel(
35
+ self,
36
+ story_id: int,
37
+ change_request_id: int
38
+ ):
39
+ return self._http_request(
40
+ "POST",
41
+ f"{self.base_endpoint}/{story_id}/change_request/cancel",
42
+ json={"change_request_id": change_request_id}
43
+ )
44
+
45
+ def promote(
46
+ self,
47
+ story_id: int,
48
+ change_request_id: int
49
+ ):
50
+ return self._http_request(
51
+ "POST",
52
+ f"{self.base_endpoint}/{story_id}/change_request/promote",
53
+ json={"change_request_id": change_request_id}
54
+ )
55
+
56
+ def view(
57
+ self,
58
+ story_id: int
59
+ ):
60
+ return self._http_request(
61
+ "GET",
62
+ f"{self.base_endpoint}/{story_id}/change_request/view"
63
+ )
64
+
@@ -0,0 +1,45 @@
1
+ from tapi.client import Client
2
+
3
+
4
+ class DraftsAPI(Client):
5
+ def __init__(self, domain: str, apiKey: str):
6
+ super().__init__(domain, apiKey)
7
+ self.base_endpoint = "stories"
8
+
9
+ def create(
10
+ self,
11
+ story_id: int,
12
+ name: str
13
+ ):
14
+ return self._http_request(
15
+ "POST",
16
+ f"{self.base_endpoint}/{story_id}/drafts",
17
+ json = {
18
+ "name": name
19
+ }
20
+ )
21
+
22
+ def list(
23
+ self,
24
+ story_id: int,
25
+ per_page: int = 10,
26
+ page: int = 1
27
+ ):
28
+ return self._http_request(
29
+ "GET",
30
+ f"{self.base_endpoint}/{story_id}/drafts",
31
+ params = {
32
+ "per_page": per_page,
33
+ "page": page
34
+ }
35
+ )
36
+
37
+ def delete(
38
+ self,
39
+ story_id: int,
40
+ draft_id: int
41
+ ):
42
+ return self._http_request(
43
+ "DELETE",
44
+ f"{self.base_endpoint}/{story_id}/drafts/{draft_id}"
45
+ )
@@ -0,0 +1,38 @@
1
+ from tapi.client import Client
2
+
3
+
4
+ class GroupsAPI(Client):
5
+ def __init__(self, domain: str, apiKey: str):
6
+ super().__init__(domain, apiKey)
7
+ self.base_endpoint = "groups"
8
+
9
+ def list_run_events(
10
+ self,
11
+ group_id: int,
12
+ group_run_guid: str,
13
+ per_page: int = 10,
14
+ page: int = 1
15
+ ):
16
+ return self._http_request(
17
+ "GET",
18
+ f"{self.base_endpoint}/{group_id}/runs/{group_run_guid}",
19
+ params = {
20
+ "page": page,
21
+ "per_page": per_page
22
+ }
23
+ )
24
+
25
+ def list_runs(
26
+ self,
27
+ group_id: int,
28
+ per_page: int = 10,
29
+ page: int = 1
30
+ ):
31
+ return self._http_request(
32
+ "GET",
33
+ f"{self.base_endpoint}/{group_id}/runs",
34
+ params={
35
+ "page": page,
36
+ "per_page": per_page
37
+ }
38
+ )
tapi/api/story/runs.py ADDED
@@ -0,0 +1,43 @@
1
+ from tapi.client import Client
2
+ from datetime import datetime
3
+ from tapi.utils.types import StoryMode
4
+ from typing import Optional, Union
5
+
6
+
7
+ class RunsAPI(Client):
8
+ def __init__(self, domain: str, apiKey: str):
9
+ super().__init__(domain, apiKey)
10
+ self.base_endpoint = "stories"
11
+
12
+ def events(
13
+ self,
14
+ story_id: int,
15
+ story_run_guid: str,
16
+ story_mode: Optional[Union[StoryMode, str]] = None,
17
+ draft_id: Optional[int] = None,
18
+ per_page: int = 10,
19
+ page: int = 1,
20
+ ):
21
+ return self._http_request(
22
+ "GET",
23
+ f"{self.base_endpoint}/{story_id}/runs/{story_run_guid}",
24
+ json={key: value for key, value in locals().items() if
25
+ value is not None and key not in ("self", "story_id", "story_run_guid")}
26
+ )
27
+
28
+ def list(
29
+ self,
30
+ story_id: int,
31
+ story_mode: Optional[Union[StoryMode, str]] = None,
32
+ draft_id: Optional[int] = None,
33
+ since: Optional[Union[datetime, str]] = None,
34
+ until: Optional[Union[datetime, str]] = None,
35
+ per_page: int = 10,
36
+ page: int = 1,
37
+ ):
38
+ return self._http_request(
39
+ "GET",
40
+ f"{self.base_endpoint}/{story_id}/runs",
41
+ json={key: value for key, value in locals().items() if
42
+ value is not None and key not in ("self", "story_id")}
43
+ )
@@ -0,0 +1,162 @@
1
+ from tapi.utils.types import *
2
+ from tapi.client import Client
3
+ from .runs import RunsAPI
4
+ from ..note import NotesAPI
5
+ from .groups import GroupsAPI
6
+ from .drafts import DraftsAPI
7
+ from ..action.actions import ActionsAPI
8
+ from .versions import VersionsAPI
9
+ from .change_requests import ChangeRequestAPI
10
+ from typing import List, Optional, Dict, Any
11
+
12
+
13
+ class StoriesAPI(Client):
14
+ def __init__(self, domain: str, apiKey: str):
15
+ super().__init__(domain, apiKey)
16
+ self.base_endpoint = "stories"
17
+ self.runs = RunsAPI(domain, apiKey)
18
+ self.notes = NotesAPI(domain, apiKey)
19
+ self.groups = GroupsAPI(domain, apiKey)
20
+ self.drafts = DraftsAPI(domain, apiKey)
21
+ self.actions = ActionsAPI(domain, apiKey)
22
+ self.versions = VersionsAPI(domain, apiKey)
23
+ self.change_request = ChangeRequestAPI(domain, apiKey)
24
+
25
+ def create(
26
+ self,
27
+ team_id: int,
28
+ name: Optional[str] = None,
29
+ description: Optional[str] = None,
30
+ keep_events_for: Union[KeepEventsFor, int] = KeepEventsFor.ONE_DAY,
31
+ folder_id: Optional[int] = None,
32
+ tags: Optional[List[str]] = None,
33
+ disabled: bool = False,
34
+ priority: bool = False
35
+ ):
36
+ return self._http_request(
37
+ "POST",
38
+ self.base_endpoint,
39
+ json = {key: value for key, value in locals().items() if value is not None and key != "self"}
40
+ )
41
+
42
+ def get(
43
+ self,
44
+ story_id: int,
45
+ story_mode: Union[StoryMode, str] = StoryMode.ALL,
46
+ draft_id: Optional[int] = None
47
+ ):
48
+ return self._http_request(
49
+ "GET",
50
+ f"{self.base_endpoint}/{story_id}",
51
+ json = {
52
+ "story_mode": story_mode,
53
+ "draft_id": draft_id
54
+ }
55
+ )
56
+
57
+ def update(
58
+ self,
59
+ story_id: int,
60
+ name: Optional[str] = None,
61
+ description: Optional[str] = None,
62
+ add_tag_names: Optional[List[str]] = None,
63
+ remove_tag_names: Optional[List[str]] = None,
64
+ keep_events_for: Optional[Union[KeepEventsFor, str]] = None,
65
+ disabled: Optional[bool] = None,
66
+ locked: Optional[bool] = None,
67
+ priority: Optional[bool] = None,
68
+ webhook_api_enabled: Optional[bool] = None,
69
+ send_to_story_access_source: Optional[Union[SendToStoryAccessSource, str]] = None,
70
+ send_to_story_access: Optional[Union[SendToStoryAccess, str]] = None,
71
+ shared_team_slugs: Optional[List[str]] = None,
72
+ send_to_story_skill_use_requires_confirmation: Optional[bool] = None,
73
+ api_entry_action_id: Optional[int] = None,
74
+ api_exit_action_ids: Optional[int] = None,
75
+ team_id: Optional[int] = None,
76
+ folder_id: Optional[int] = None,
77
+ change_control_enabled: Optional[bool] = None,
78
+ draft_id: Optional[int] = None,
79
+ monitor_failures: Optional[bool] = None
80
+
81
+ ):
82
+ return self._http_request(
83
+ "PUT",
84
+ f"{self.base_endpoint}/{story_id}",
85
+ json = {key: value for key, value in locals().items() if value is not None and key not in ("self", "story_id")}
86
+ )
87
+
88
+ def list(
89
+ self,
90
+ team_id: Optional[int] = None,
91
+ folder_id: Optional[int] = None,
92
+ tags: Optional[List[str]] = None,
93
+ search: Optional[str] = None,
94
+ filter: Optional[Union[Filter, str]] = None,
95
+ order: Optional[Union[StoriesReturnOrder, str]] = None,
96
+ per_page: int = 10,
97
+ page: int = 1
98
+ ):
99
+ return self._http_request(
100
+ "GET",
101
+ self.base_endpoint,
102
+ json = {key: value for key, value in locals().items() if value is not None and key != "self"}
103
+ )
104
+
105
+ def delete(
106
+ self,
107
+ story_id: int
108
+ ):
109
+ return self._http_request(
110
+ "DELETE",
111
+ f"{self.base_endpoint}/{story_id}"
112
+ )
113
+
114
+ def batch_delete(
115
+ self,
116
+ story_ids: List[int]
117
+ ):
118
+ return self._http_request(
119
+ "DELETE",
120
+ f"{self.base_endpoint}/batch",
121
+ json = {"ids": story_ids}
122
+ )
123
+
124
+ def export(
125
+ self,
126
+ story_id: int,
127
+ randomize_urls: Optional[bool] = True,
128
+ draft_id: Optional[int] = None,
129
+ ):
130
+ return self._http_request(
131
+ "GET",
132
+ f"{self.base_endpoint}/{story_id}/export",
133
+ json = {
134
+ "randomize_urls": randomize_urls,
135
+ "draft_id": draft_id
136
+ }
137
+ )
138
+
139
+ def import_(
140
+ self,
141
+ new_name: str,
142
+ data: Dict[str, Any],
143
+ team_id: int,
144
+ folder_id: Optional[int] = None,
145
+ mode: Union[Mode, str] = Mode.NEW
146
+ ):
147
+ return self._http_request(
148
+ "POST",
149
+ f"{self.base_endpoint}/import",
150
+ json = {key: value for key, value in locals().items() if value is not None and key != "self"}
151
+ )
152
+
153
+ def disable(
154
+ self,
155
+ id: int,
156
+ disabled: bool
157
+ ):
158
+ return self._http_request(
159
+ "POST",
160
+ f"{self.base_endpoint}/{id}/disable",
161
+ json = {"disabled": disabled}
162
+ )
@@ -0,0 +1,65 @@
1
+ from tapi.client import Client
2
+ from typing import Optional
3
+
4
+
5
+ class VersionsAPI(Client):
6
+ def __init__(self, domain: str, apiKey: str):
7
+ super().__init__(domain, apiKey)
8
+ self.base_endpoint = "stories"
9
+
10
+ def create(
11
+ self,
12
+ story_id: int,
13
+ name: Optional[str] = None
14
+ ):
15
+ return self._http_request(
16
+ "POST",
17
+ f"{self.base_endpoint}/{story_id}/versions",
18
+ json={key: value for key, value in locals().items() if
19
+ value is not None and key not in ("self", "story_id")}
20
+ )
21
+
22
+ def get(
23
+ self,
24
+ story_id: int,
25
+ version_id: int
26
+ ):
27
+ return self._http_request(
28
+ "GET",
29
+ f"{self.base_endpoint}/{story_id}/versions/{version_id}"
30
+ )
31
+
32
+ def update(
33
+ self,
34
+ name: str,
35
+ story_id: int,
36
+ version_id: int
37
+ ):
38
+ return self._http_request(
39
+ "POST",
40
+ f"{self.base_endpoint}/{story_id}/versions/{version_id}",
41
+ json={"name": name}
42
+ )
43
+
44
+ def list(
45
+ self,
46
+ story_id: int,
47
+ per_page: int = 10,
48
+ page: int = 1,
49
+ ):
50
+ return self._http_request(
51
+ "GET",
52
+ f"{self.base_endpoint}/{story_id}/versions",
53
+ json={key: value for key, value in locals().items() if
54
+ value is not None and key not in ("self", "story_id")}
55
+ )
56
+
57
+ def delete(
58
+ self,
59
+ story_id: int,
60
+ version_id: int
61
+ ):
62
+ return self._http_request(
63
+ "DELETE",
64
+ f"{self.base_endpoint}/{story_id}/versions/{version_id}"
65
+ )
@@ -0,0 +1,4 @@
1
+ from .members import MembersAPI
2
+ from .teams import TeamsAPI
3
+
4
+ __all__ = ["TeamsAPI", "MembersAPI"]
@@ -0,0 +1,62 @@
1
+ from tapi.utils.types import Role
2
+ from tapi.client import Client
3
+ from typing import Optional, Union
4
+
5
+
6
+ class MembersAPI(Client):
7
+ def __init__(self, domain: str, apiKey: str):
8
+ super().__init__(domain, apiKey)
9
+ self.base_endpoint = "teams"
10
+
11
+ def list(
12
+ self,
13
+ team_id: int,
14
+ per_page: int = 10,
15
+ page: int = 1,
16
+ ):
17
+ return self._http_request(
18
+ "GET",
19
+ f"{self.base_endpoint}/{team_id}/members",
20
+ json = {key: value for key, value in locals().items() if value is not None and key not in ("self", "team_id")}
21
+ )
22
+
23
+ def remove(
24
+ self,
25
+ team_id: int,
26
+ user_id: int
27
+ ):
28
+ return self._http_request(
29
+ "POST",
30
+ f"{self.base_endpoint}/{team_id}/remove_member",
31
+ json = {"user_id": user_id}
32
+ )
33
+
34
+ def invite(
35
+ self,
36
+ team_id: int,
37
+ email: Optional[str] = None,
38
+ user_id: Optional[int] = None,
39
+ role: Union[Role, str] = Role.VIEWER
40
+ ):
41
+ if email and user_id:
42
+ raise ValueError("Invalid input: Provide either 'email' or 'user_id', not both.")
43
+
44
+ if not email and not user_id:
45
+ raise ValueError("Invalid input: You must provide at least one of 'email' or 'user_id'.")
46
+
47
+ return self._http_request(
48
+ "POST",
49
+ f"{self.base_endpoint}/{team_id}/invite_member",
50
+ json={key: value for key, value in locals().items() if value is not None and key not in ("self", "team_id")}
51
+ )
52
+
53
+ def resend_invite(
54
+ self,
55
+ team_id: int,
56
+ user_id: Optional[int] = None,
57
+ ):
58
+ return self._http_request(
59
+ "POST",
60
+ f"{self.base_endpoint}/{team_id}/resend_invitation",
61
+ json = {"user_id": user_id}
62
+ )