vobiz-python 0.1.0__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 (63) hide show
  1. vobiz/__init__.py +4 -0
  2. vobiz/base.py +237 -0
  3. vobiz/exceptions.py +34 -0
  4. vobiz/resources/__init__.py +12 -0
  5. vobiz/resources/accounts.py +59 -0
  6. vobiz/resources/applications.py +138 -0
  7. vobiz/resources/calls_vobiz.py +206 -0
  8. vobiz/resources/cdrs.py +46 -0
  9. vobiz/resources/credentials.py +104 -0
  10. vobiz/resources/endpoints.py +101 -0
  11. vobiz/resources/ip_access_control_lists.py +100 -0
  12. vobiz/resources/numbers.py +134 -0
  13. vobiz/resources/origination_uris.py +109 -0
  14. vobiz/resources/recordings.py +91 -0
  15. vobiz/resources/sip_trunks.py +99 -0
  16. vobiz/resources/subaccounts.py +101 -0
  17. vobiz/rest/__init__.py +2 -0
  18. vobiz/rest/client.py +277 -0
  19. vobiz/utils/__init__.py +72 -0
  20. vobiz/utils/interactive.py +50 -0
  21. vobiz/utils/jwt.py +97 -0
  22. vobiz/utils/location.py +6 -0
  23. vobiz/utils/signature_v3.py +111 -0
  24. vobiz/utils/template.py +50 -0
  25. vobiz/utils/validators.py +280 -0
  26. vobiz/version.py +2 -0
  27. vobiz/xml/ConferenceElement.py +485 -0
  28. vobiz/xml/DTMFElement.py +41 -0
  29. vobiz/xml/DialElement.py +371 -0
  30. vobiz/xml/MultiPartyCallElement.py +711 -0
  31. vobiz/xml/ResponseElement.py +414 -0
  32. vobiz/xml/VobizXMLElement.py +48 -0
  33. vobiz/xml/__init__.py +31 -0
  34. vobiz/xml/breakElement.py +62 -0
  35. vobiz/xml/contElement.py +190 -0
  36. vobiz/xml/emphasisElement.py +174 -0
  37. vobiz/xml/getDigitsElement.py +294 -0
  38. vobiz/xml/getInputElement.py +369 -0
  39. vobiz/xml/hangupElement.py +57 -0
  40. vobiz/xml/langElement.py +197 -0
  41. vobiz/xml/messageElement.py +115 -0
  42. vobiz/xml/numberElement.py +77 -0
  43. vobiz/xml/pElement.py +164 -0
  44. vobiz/xml/phonemeElement.py +62 -0
  45. vobiz/xml/playElement.py +41 -0
  46. vobiz/xml/preAnswerElement.py +148 -0
  47. vobiz/xml/prosodyElement.py +227 -0
  48. vobiz/xml/recordElement.py +337 -0
  49. vobiz/xml/redirectElement.py +42 -0
  50. vobiz/xml/sElement.py +154 -0
  51. vobiz/xml/sayAsElement.py +61 -0
  52. vobiz/xml/speakElement.py +249 -0
  53. vobiz/xml/streamElement.py +123 -0
  54. vobiz/xml/subElement.py +43 -0
  55. vobiz/xml/userElement.py +79 -0
  56. vobiz/xml/wElement.py +144 -0
  57. vobiz/xml/waitElement.py +93 -0
  58. vobiz/xml/xmlUtils.py +6 -0
  59. vobiz_python-0.1.0.dist-info/METADATA +640 -0
  60. vobiz_python-0.1.0.dist-info/RECORD +63 -0
  61. vobiz_python-0.1.0.dist-info/WHEEL +5 -0
  62. vobiz_python-0.1.0.dist-info/licenses/LICENSE.txt +19 -0
  63. vobiz_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,46 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
4
+
5
+
6
+ class CDRs:
7
+ """
8
+ Vobiz Call Detail Records (CDRs) resource.
9
+
10
+ Endpoint: https://api.vobiz.ai/api/v1/account/{account_id}/cdr
11
+ """
12
+
13
+ def __init__(self, client):
14
+ self.client = client
15
+
16
+ @property
17
+ def _account_id(self) -> str:
18
+ return self.client.auth_id
19
+
20
+ def list(
21
+ self,
22
+ page: Optional[int] = None,
23
+ per_page: Optional[int] = None,
24
+ start_date: Optional[str] = None,
25
+ end_date: Optional[str] = None,
26
+ **filters: Any,
27
+ ):
28
+ """
29
+ GET /api/v1/account/{account_id}/cdr
30
+ """
31
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/cdr"
32
+ params: Dict[str, Any] = {}
33
+ if page is not None:
34
+ params["page"] = page
35
+ if per_page is not None:
36
+ params["per_page"] = per_page
37
+ if start_date is not None:
38
+ params["start_date"] = start_date
39
+ if end_date is not None:
40
+ params["end_date"] = end_date
41
+ params.update(filters)
42
+
43
+ resp = self.client.session.get(
44
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
45
+ )
46
+ return self.client.process_response("GET", resp)
@@ -0,0 +1,104 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
4
+
5
+
6
+ class Credentials:
7
+ """
8
+ Vobiz SIP Credentials resource.
9
+
10
+ All endpoints are scoped to the authenticated account.
11
+ """
12
+
13
+ def __init__(self, client):
14
+ self.client = client
15
+
16
+ @property
17
+ def _account_id(self) -> str:
18
+ # For Vobiz, we treat the RestClient auth_id as the account_id
19
+ return self.client.auth_id
20
+
21
+ def create(
22
+ self,
23
+ username: str,
24
+ password: str,
25
+ enabled: Optional[bool] = None,
26
+ description: Optional[str] = None,
27
+ **extra: Any,
28
+ ):
29
+ """
30
+ POST /api/v1/account/{account_id}/credentials
31
+
32
+ Create a new SIP credential (username/password) for the account.
33
+ """
34
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/credentials"
35
+ body: Dict[str, Any] = {
36
+ "username": username,
37
+ "password": password,
38
+ }
39
+ if enabled is not None:
40
+ body["enabled"] = enabled
41
+ if description is not None:
42
+ body["description"] = description
43
+ body.update(extra)
44
+
45
+ resp = self.client.session.post(
46
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
47
+ )
48
+ return self.client.process_response("POST", resp)
49
+
50
+ def list(
51
+ self,
52
+ limit: Optional[int] = None,
53
+ offset: Optional[int] = None,
54
+ **filters: Any,
55
+ ):
56
+ """
57
+ GET /api/v1/account/{account_id}/trunks/credentials
58
+
59
+ Retrieve a paginated list of all credentials associated with the account.
60
+ """
61
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/trunks/credentials"
62
+ params: Dict[str, Any] = {}
63
+ if limit is not None:
64
+ params["limit"] = limit
65
+ if offset is not None:
66
+ params["offset"] = offset
67
+ params.update(filters)
68
+
69
+ resp = self.client.session.get(
70
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
71
+ )
72
+ return self.client.process_response("GET", resp)
73
+
74
+ def get(self, credential_id: str):
75
+ """
76
+ GET /api/v1/account/{account_id}/credentials/{credential_id}
77
+ """
78
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/credentials/{credential_id}"
79
+ resp = self.client.session.get(
80
+ url, timeout=self.client.timeout, proxies=self.client.proxies
81
+ )
82
+ return self.client.process_response("GET", resp)
83
+
84
+ def update(self, credential_id: str, **params: Any):
85
+ """
86
+ PUT /api/v1/account/{account_id}/credentials/{credential_id}
87
+ """
88
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/credentials/{credential_id}"
89
+ body: Dict[str, Any] = dict(params)
90
+ resp = self.client.session.put(
91
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
92
+ )
93
+ return self.client.process_response("PUT", resp)
94
+
95
+ def delete(self, credential_id: str):
96
+ """
97
+ DELETE /api/v1/account/{account_id}/credentials/{credential_id}
98
+ """
99
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/credentials/{credential_id}"
100
+ resp = self.client.session.delete(
101
+ url, timeout=self.client.timeout, proxies=self.client.proxies
102
+ )
103
+ return self.client.process_response("DELETE", resp)
104
+
@@ -0,0 +1,101 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+
4
+ class Endpoints:
5
+ """
6
+ Vobiz Endpoints (SIP endpoints / devices) resource.
7
+
8
+ Uses the `/v1/Account/{auth_id}/Endpoint/...` paths described in the
9
+ Vobiz endpoint documentation.
10
+ """
11
+
12
+ def __init__(self, client):
13
+ self.client = client
14
+
15
+ def create(
16
+ self,
17
+ username: str,
18
+ password: str,
19
+ alias: Optional[str] = None,
20
+ application: Optional[str] = None,
21
+ **extra: Any,
22
+ ):
23
+ """
24
+ POST /v1/Account/{auth_id}/Endpoint/
25
+
26
+ Create a new SIP endpoint.
27
+ """
28
+ body: Dict[str, Any] = {
29
+ "username": username,
30
+ "password": password,
31
+ }
32
+ if alias is not None:
33
+ body["alias"] = alias
34
+ if application is not None:
35
+ body["application"] = application
36
+ body.update(extra)
37
+
38
+ return self.client.request(
39
+ "POST",
40
+ ("Endpoint",),
41
+ data=body,
42
+ )
43
+
44
+ def list(
45
+ self,
46
+ limit: Optional[int] = None,
47
+ offset: Optional[int] = None,
48
+ **filters: Any,
49
+ ):
50
+ """
51
+ GET /v1/Account/{auth_id}/Endpoint/
52
+
53
+ Retrieve a paginated list of all SIP endpoints in the account.
54
+ """
55
+ params: Dict[str, Any] = {}
56
+ if limit is not None:
57
+ params["limit"] = limit
58
+ if offset is not None:
59
+ params["offset"] = offset
60
+ params.update(filters)
61
+
62
+ return self.client.request(
63
+ "GET",
64
+ ("Endpoint",),
65
+ data=params,
66
+ )
67
+
68
+ def get(self, endpoint_id: str):
69
+ """
70
+ GET /v1/Account/{auth_id}/Endpoint/{endpoint_id}/
71
+
72
+ Retrieve details for a specific endpoint.
73
+ """
74
+ return self.client.request(
75
+ "GET",
76
+ ("Endpoint", endpoint_id),
77
+ )
78
+
79
+ def update(self, endpoint_id: str, **params: Any):
80
+ """
81
+ POST /v1/Account/{auth_id}/Endpoint/{endpoint_id}/
82
+
83
+ Update an endpoint's password, alias, application, or permissions.
84
+ """
85
+ body: Dict[str, Any] = dict(params)
86
+ return self.client.request(
87
+ "POST",
88
+ ("Endpoint", endpoint_id),
89
+ data=body,
90
+ )
91
+
92
+ def delete(self, endpoint_id: str):
93
+ """
94
+ DELETE /v1/Account/{auth_id}/Endpoint/{endpoint_id}/
95
+
96
+ Delete an endpoint. On success, the API returns 204 No Content.
97
+ """
98
+ return self.client.request(
99
+ "DELETE",
100
+ ("Endpoint", endpoint_id),
101
+ )
@@ -0,0 +1,100 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
4
+
5
+
6
+ class IpAccessControlLists:
7
+ """
8
+ Vobiz IP Access Control Lists resource.
9
+
10
+ All endpoints are scoped to the authenticated account.
11
+ """
12
+
13
+ def __init__(self, client):
14
+ self.client = client
15
+
16
+ @property
17
+ def _account_id(self) -> str:
18
+ # For Vobiz, we treat the RestClient auth_id as the account_id
19
+ return self.client.auth_id
20
+
21
+ def create(
22
+ self,
23
+ ip_address: str,
24
+ description: Optional[str] = None,
25
+ enabled: Optional[bool] = None,
26
+ **extra: Any,
27
+ ):
28
+ """
29
+ POST /api/v1/account/{account_id}/ip-acl
30
+
31
+ Create a new IP ACL entry.
32
+ """
33
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/ip-acl"
34
+ body: Dict[str, Any] = {"ip_address": ip_address}
35
+ if description is not None:
36
+ body["description"] = description
37
+ if enabled is not None:
38
+ body["enabled"] = enabled
39
+ body.update(extra)
40
+
41
+ resp = self.client.session.post(
42
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
43
+ )
44
+ return self.client.process_response("POST", resp)
45
+
46
+ def list(
47
+ self,
48
+ limit: Optional[int] = None,
49
+ offset: Optional[int] = None,
50
+ **filters: Any,
51
+ ):
52
+ """
53
+ GET /api/v1/account/{account_id}/trunks/ip-acl
54
+
55
+ Retrieve a paginated list of all IP ACL entries.
56
+ """
57
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/trunks/ip-acl"
58
+ params: Dict[str, Any] = {}
59
+ if limit is not None:
60
+ params["limit"] = limit
61
+ if offset is not None:
62
+ params["offset"] = offset
63
+ params.update(filters)
64
+
65
+ resp = self.client.session.get(
66
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
67
+ )
68
+ return self.client.process_response("GET", resp)
69
+
70
+ def get(self, acl_id: str):
71
+ """
72
+ GET /api/v1/account/{account_id}/ip-acl/{ip_acl_id}
73
+ """
74
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/ip-acl/{acl_id}"
75
+ resp = self.client.session.get(
76
+ url, timeout=self.client.timeout, proxies=self.client.proxies
77
+ )
78
+ return self.client.process_response("GET", resp)
79
+
80
+ def update(self, acl_id: str, **params: Any):
81
+ """
82
+ PUT /api/v1/account/{account_id}/ip-acl/{ip_acl_id}
83
+ """
84
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/ip-acl/{acl_id}"
85
+ body: Dict[str, Any] = dict(params)
86
+ resp = self.client.session.put(
87
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
88
+ )
89
+ return self.client.process_response("PUT", resp)
90
+
91
+ def delete(self, acl_id: str):
92
+ """
93
+ DELETE /api/v1/account/{account_id}/ip-acl/{ip_acl_id}
94
+ """
95
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/ip-acl/{acl_id}"
96
+ resp = self.client.session.delete(
97
+ url, timeout=self.client.timeout, proxies=self.client.proxies
98
+ )
99
+ return self.client.process_response("DELETE", resp)
100
+
@@ -0,0 +1,134 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
4
+
5
+
6
+ class PhoneNumbers:
7
+ """
8
+ Vobiz Phone Numbers resource.
9
+
10
+ Implements inventory listing, purchase from inventory, and release,
11
+ as defined in the Vobiz phone number endpoints.
12
+ """
13
+
14
+ def __init__(self, client):
15
+ self.client = client
16
+
17
+ @property
18
+ def _account_id(self) -> str:
19
+ # For Vobiz, we treat the RestClient auth_id as the account_id
20
+ return self.client.auth_id
21
+
22
+ def list(
23
+ self,
24
+ page: Optional[int] = None,
25
+ per_page: Optional[int] = None,
26
+ include_subaccounts: Optional[bool] = None,
27
+ **filters: Any,
28
+ ):
29
+ """
30
+ GET /api/v1/account/{auth_id}/numbers
31
+
32
+ List all phone numbers purchased and assigned to this account.
33
+ include_subaccounts: if True, also returns numbers from sub-accounts (master accounts only).
34
+ """
35
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/numbers"
36
+ params: Dict[str, Any] = {}
37
+ if page is not None:
38
+ params["page"] = page
39
+ if per_page is not None:
40
+ params["per_page"] = per_page
41
+ if include_subaccounts is not None:
42
+ params["include_subaccounts"] = include_subaccounts
43
+ params.update(filters)
44
+
45
+ resp = self.client.session.get(
46
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
47
+ )
48
+ return self.client.process_response("GET", resp)
49
+
50
+ def list_inventory( self,
51
+ country: Optional[str] = None,
52
+ page: Optional[int] = None,
53
+ per_page: Optional[int] = None,
54
+ **filters: Any,
55
+ ):
56
+ """
57
+ GET /api/v1/account/{auth_id}/inventory/numbers
58
+
59
+ Browse available phone numbers in inventory that are not assigned
60
+ to any account (auth_id IS NULL, status='active').
61
+ """
62
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/inventory/numbers"
63
+ params: Dict[str, Any] = {}
64
+ if country is not None:
65
+ params["country"] = country
66
+ if page is not None:
67
+ params["page"] = page
68
+ if per_page is not None:
69
+ params["per_page"] = per_page
70
+ params.update(filters)
71
+
72
+ resp = self.client.session.get(
73
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
74
+ )
75
+ return self.client.process_response("GET", resp)
76
+
77
+ def purchase_from_inventory(
78
+ self,
79
+ e164: str,
80
+ currency: Optional[str] = None,
81
+ **extra: Any,
82
+ ):
83
+ """
84
+ POST /api/v1/account/{auth_id}/numbers/purchase-from-inventory
85
+
86
+ Purchase a phone number from inventory and assign it to the account.
87
+ """
88
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/numbers/purchase-from-inventory"
89
+ body: Dict[str, Any] = {"e164": e164}
90
+ if currency is not None:
91
+ body["currency"] = currency
92
+ body.update(extra)
93
+
94
+ resp = self.client.session.post(
95
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
96
+ )
97
+ return self.client.process_response("POST", resp)
98
+
99
+ def release(self, e164_number: str):
100
+ """
101
+ DELETE /api/v1/account/{auth_id}/numbers/{e164_number}
102
+
103
+ Release a phone number from the account back to inventory.
104
+ """
105
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/numbers/{e164_number}"
106
+ resp = self.client.session.delete(
107
+ url, timeout=self.client.timeout, proxies=self.client.proxies
108
+ )
109
+ return self.client.process_response("DELETE", resp)
110
+
111
+ def assign_to_trunk(self, e164_number: str, trunk_group_id: str):
112
+ """
113
+ POST /api/v1/account/{account_id}/numbers/{PHONE_NUMBER}/assign
114
+
115
+ Assign a phone number to a SIP trunk.
116
+ """
117
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/numbers/{e164_number}/assign"
118
+ body: Dict[str, Any] = {"trunk_group_id": trunk_group_id}
119
+ resp = self.client.session.post(
120
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
121
+ )
122
+ return self.client.process_response("POST", resp)
123
+
124
+ def unassign_from_trunk(self, e164_number: str):
125
+ """
126
+ DELETE /api/v1/account/{account_id}/numbers/{PHONE_NUMBER}/assign
127
+
128
+ Unassign a phone number from its SIP trunk.
129
+ """
130
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/numbers/{e164_number}/assign"
131
+ resp = self.client.session.delete(
132
+ url, timeout=self.client.timeout, proxies=self.client.proxies
133
+ )
134
+ return self.client.process_response("DELETE", resp)
@@ -0,0 +1,109 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
4
+
5
+
6
+ class OriginationUris:
7
+ """
8
+ Vobiz Origination URIs resource.
9
+
10
+ Implements create, list, update, and delete operations using the
11
+ `/api/v1/account/{account_id}/origination-uris` and
12
+ `/api/v1/account/{account_id}/trunks/origination-uris` endpoints.
13
+ """
14
+
15
+ def __init__(self, client):
16
+ self.client = client
17
+
18
+ @property
19
+ def _account_id(self) -> str:
20
+ # For Vobiz, we treat the RestClient auth_id as the account_id
21
+ return self.client.auth_id
22
+
23
+ def create(
24
+ self,
25
+ uri: str,
26
+ priority: Optional[int] = None,
27
+ weight: Optional[int] = None,
28
+ enabled: Optional[bool] = None,
29
+ **extra: Any,
30
+ ):
31
+ """
32
+ POST /api/v1/account/{account_id}/origination-uris
33
+
34
+ Create a new origination URI for outbound routing.
35
+ """
36
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/origination-uris"
37
+ body: Dict[str, Any] = {"uri": uri}
38
+ if priority is not None:
39
+ body["priority"] = priority
40
+ if weight is not None:
41
+ body["weight"] = weight
42
+ if enabled is not None:
43
+ body["enabled"] = enabled
44
+ body.update(extra)
45
+
46
+ resp = self.client.session.post(
47
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
48
+ )
49
+ return self.client.process_response("POST", resp)
50
+
51
+ def list(
52
+ self,
53
+ trunk_id: Optional[str] = None,
54
+ limit: Optional[int] = None,
55
+ offset: Optional[int] = None,
56
+ **filters: Any,
57
+ ):
58
+ """
59
+ GET /api/v1/account/{account_id}/trunks/origination-uris
60
+
61
+ Retrieve a paginated list of origination URIs.
62
+ Optionally filter by trunk_id.
63
+ """
64
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/trunks/origination-uris"
65
+ params: Dict[str, Any] = {}
66
+ if trunk_id is not None:
67
+ params["trunk_id"] = trunk_id
68
+ if limit is not None:
69
+ params["limit"] = limit
70
+ if offset is not None:
71
+ params["offset"] = offset
72
+ params.update(filters)
73
+
74
+ resp = self.client.session.get(
75
+ url, params=params, timeout=self.client.timeout, proxies=self.client.proxies
76
+ )
77
+ return self.client.process_response("GET", resp)
78
+
79
+ def get(self, uri_id: str):
80
+ """
81
+ GET /api/v1/account/{account_id}/origination-uris/{uri_id}
82
+ """
83
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/origination-uris/{uri_id}"
84
+ resp = self.client.session.get(
85
+ url, timeout=self.client.timeout, proxies=self.client.proxies
86
+ )
87
+ return self.client.process_response("GET", resp)
88
+
89
+ def update(self, uri_id: str, **params: Any):
90
+ """
91
+ PUT /api/v1/account/{account_id}/origination-uris/{uri_id}
92
+ """
93
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/origination-uris/{uri_id}"
94
+ body: Dict[str, Any] = dict(params)
95
+ resp = self.client.session.put(
96
+ url, json=body, timeout=self.client.timeout, proxies=self.client.proxies
97
+ )
98
+ return self.client.process_response("PUT", resp)
99
+
100
+ def delete(self, uri_id: str):
101
+ """
102
+ DELETE /api/v1/account/{account_id}/origination-uris/{uri_id}
103
+ """
104
+ url = f"{VOBIZ_API_V1}/account/{self._account_id}/origination-uris/{uri_id}"
105
+ resp = self.client.session.delete(
106
+ url, timeout=self.client.timeout, proxies=self.client.proxies
107
+ )
108
+ return self.client.process_response("DELETE", resp)
109
+
@@ -0,0 +1,91 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+
4
+ class Recordings:
5
+ """
6
+ Vobiz Recordings resource.
7
+
8
+ Endpoint: https://api.vobiz.ai/api/v1/Account/{auth_id}/Recording/
9
+ """
10
+
11
+ def __init__(self, client):
12
+ self.client = client
13
+
14
+ def list(
15
+ self,
16
+ limit: Optional[int] = None,
17
+ offset: Optional[int] = None,
18
+ call_uuid: Optional[str] = None,
19
+ recording_type: Optional[str] = None,
20
+ **filters: Any,
21
+ ):
22
+ """
23
+ GET /api/v1/Account/{auth_id}/Recording/
24
+ """
25
+ params: Dict[str, Any] = {}
26
+ if limit is not None:
27
+ params["limit"] = limit
28
+ if offset is not None:
29
+ params["offset"] = offset
30
+ if call_uuid is not None:
31
+ params["call_uuid"] = call_uuid
32
+ if recording_type is not None:
33
+ params["recording_type"] = recording_type
34
+ params.update(filters)
35
+
36
+ return self.client.request("GET", ("Recording",), data=params)
37
+
38
+ def get(self, recording_id: str):
39
+ """
40
+ GET /api/v1/Account/{auth_id}/Recording/{recording_id}/
41
+ """
42
+ return self.client.request("GET", ("Recording", recording_id))
43
+
44
+ def delete(self, recording_id: str):
45
+ """
46
+ DELETE /api/v1/Account/{auth_id}/Recording/{recording_id}/
47
+ """
48
+ return self.client.request("DELETE", ("Recording", recording_id))
49
+
50
+ def export(self, recipient_emails: list, **filters: Any):
51
+ """
52
+ POST /api/v1/Account/{auth_id}/export/recording/
53
+
54
+ Async export — recordings matching filters are packaged and emailed.
55
+ recipient_emails: list of email addresses to receive the download link.
56
+
57
+ Date range filters (use one or the other, not both):
58
+ from_date / to_date — e.g. "2025-01-01 00:00:00"
59
+ recording_storage_duration — exact days old
60
+ recording_storage_duration__gte / __lte — range of days old
61
+
62
+ Optional additional filters (only for ranges <= 30 days):
63
+ from_number, to_number, conference_name, recording_format ("mp3"/"wav")
64
+ """
65
+ VOBIZ_API_V1 = "https://api.vobiz.ai/api/v1"
66
+ url = f"{VOBIZ_API_V1}/Account/{self.client.auth_id}/export/recording/"
67
+ body: Dict[str, Any] = {
68
+ "recipient": {"customer_account": recipient_emails}
69
+ }
70
+ body.update(filters)
71
+ resp = self.client.session.post(
72
+ url, json=body,
73
+ timeout=self.client.timeout,
74
+ proxies=self.client.proxies,
75
+ )
76
+ return self.client.process_response("POST", resp)
77
+
78
+ def bulk_delete(self, **filters: Any):
79
+ """
80
+ DELETE /api/v1/Account/{auth_id}/Recording/BulkDelete/
81
+
82
+ Async bulk delete — permanently removes all recordings matching filters.
83
+ At least one filter is recommended to avoid deleting everything.
84
+
85
+ Filter params (as query string kwargs):
86
+ add_time__gte / add_time__lte — "YYYY-MM-DD HH:MM:SS"
87
+ conference_name, recording_format, from_number, to_number
88
+ """
89
+ return self.client.request(
90
+ "DELETE", ("Recording", "BulkDelete"), data=filters
91
+ )