hooksniff-python 0.4.2__tar.gz → 0.4.3__tar.gz

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 (34) hide show
  1. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/PKG-INFO +4 -4
  2. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/README.md +3 -3
  3. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/hooksniff/__init__.py +1 -1
  4. hooksniff_python-0.4.3/hooksniff/resources/__init__.py +58 -0
  5. hooksniff_python-0.4.3/hooksniff/resources/advanced.py +66 -0
  6. hooksniff_python-0.4.3/hooksniff/resources/alert.py +30 -0
  7. hooksniff_python-0.4.3/hooksniff/resources/analytics.py +18 -0
  8. hooksniff_python-0.4.3/hooksniff/resources/api_key.py +21 -0
  9. hooksniff_python-0.4.3/hooksniff/resources/application.py +27 -0
  10. hooksniff_python-0.4.3/hooksniff/resources/billing.py +24 -0
  11. hooksniff_python-0.4.3/hooksniff/resources/broadcast.py +27 -0
  12. hooksniff_python-0.4.3/hooksniff/resources/connector.py +32 -0
  13. hooksniff_python-0.4.3/hooksniff/resources/cortex.py +43 -0
  14. hooksniff_python-0.4.3/hooksniff/resources/endpoint.py +31 -0
  15. hooksniff_python-0.4.3/hooksniff/resources/health.py +15 -0
  16. hooksniff_python-0.4.3/hooksniff/resources/notification.py +22 -0
  17. hooksniff_python-0.4.3/hooksniff/resources/platform.py +28 -0
  18. hooksniff_python-0.4.3/hooksniff/resources/routing.py +20 -0
  19. hooksniff_python-0.4.3/hooksniff/resources/schema.py +25 -0
  20. hooksniff_python-0.4.3/hooksniff/resources/search.py +12 -0
  21. hooksniff_python-0.4.3/hooksniff/resources/stream.py +41 -0
  22. hooksniff_python-0.4.3/hooksniff/resources/team.py +33 -0
  23. hooksniff_python-0.4.3/hooksniff/resources/template.py +28 -0
  24. hooksniff_python-0.4.3/hooksniff/resources/transform.py +24 -0
  25. hooksniff_python-0.4.3/hooksniff/resources/webhook.py +34 -0
  26. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/hooksniff/webhook.py +1 -1
  27. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/pyproject.toml +1 -1
  28. hooksniff_python-0.4.2/hooksniff/resources.py +0 -450
  29. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/.gitignore +0 -0
  30. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/LICENSE +0 -0
  31. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/hooksniff/client.py +0 -0
  32. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/hooksniff/exceptions.py +0 -0
  33. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/hooksniff/http_client.py +0 -0
  34. {hooksniff_python-0.4.2 → hooksniff_python-0.4.3}/test_live.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hooksniff-python
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Official HookSniff SDK for Python - Webhook infrastructure for developers
5
5
  Project-URL: Homepage, https://hooksniff.vercel.app
6
6
  Project-URL: Repository, https://github.com/servetarslan02/hooksniff-python
@@ -34,7 +34,7 @@ pip install hooksniff-python
34
34
  ## Quick Start
35
35
 
36
36
  ```python
37
- from hooksniff_python import HookSniff
37
+ from hooksniff import HookSniff
38
38
 
39
39
  hs = HookSniff("hr_live_...")
40
40
 
@@ -156,7 +156,7 @@ delivery = hs.webhook.replay("msg_123")
156
156
  ### Webhook Verification
157
157
 
158
158
  ```python
159
- from hooksniff_python import Webhook, WebhookVerificationError
159
+ from hooksniff import Webhook, WebhookVerificationError
160
160
 
161
161
  wh = Webhook("whsec_...")
162
162
 
@@ -173,7 +173,7 @@ def handle_webhook(request):
173
173
  ### Error Handling
174
174
 
175
175
  ```python
176
- from hooksniff_python import AuthenticationError, NotFoundError, RateLimitError
176
+ from hooksniff import AuthenticationError, NotFoundError, RateLimitError
177
177
 
178
178
  try:
179
179
  hs.endpoint.get("invalid_id")
@@ -11,7 +11,7 @@ pip install hooksniff-python
11
11
  ## Quick Start
12
12
 
13
13
  ```python
14
- from hooksniff_python import HookSniff
14
+ from hooksniff import HookSniff
15
15
 
16
16
  hs = HookSniff("hr_live_...")
17
17
 
@@ -133,7 +133,7 @@ delivery = hs.webhook.replay("msg_123")
133
133
  ### Webhook Verification
134
134
 
135
135
  ```python
136
- from hooksniff_python import Webhook, WebhookVerificationError
136
+ from hooksniff import Webhook, WebhookVerificationError
137
137
 
138
138
  wh = Webhook("whsec_...")
139
139
 
@@ -150,7 +150,7 @@ def handle_webhook(request):
150
150
  ### Error Handling
151
151
 
152
152
  ```python
153
- from hooksniff_python import AuthenticationError, NotFoundError, RateLimitError
153
+ from hooksniff import AuthenticationError, NotFoundError, RateLimitError
154
154
 
155
155
  try:
156
156
  hs.endpoint.get("invalid_id")
@@ -27,7 +27,7 @@ from .exceptions import (
27
27
  ServerError,
28
28
  )
29
29
 
30
- __version__ = "0.4.1"
30
+ __version__ = "0.4.3"
31
31
  __all__ = [
32
32
  "HookSniff",
33
33
  "Webhook",
@@ -0,0 +1,58 @@
1
+ """HookSniff SDK resources."""
2
+
3
+ from .application import ApplicationResource
4
+ from .endpoint import EndpointResource
5
+ from .webhook import WebhookResource
6
+ from .api_key import ApiKeyResource
7
+ from .analytics import AnalyticsResource
8
+ from .search import SearchResource
9
+ from .health import HealthResource
10
+ from .billing import BillingResource
11
+ from .notification import NotificationResource
12
+ from .cortex import CortexResource
13
+ from .team import TeamResource
14
+ from .alert import AlertResource
15
+ from .template import TemplateResource
16
+ from .schema import SchemaResource
17
+ from .connector import ConnectorResource
18
+ from .stream import StreamResource
19
+ from .advanced import (
20
+ BackgroundTaskResource,
21
+ IntegrationResource,
22
+ ServiceTokenResource,
23
+ OperationalWebhookResource,
24
+ )
25
+ from .routing import RateLimitResource, AuditResource
26
+ from .platform import SsoResource, CustomDomainResource, EnvironmentResource
27
+ from .broadcast import BroadcastResource
28
+ from .transform import TransformResource
29
+
30
+ __all__ = [
31
+ "ApplicationResource",
32
+ "EndpointResource",
33
+ "WebhookResource",
34
+ "ApiKeyResource",
35
+ "AnalyticsResource",
36
+ "SearchResource",
37
+ "HealthResource",
38
+ "BillingResource",
39
+ "NotificationResource",
40
+ "CortexResource",
41
+ "TeamResource",
42
+ "AlertResource",
43
+ "TemplateResource",
44
+ "SchemaResource",
45
+ "ConnectorResource",
46
+ "StreamResource",
47
+ "BackgroundTaskResource",
48
+ "IntegrationResource",
49
+ "ServiceTokenResource",
50
+ "OperationalWebhookResource",
51
+ "RateLimitResource",
52
+ "AuditResource",
53
+ "SsoResource",
54
+ "CustomDomainResource",
55
+ "EnvironmentResource",
56
+ "BroadcastResource",
57
+ "TransformResource",
58
+ ]
@@ -0,0 +1,66 @@
1
+ """Advanced resources: Background tasks, Integrations, Service tokens, Operational webhooks."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class BackgroundTaskResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/background-tasks")
13
+
14
+ def get(self, task_id: str) -> Dict[str, Any]:
15
+ return self.http.request("GET", f"/v1/background-tasks/{task_id}")
16
+
17
+ def cancel(self, task_id: str) -> None:
18
+ self.http.request("POST", f"/v1/background-tasks/{task_id}/cancel")
19
+
20
+
21
+ class IntegrationResource:
22
+ def __init__(self, http: HttpClient):
23
+ self.http = http
24
+
25
+ def list(self) -> List[Dict[str, Any]]:
26
+ return self.http.request("GET", "/v1/integrations")
27
+
28
+ def get(self, integration_id: str) -> Dict[str, Any]:
29
+ return self.http.request("GET", f"/v1/integrations/{integration_id}")
30
+
31
+ def delete(self, integration_id: str) -> None:
32
+ self.http.request("DELETE", f"/v1/integrations/{integration_id}")
33
+
34
+ def rotate_key(self, integration_id: str) -> Dict[str, Any]:
35
+ return self.http.request("POST", f"/v1/integrations/{integration_id}/rotate-key")
36
+
37
+
38
+ class ServiceTokenResource:
39
+ def __init__(self, http: HttpClient):
40
+ self.http = http
41
+
42
+ def list(self) -> List[Dict[str, Any]]:
43
+ return self.http.request("GET", "/v1/service-tokens")
44
+
45
+ def create(self, name: str) -> Dict[str, Any]:
46
+ return self.http.request("POST", "/v1/service-tokens", {"name": name})
47
+
48
+ def delete(self, token_id: str) -> None:
49
+ self.http.request("DELETE", f"/v1/service-tokens/{token_id}")
50
+
51
+
52
+ class OperationalWebhookResource:
53
+ def __init__(self, http: HttpClient):
54
+ self.http = http
55
+
56
+ def list(self) -> List[Dict[str, Any]]:
57
+ return self.http.request("GET", "/v1/operational-webhooks")
58
+
59
+ def create(self, url: str, events: List[str]) -> Dict[str, Any]:
60
+ return self.http.request("POST", "/v1/operational-webhooks", {"url": url, "events": events})
61
+
62
+ def get(self, webhook_id: str) -> Dict[str, Any]:
63
+ return self.http.request("GET", f"/v1/operational-webhooks/{webhook_id}")
64
+
65
+ def delete(self, webhook_id: str) -> None:
66
+ self.http.request("DELETE", f"/v1/operational-webhooks/{webhook_id}")
@@ -0,0 +1,30 @@
1
+ """Alert resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class AlertResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ response = self.http.request("GET", "/v1/alerts")
13
+ return response if isinstance(response, list) else response.get("alerts", [])
14
+
15
+ def create(self, name: str, condition: str, threshold: int, channels: List[str]) -> Dict[str, Any]:
16
+ return self.http.request("POST", "/v1/alerts", {
17
+ "name": name, "condition": condition, "threshold": threshold, "channels": channels
18
+ })
19
+
20
+ def get(self, alert_id: str) -> Dict[str, Any]:
21
+ return self.http.request("GET", f"/v1/alerts/{alert_id}")
22
+
23
+ def update(self, alert_id: str, **kwargs) -> Dict[str, Any]:
24
+ return self.http.request("PUT", f"/v1/alerts/{alert_id}", kwargs)
25
+
26
+ def delete(self, alert_id: str) -> None:
27
+ self.http.request("DELETE", f"/v1/alerts/{alert_id}")
28
+
29
+ def list_events(self, alert_id: str) -> List[Dict[str, Any]]:
30
+ return self.http.request("GET", f"/v1/alerts/{alert_id}/events")
@@ -0,0 +1,18 @@
1
+ """Analytics resource."""
2
+
3
+ from typing import Any
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class AnalyticsResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def deliveries(self, range: str = "24h") -> Any:
12
+ return self.http.request("GET", f"/v1/analytics/deliveries?range={range}")
13
+
14
+ def success_rate(self, range: str = "24h") -> Any:
15
+ return self.http.request("GET", f"/v1/analytics/success-rate?range={range}")
16
+
17
+ def latency(self, range: str = "24h") -> Any:
18
+ return self.http.request("GET", f"/v1/analytics/latency?range={range}")
@@ -0,0 +1,21 @@
1
+ """API Key resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class ApiKeyResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/api-keys")
13
+
14
+ def create(self, name: str) -> Dict[str, Any]:
15
+ return self.http.request("POST", "/v1/api-keys", {"name": name})
16
+
17
+ def delete(self, api_key_id: str) -> None:
18
+ self.http.request("DELETE", f"/v1/api-keys/{api_key_id}")
19
+
20
+ def rotate(self, api_key_id: str) -> Dict[str, Any]:
21
+ return self.http.request("POST", f"/v1/api-keys/{api_key_id}/rotate")
@@ -0,0 +1,27 @@
1
+ """Application resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient, PaginatedList
5
+
6
+
7
+ class ApplicationResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def create(self, name: str, description: str = None) -> Dict[str, Any]:
12
+ body: Dict[str, Any] = {"name": name}
13
+ if description:
14
+ body["description"] = description
15
+ return self.http.request("POST", "/v1/applications", body)
16
+
17
+ def list(self, per_page: int = 50) -> PaginatedList:
18
+ return PaginatedList(self.http, "/v1/applications", per_page=per_page)
19
+
20
+ def get(self, application_id: str) -> Dict[str, Any]:
21
+ return self.http.request("GET", f"/v1/applications/{application_id}")
22
+
23
+ def update(self, application_id: str, **kwargs) -> Dict[str, Any]:
24
+ return self.http.request("PUT", f"/v1/applications/{application_id}", kwargs)
25
+
26
+ def delete(self, application_id: str) -> None:
27
+ self.http.request("DELETE", f"/v1/applications/{application_id}")
@@ -0,0 +1,24 @@
1
+ """Billing resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class BillingResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def subscription(self) -> Dict[str, Any]:
12
+ return self.http.request("GET", "/v1/billing/subscription")
13
+
14
+ def upgrade(self, plan: str) -> Dict[str, Any]:
15
+ return self.http.request("POST", "/v1/billing/upgrade", {"plan": plan})
16
+
17
+ def portal(self) -> Dict[str, Any]:
18
+ return self.http.request("POST", "/v1/billing/portal")
19
+
20
+ def usage(self) -> Dict[str, Any]:
21
+ return self.http.request("GET", "/v1/billing/usage")
22
+
23
+ def invoices(self) -> Dict[str, Any]:
24
+ return self.http.request("GET", "/v1/billing/invoices")
@@ -0,0 +1,27 @@
1
+ """Broadcast resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class BroadcastResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/broadcasts")
13
+
14
+ def create(self, title: str, message: str, scheduled_at: str = None) -> Dict[str, Any]:
15
+ body: Dict[str, Any] = {"title": title, "message": message}
16
+ if scheduled_at:
17
+ body["scheduled_at"] = scheduled_at
18
+ return self.http.request("POST", "/v1/broadcasts", body)
19
+
20
+ def get(self, broadcast_id: str) -> Dict[str, Any]:
21
+ return self.http.request("GET", f"/v1/broadcasts/{broadcast_id}")
22
+
23
+ def delete(self, broadcast_id: str) -> None:
24
+ self.http.request("DELETE", f"/v1/broadcasts/{broadcast_id}")
25
+
26
+ def send(self, broadcast_id: str) -> None:
27
+ self.http.request("POST", f"/v1/broadcasts/{broadcast_id}/send")
@@ -0,0 +1,32 @@
1
+ """Connector resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class ConnectorResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/connectors")
13
+
14
+ def get(self, connector_id: str) -> Dict[str, Any]:
15
+ return self.http.request("GET", f"/v1/connectors/{connector_id}")
16
+
17
+ def list_configs(self) -> List[Dict[str, Any]]:
18
+ return self.http.request("GET", "/v1/connectors/configs")
19
+
20
+ def create_config(self, connector_id: str, name: str, config: Dict[str, Any]) -> Dict[str, Any]:
21
+ return self.http.request("POST", "/v1/connectors/configs", {
22
+ "connector_id": connector_id, "name": name, "config": config
23
+ })
24
+
25
+ def get_config(self, config_id: str) -> Dict[str, Any]:
26
+ return self.http.request("GET", f"/v1/connectors/configs/{config_id}")
27
+
28
+ def update_config(self, config_id: str, **kwargs) -> Dict[str, Any]:
29
+ return self.http.request("PUT", f"/v1/connectors/configs/{config_id}", kwargs)
30
+
31
+ def delete_config(self, config_id: str) -> None:
32
+ self.http.request("DELETE", f"/v1/connectors/configs/{config_id}")
@@ -0,0 +1,43 @@
1
+ """Cortex AI resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class CortexResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def insights(self) -> List[Dict[str, Any]]:
12
+ response = self.http.request("GET", "/v1/cortex/insights")
13
+ if isinstance(response, dict) and "insights" in response:
14
+ raw = response["insights"]
15
+ result = []
16
+ for row in raw:
17
+ if isinstance(row, list) and len(row) >= 10:
18
+ result.append({
19
+ "id": row[0],
20
+ "customer_id": row[1],
21
+ "type": row[2],
22
+ "title": row[3],
23
+ "description": row[4],
24
+ "severity": row[5],
25
+ "metadata": row[7] if len(row) > 7 else {},
26
+ "created_at": row[9] if len(row) > 9 else None,
27
+ })
28
+ else:
29
+ result.append(row)
30
+ return result
31
+ return response if isinstance(response, list) else []
32
+
33
+ def anomalies(self, endpoint_id: str = None) -> List[Dict[str, Any]]:
34
+ path = "/v1/cortex/anomalies"
35
+ if endpoint_id:
36
+ path += f"?endpoint_id={endpoint_id}"
37
+ return self.http.request("GET", path)
38
+
39
+ def predict(self, endpoint_id: str) -> Dict[str, Any]:
40
+ return self.http.request("GET", f"/v1/cortex/predict/{endpoint_id}")
41
+
42
+ def auto_heal(self, endpoint_id: str) -> Dict[str, Any]:
43
+ return self.http.request("POST", f"/v1/cortex/auto-heal/{endpoint_id}")
@@ -0,0 +1,31 @@
1
+ """Endpoint resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient, PaginatedList
5
+
6
+
7
+ class EndpointResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def create(self, url: str, application_id: str, description: str = None, **kwargs) -> Dict[str, Any]:
12
+ body: Dict[str, Any] = {"url": url, "application_id": application_id}
13
+ if description:
14
+ body["description"] = description
15
+ body.update(kwargs)
16
+ return self.http.request("POST", "/v1/endpoints", body)
17
+
18
+ def list(self, per_page: int = 50) -> PaginatedList:
19
+ return PaginatedList(self.http, "/v1/endpoints", per_page=per_page)
20
+
21
+ def get(self, endpoint_id: str) -> Dict[str, Any]:
22
+ return self.http.request("GET", f"/v1/endpoints/{endpoint_id}")
23
+
24
+ def update(self, endpoint_id: str, **kwargs) -> Dict[str, Any]:
25
+ return self.http.request("PUT", f"/v1/endpoints/{endpoint_id}", kwargs)
26
+
27
+ def delete(self, endpoint_id: str) -> None:
28
+ self.http.request("DELETE", f"/v1/endpoints/{endpoint_id}")
29
+
30
+ def rotate_secret(self, endpoint_id: str) -> Dict[str, Any]:
31
+ return self.http.request("POST", f"/v1/endpoints/{endpoint_id}/rotate-secret")
@@ -0,0 +1,15 @@
1
+ """Health resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class HealthResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def check(self) -> Dict[str, Any]:
12
+ return self.http.request("GET", "/health")
13
+
14
+ def outbound_ips(self) -> Dict[str, Any]:
15
+ return self.http.request("GET", "/v1/outbound-ips")
@@ -0,0 +1,22 @@
1
+ """Notification resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class NotificationResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self, per_page: int = 20) -> Dict[str, Any]:
12
+ return self.http.request("GET", f"/v1/notifications?per_page={per_page}")
13
+
14
+ def get_unread_count(self) -> Dict[str, Any]:
15
+ response = self.http.request("GET", "/v1/notifications/unread-count")
16
+ return {"count": response.get("unread_count", 0)}
17
+
18
+ def mark_read(self, notification_id: str) -> None:
19
+ self.http.request("POST", f"/v1/notifications/{notification_id}/read")
20
+
21
+ def mark_all_read(self) -> None:
22
+ self.http.request("POST", "/v1/notifications/read-all")
@@ -0,0 +1,28 @@
1
+ """Platform resources: SSO, Custom domains, Environments."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class SsoResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def get_config(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/sso/config")
13
+
14
+
15
+ class CustomDomainResource:
16
+ def __init__(self, http: HttpClient):
17
+ self.http = http
18
+
19
+ def list(self) -> List[Dict[str, Any]]:
20
+ return self.http.request("GET", "/v1/custom-domains")
21
+
22
+
23
+ class EnvironmentResource:
24
+ def __init__(self, http: HttpClient):
25
+ self.http = http
26
+
27
+ def list(self) -> List[Dict[str, Any]]:
28
+ return self.http.request("GET", "/v1/environments")
@@ -0,0 +1,20 @@
1
+ """Routing resources: Rate limits, Audit log."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class RateLimitResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/rate-limits")
13
+
14
+
15
+ class AuditResource:
16
+ def __init__(self, http: HttpClient):
17
+ self.http = http
18
+
19
+ def list(self) -> Dict[str, Any]:
20
+ return self.http.request("GET", "/v1/audit-log")
@@ -0,0 +1,25 @@
1
+ """Schema resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class SchemaResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ response = self.http.request("GET", "/v1/schemas")
13
+ return response if isinstance(response, list) else response.get("schemas", [])
14
+
15
+ def create(self, name: str, schema: Dict[str, Any]) -> Dict[str, Any]:
16
+ return self.http.request("POST", "/v1/schemas", {"name": name, "schema": schema})
17
+
18
+ def get(self, schema_id: str) -> Dict[str, Any]:
19
+ return self.http.request("GET", f"/v1/schemas/{schema_id}")
20
+
21
+ def delete(self, schema_id: str) -> None:
22
+ self.http.request("DELETE", f"/v1/schemas/{schema_id}")
23
+
24
+ def validate(self, schema_id: str, data: Any) -> Dict[str, Any]:
25
+ return self.http.request("POST", f"/v1/schemas/{schema_id}/validate", {"data": data})
@@ -0,0 +1,12 @@
1
+ """Search resource."""
2
+
3
+ from typing import Any, Dict
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class SearchResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def deliveries(self, query: str, page: int = 1, per_page: int = 20) -> Dict[str, Any]:
12
+ return self.http.request("GET", f"/v1/search?q={query}&page={page}&per_page={per_page}")
@@ -0,0 +1,41 @@
1
+ """Stream resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class StreamResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list_channels(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/stream/channels")
13
+
14
+ def create_channel(self, name: str, description: str = None) -> Dict[str, Any]:
15
+ body: Dict[str, Any] = {"name": name}
16
+ if description:
17
+ body["description"] = description
18
+ return self.http.request("POST", "/v1/stream/channels", body)
19
+
20
+ def get_channel(self, channel_id: str) -> Dict[str, Any]:
21
+ return self.http.request("GET", f"/v1/stream/channels/{channel_id}")
22
+
23
+ def delete_channel(self, channel_id: str) -> None:
24
+ self.http.request("DELETE", f"/v1/stream/channels/{channel_id}")
25
+
26
+ def list_messages(self, channel_id: str) -> List[Dict[str, Any]]:
27
+ return self.http.request("GET", f"/v1/stream/channels/{channel_id}/messages")
28
+
29
+ def publish(self, channel_id: str, event: str, data: Dict[str, Any]) -> Dict[str, Any]:
30
+ return self.http.request("POST", "/v1/stream/publish", {
31
+ "channel_id": channel_id, "event": event, "data": data
32
+ })
33
+
34
+ def list_subscriptions(self) -> List[Dict[str, Any]]:
35
+ return self.http.request("GET", "/v1/stream/subscriptions")
36
+
37
+ def get_subscription(self, subscription_id: str) -> Dict[str, Any]:
38
+ return self.http.request("GET", f"/v1/stream/subscriptions/{subscription_id}")
39
+
40
+ def disconnect_subscription(self, subscription_id: str) -> None:
41
+ self.http.request("DELETE", f"/v1/stream/subscriptions/{subscription_id}")
@@ -0,0 +1,33 @@
1
+ """Team resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class TeamResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", "/v1/teams")
13
+
14
+ def create(self, name: str, description: str = None) -> Dict[str, Any]:
15
+ body: Dict[str, Any] = {"name": name}
16
+ if description:
17
+ body["description"] = description
18
+ return self.http.request("POST", "/v1/teams", body)
19
+
20
+ def get(self, team_id: str) -> Dict[str, Any]:
21
+ return self.http.request("GET", f"/v1/teams/{team_id}")
22
+
23
+ def delete(self, team_id: str) -> None:
24
+ self.http.request("DELETE", f"/v1/teams/{team_id}")
25
+
26
+ def list_members(self, team_id: str) -> List[Dict[str, Any]]:
27
+ return self.http.request("GET", f"/v1/teams/{team_id}/members")
28
+
29
+ def invite_member(self, team_id: str, email: str, role: str = "viewer") -> Dict[str, Any]:
30
+ return self.http.request("POST", f"/v1/teams/{team_id}/members", {"email": email, "role": role})
31
+
32
+ def remove_member(self, team_id: str, member_id: str) -> None:
33
+ self.http.request("DELETE", f"/v1/teams/{team_id}/members/{member_id}")
@@ -0,0 +1,28 @@
1
+ """Template resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class TemplateResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self) -> List[Dict[str, Any]]:
12
+ response = self.http.request("GET", "/v1/templates")
13
+ return response if isinstance(response, list) else response.get("templates", [])
14
+
15
+ def create(self, name: str, content: str, description: str = None) -> Dict[str, Any]:
16
+ body: Dict[str, Any] = {"name": name, "content": content}
17
+ if description:
18
+ body["description"] = description
19
+ return self.http.request("POST", "/v1/templates", body)
20
+
21
+ def get(self, template_id: str) -> Dict[str, Any]:
22
+ return self.http.request("GET", f"/v1/templates/{template_id}")
23
+
24
+ def update(self, template_id: str, **kwargs) -> Dict[str, Any]:
25
+ return self.http.request("PUT", f"/v1/templates/{template_id}", kwargs)
26
+
27
+ def delete(self, template_id: str) -> None:
28
+ self.http.request("DELETE", f"/v1/templates/{template_id}")
@@ -0,0 +1,24 @@
1
+ """Transform resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient
5
+
6
+
7
+ class TransformResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def list(self, endpoint_id: str) -> List[Dict[str, Any]]:
12
+ return self.http.request("GET", f"/v1/endpoints/{endpoint_id}/transforms")
13
+
14
+ def create(self, endpoint_id: str, name: str, code: str) -> Dict[str, Any]:
15
+ return self.http.request("POST", f"/v1/endpoints/{endpoint_id}/transforms", {"name": name, "code": code})
16
+
17
+ def get(self, endpoint_id: str, transform_id: str) -> Dict[str, Any]:
18
+ return self.http.request("GET", f"/v1/endpoints/{endpoint_id}/transforms/{transform_id}")
19
+
20
+ def update(self, endpoint_id: str, transform_id: str, **kwargs) -> Dict[str, Any]:
21
+ return self.http.request("PUT", f"/v1/endpoints/{endpoint_id}/transforms/{transform_id}", kwargs)
22
+
23
+ def delete(self, endpoint_id: str, transform_id: str) -> None:
24
+ self.http.request("DELETE", f"/v1/endpoints/{endpoint_id}/transforms/{transform_id}")
@@ -0,0 +1,34 @@
1
+ """Webhook resource."""
2
+
3
+ from typing import Any, Dict, List
4
+ from ..http_client import HttpClient, PaginatedList
5
+
6
+
7
+ class WebhookResource:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+
11
+ def send(self, endpoint_id: str, event: str, data: Dict[str, Any], idempotency_key: str = None) -> Dict[str, Any]:
12
+ body = {"endpoint_id": endpoint_id, "event": event, "data": data}
13
+ options = {"idempotency_key": idempotency_key} if idempotency_key else None
14
+ return self.http.request("POST", "/v1/webhooks", body, options)
15
+
16
+ def send_batch(self, webhooks: List[Dict[str, Any]]) -> Dict[str, Any]:
17
+ return self.http.request("POST", "/v1/webhooks/batch", {"webhooks": webhooks})
18
+
19
+ def list(self, per_page: int = 50, endpoint_id: str = None, status: str = None) -> PaginatedList:
20
+ params: Dict[str, str] = {}
21
+ if endpoint_id:
22
+ params["endpoint_id"] = endpoint_id
23
+ if status:
24
+ params["status"] = status
25
+ return PaginatedList(self.http, "/v1/webhooks", params=params, per_page=per_page)
26
+
27
+ def get(self, webhook_id: str) -> Dict[str, Any]:
28
+ return self.http.request("GET", f"/v1/webhooks/{webhook_id}")
29
+
30
+ def replay(self, webhook_id: str) -> Dict[str, Any]:
31
+ return self.http.request("POST", f"/v1/webhooks/{webhook_id}/replay")
32
+
33
+ def batch_replay(self, webhook_ids: List[str]) -> Dict[str, Any]:
34
+ return self.http.request("POST", "/v1/webhooks/batch-replay", {"webhook_ids": webhook_ids})
@@ -81,5 +81,5 @@ class Webhook:
81
81
  secret_key = secret_bytes
82
82
 
83
83
  return base64.b64encode(
84
- hmac.new(secret_key, content.encode("utf-8"), hashlib.sha256).digest()
84
+ hmac.HMAC(secret_key, content.encode("utf-8"), hashlib.sha256).digest()
85
85
  ).decode("utf-8")
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hooksniff-python"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Official HookSniff SDK for Python - Webhook infrastructure for developers"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,450 +0,0 @@
1
- from typing import Any, Dict, List, Optional
2
- from .http_client import HttpClient, PaginatedList
3
-
4
-
5
- class ApplicationResource:
6
- def __init__(self, http: HttpClient):
7
- self.http = http
8
-
9
- def create(self, name: str, description: str = None) -> Dict[str, Any]:
10
- body = {"name": name}
11
- if description:
12
- body["description"] = description
13
- return self.http.request("POST", "/v1/applications", body)
14
-
15
- def list(self, per_page: int = 50) -> PaginatedList:
16
- return PaginatedList(self.http, "/v1/applications", per_page=per_page)
17
-
18
- def get(self, application_id: str) -> Dict[str, Any]:
19
- return self.http.request("GET", f"/v1/applications/{application_id}")
20
-
21
- def update(self, application_id: str, **kwargs) -> Dict[str, Any]:
22
- return self.http.request("PUT", f"/v1/applications/{application_id}", kwargs)
23
-
24
- def delete(self, application_id: str) -> None:
25
- self.http.request("DELETE", f"/v1/applications/{application_id}")
26
-
27
-
28
- class EndpointResource:
29
- def __init__(self, http: HttpClient):
30
- self.http = http
31
-
32
- def create(self, url: str, application_id: str, description: str = None, **kwargs) -> Dict[str, Any]:
33
- body = {"url": url, "application_id": application_id}
34
- if description:
35
- body["description"] = description
36
- body.update(kwargs)
37
- return self.http.request("POST", "/v1/endpoints", body)
38
-
39
- def list(self, per_page: int = 50) -> PaginatedList:
40
- return PaginatedList(self.http, "/v1/endpoints", per_page=per_page)
41
-
42
- def get(self, endpoint_id: str) -> Dict[str, Any]:
43
- return self.http.request("GET", f"/v1/endpoints/{endpoint_id}")
44
-
45
- def update(self, endpoint_id: str, **kwargs) -> Dict[str, Any]:
46
- return self.http.request("PUT", f"/v1/endpoints/{endpoint_id}", kwargs)
47
-
48
- def delete(self, endpoint_id: str) -> None:
49
- self.http.request("DELETE", f"/v1/endpoints/{endpoint_id}")
50
-
51
- def rotate_secret(self, endpoint_id: str) -> Dict[str, Any]:
52
- return self.http.request("POST", f"/v1/endpoints/{endpoint_id}/rotate-secret")
53
-
54
-
55
- class WebhookResource:
56
- def __init__(self, http: HttpClient):
57
- self.http = http
58
-
59
- def send(self, endpoint_id: str, event: str, data: Dict[str, Any], idempotency_key: str = None) -> Dict[str, Any]:
60
- body = {"endpoint_id": endpoint_id, "event": event, "data": data}
61
- options = {"idempotency_key": idempotency_key} if idempotency_key else None
62
- return self.http.request("POST", "/v1/webhooks", body, options)
63
-
64
- def send_batch(self, webhooks: List[Dict[str, Any]]) -> Dict[str, Any]:
65
- return self.http.request("POST", "/v1/webhooks/batch", {"webhooks": webhooks})
66
-
67
- def list(self, per_page: int = 50, endpoint_id: str = None, status: str = None) -> PaginatedList:
68
- params = {}
69
- if endpoint_id:
70
- params["endpoint_id"] = endpoint_id
71
- if status:
72
- params["status"] = status
73
- return PaginatedList(self.http, "/v1/webhooks", params=params, per_page=per_page)
74
-
75
- def get(self, webhook_id: str) -> Dict[str, Any]:
76
- return self.http.request("GET", f"/v1/webhooks/{webhook_id}")
77
-
78
- def replay(self, webhook_id: str) -> Dict[str, Any]:
79
- return self.http.request("POST", f"/v1/webhooks/{webhook_id}/replay")
80
-
81
-
82
- class ApiKeyResource:
83
- def __init__(self, http: HttpClient):
84
- self.http = http
85
-
86
- def list(self) -> List[Dict[str, Any]]:
87
- return self.http.request("GET", "/v1/api-keys")
88
-
89
- def create(self, name: str) -> Dict[str, Any]:
90
- return self.http.request("POST", "/v1/api-keys", {"name": name})
91
-
92
- def delete(self, api_key_id: str) -> None:
93
- self.http.request("DELETE", f"/v1/api-keys/{api_key_id}")
94
-
95
-
96
- class AnalyticsResource:
97
- def __init__(self, http: HttpClient):
98
- self.http = http
99
-
100
- def deliveries(self, range: str = "24h") -> Any:
101
- return self.http.request("GET", f"/v1/analytics/deliveries?range={range}")
102
-
103
- def success_rate(self, range: str = "24h") -> Any:
104
- return self.http.request("GET", f"/v1/analytics/success-rate?range={range}")
105
-
106
-
107
- class SearchResource:
108
- def __init__(self, http: HttpClient):
109
- self.http = http
110
-
111
- def deliveries(self, query: str, page: int = 1, per_page: int = 20) -> Dict[str, Any]:
112
- return self.http.request("GET", f"/v1/search?q={query}&page={page}&per_page={per_page}")
113
-
114
-
115
- class HealthResource:
116
- def __init__(self, http: HttpClient):
117
- self.http = http
118
-
119
- def check(self) -> Dict[str, Any]:
120
- return self.http.request("GET", "/health")
121
-
122
- def outbound_ips(self) -> Dict[str, Any]:
123
- return self.http.request("GET", "/v1/outbound-ips")
124
-
125
-
126
- class BillingResource:
127
- def __init__(self, http: HttpClient):
128
- self.http = http
129
-
130
- def subscription(self) -> Dict[str, Any]:
131
- return self.http.request("GET", "/v1/billing/subscription")
132
-
133
- def upgrade(self, plan: str) -> Dict[str, Any]:
134
- return self.http.request("POST", "/v1/billing/upgrade", {"plan": plan})
135
-
136
- def portal(self) -> Dict[str, Any]:
137
- return self.http.request("POST", "/v1/billing/portal")
138
-
139
-
140
- class NotificationResource:
141
- def __init__(self, http: HttpClient):
142
- self.http = http
143
-
144
- def list(self, per_page: int = 20) -> Dict[str, Any]:
145
- return self.http.request("GET", f"/v1/notifications?per_page={per_page}")
146
-
147
- def get_unread_count(self) -> Dict[str, Any]:
148
- response = self.http.request("GET", "/v1/notifications/unread-count")
149
- return {"count": response.get("unread_count", 0)}
150
-
151
- def mark_read(self, notification_id: str) -> None:
152
- self.http.request("POST", f"/v1/notifications/{notification_id}/read")
153
-
154
- def mark_all_read(self) -> None:
155
- self.http.request("POST", "/v1/notifications/read-all")
156
-
157
-
158
- class CortexResource:
159
- def __init__(self, http: HttpClient):
160
- self.http = http
161
-
162
- def insights(self) -> List[Dict[str, Any]]:
163
- response = self.http.request("GET", "/v1/cortex/insights")
164
- if isinstance(response, dict) and "insights" in response:
165
- raw = response["insights"]
166
- result = []
167
- for row in raw:
168
- if isinstance(row, list) and len(row) >= 10:
169
- result.append({
170
- "id": row[0],
171
- "customer_id": row[1],
172
- "type": row[2],
173
- "title": row[3],
174
- "description": row[4],
175
- "severity": row[5],
176
- "metadata": row[7] if len(row) > 7 else {},
177
- "created_at": row[9] if len(row) > 9 else None,
178
- })
179
- else:
180
- result.append(row)
181
- return result
182
- return response if isinstance(response, list) else []
183
-
184
- def anomalies(self, endpoint_id: str = None) -> List[Dict[str, Any]]:
185
- path = "/v1/cortex/anomalies"
186
- if endpoint_id:
187
- path += f"?endpoint_id={endpoint_id}"
188
- return self.http.request("GET", path)
189
-
190
- def predict(self, endpoint_id: str) -> Dict[str, Any]:
191
- return self.http.request("GET", f"/v1/cortex/predict/{endpoint_id}")
192
-
193
- def auto_heal(self, endpoint_id: str) -> Dict[str, Any]:
194
- return self.http.request("POST", f"/v1/cortex/auto-heal/{endpoint_id}")
195
-
196
-
197
- class TeamResource:
198
- def __init__(self, http: HttpClient):
199
- self.http = http
200
-
201
- def list(self) -> List[Dict[str, Any]]:
202
- return self.http.request("GET", "/v1/teams")
203
-
204
- def create(self, name: str, description: str = None) -> Dict[str, Any]:
205
- body = {"name": name}
206
- if description:
207
- body["description"] = description
208
- return self.http.request("POST", "/v1/teams", body)
209
-
210
- def get(self, team_id: str) -> Dict[str, Any]:
211
- return self.http.request("GET", f"/v1/teams/{team_id}")
212
-
213
- def delete(self, team_id: str) -> None:
214
- self.http.request("DELETE", f"/v1/teams/{team_id}")
215
-
216
-
217
- class AlertResource:
218
- def __init__(self, http: HttpClient):
219
- self.http = http
220
-
221
- def list(self) -> List[Dict[str, Any]]:
222
- response = self.http.request("GET", "/v1/alerts")
223
- return response if isinstance(response, list) else response.get("alerts", [])
224
-
225
- def create(self, name: str, condition: str, threshold: int, channels: List[str]) -> Dict[str, Any]:
226
- return self.http.request("POST", "/v1/alerts", {
227
- "name": name, "condition": condition, "threshold": threshold, "channels": channels
228
- })
229
-
230
- def get(self, alert_id: str) -> Dict[str, Any]:
231
- return self.http.request("GET", f"/v1/alerts/{alert_id}")
232
-
233
- def delete(self, alert_id: str) -> None:
234
- self.http.request("DELETE", f"/v1/alerts/{alert_id}")
235
-
236
-
237
- class TemplateResource:
238
- def __init__(self, http: HttpClient):
239
- self.http = http
240
-
241
- def list(self) -> List[Dict[str, Any]]:
242
- response = self.http.request("GET", "/v1/templates")
243
- return response if isinstance(response, list) else response.get("templates", [])
244
-
245
- def get(self, template_id: str) -> Dict[str, Any]:
246
- return self.http.request("GET", f"/v1/templates/{template_id}")
247
-
248
-
249
- class SchemaResource:
250
- def __init__(self, http: HttpClient):
251
- self.http = http
252
-
253
- def list(self) -> List[Dict[str, Any]]:
254
- response = self.http.request("GET", "/v1/schemas")
255
- return response if isinstance(response, list) else response.get("schemas", [])
256
-
257
- def create(self, name: str, schema: Dict[str, Any]) -> Dict[str, Any]:
258
- return self.http.request("POST", "/v1/schemas", {"name": name, "schema": schema})
259
-
260
- def get(self, schema_id: str) -> Dict[str, Any]:
261
- return self.http.request("GET", f"/v1/schemas/{schema_id}")
262
-
263
- def delete(self, schema_id: str) -> None:
264
- self.http.request("DELETE", f"/v1/schemas/{schema_id}")
265
-
266
-
267
- class ConnectorResource:
268
- def __init__(self, http: HttpClient):
269
- self.http = http
270
-
271
- def list(self) -> List[Dict[str, Any]]:
272
- return self.http.request("GET", "/v1/connectors")
273
-
274
- def get(self, connector_id: str) -> Dict[str, Any]:
275
- return self.http.request("GET", f"/v1/connectors/{connector_id}")
276
-
277
- def list_configs(self) -> List[Dict[str, Any]]:
278
- return self.http.request("GET", "/v1/connectors/configs")
279
-
280
- def create_config(self, connector_id: str, name: str, config: Dict[str, Any]) -> Dict[str, Any]:
281
- return self.http.request("POST", "/v1/connectors/configs", {
282
- "connector_id": connector_id, "name": name, "config": config
283
- })
284
-
285
-
286
- class StreamResource:
287
- def __init__(self, http: HttpClient):
288
- self.http = http
289
-
290
- def list_channels(self) -> List[Dict[str, Any]]:
291
- return self.http.request("GET", "/v1/stream/channels")
292
-
293
- def create_channel(self, name: str, description: str = None) -> Dict[str, Any]:
294
- body = {"name": name}
295
- if description:
296
- body["description"] = description
297
- return self.http.request("POST", "/v1/stream/channels", body)
298
-
299
- def get_channel(self, channel_id: str) -> Dict[str, Any]:
300
- return self.http.request("GET", f"/v1/stream/channels/{channel_id}")
301
-
302
- def delete_channel(self, channel_id: str) -> None:
303
- self.http.request("DELETE", f"/v1/stream/channels/{channel_id}")
304
-
305
- def publish(self, channel_id: str, event: str, data: Dict[str, Any]) -> Dict[str, Any]:
306
- return self.http.request("POST", "/v1/stream/publish", {
307
- "channel_id": channel_id, "event": event, "data": data
308
- })
309
-
310
- def list_subscriptions(self) -> List[Dict[str, Any]]:
311
- return self.http.request("GET", "/v1/stream/subscriptions")
312
-
313
-
314
- class BackgroundTaskResource:
315
- def __init__(self, http: HttpClient):
316
- self.http = http
317
-
318
- def list(self) -> List[Dict[str, Any]]:
319
- return self.http.request("GET", "/v1/background-tasks")
320
-
321
- def get(self, task_id: str) -> Dict[str, Any]:
322
- return self.http.request("GET", f"/v1/background-tasks/{task_id}")
323
-
324
- def cancel(self, task_id: str) -> None:
325
- self.http.request("POST", f"/v1/background-tasks/{task_id}/cancel")
326
-
327
-
328
- class IntegrationResource:
329
- def __init__(self, http: HttpClient):
330
- self.http = http
331
-
332
- def list(self) -> List[Dict[str, Any]]:
333
- return self.http.request("GET", "/v1/integrations")
334
-
335
- def get(self, integration_id: str) -> Dict[str, Any]:
336
- return self.http.request("GET", f"/v1/integrations/{integration_id}")
337
-
338
- def delete(self, integration_id: str) -> None:
339
- self.http.request("DELETE", f"/v1/integrations/{integration_id}")
340
-
341
-
342
- class ServiceTokenResource:
343
- def __init__(self, http: HttpClient):
344
- self.http = http
345
-
346
- def list(self) -> List[Dict[str, Any]]:
347
- return self.http.request("GET", "/v1/service-tokens")
348
-
349
- def create(self, name: str) -> Dict[str, Any]:
350
- return self.http.request("POST", "/v1/service-tokens", {"name": name})
351
-
352
- def delete(self, token_id: str) -> None:
353
- self.http.request("DELETE", f"/v1/service-tokens/{token_id}")
354
-
355
-
356
- class OperationalWebhookResource:
357
- def __init__(self, http: HttpClient):
358
- self.http = http
359
-
360
- def list(self) -> List[Dict[str, Any]]:
361
- return self.http.request("GET", "/v1/operational-webhooks")
362
-
363
- def create(self, url: str, events: List[str]) -> Dict[str, Any]:
364
- return self.http.request("POST", "/v1/operational-webhooks", {"url": url, "events": events})
365
-
366
- def get(self, webhook_id: str) -> Dict[str, Any]:
367
- return self.http.request("GET", f"/v1/operational-webhooks/{webhook_id}")
368
-
369
- def delete(self, webhook_id: str) -> None:
370
- self.http.request("DELETE", f"/v1/operational-webhooks/{webhook_id}")
371
-
372
-
373
- class RateLimitResource:
374
- def __init__(self, http: HttpClient):
375
- self.http = http
376
-
377
- def list(self) -> List[Dict[str, Any]]:
378
- return self.http.request("GET", "/v1/rate-limits")
379
-
380
-
381
- class AuditResource:
382
- def __init__(self, http: HttpClient):
383
- self.http = http
384
-
385
- def list(self) -> Dict[str, Any]:
386
- return self.http.request("GET", "/v1/audit-log")
387
-
388
-
389
- class SsoResource:
390
- def __init__(self, http: HttpClient):
391
- self.http = http
392
-
393
- def get_config(self) -> List[Dict[str, Any]]:
394
- return self.http.request("GET", "/v1/sso/config")
395
-
396
-
397
- class CustomDomainResource:
398
- def __init__(self, http: HttpClient):
399
- self.http = http
400
-
401
- def list(self) -> List[Dict[str, Any]]:
402
- return self.http.request("GET", "/v1/custom-domains")
403
-
404
-
405
- class EnvironmentResource:
406
- def __init__(self, http: HttpClient):
407
- self.http = http
408
-
409
- def list(self) -> List[Dict[str, Any]]:
410
- return self.http.request("GET", "/v1/environments")
411
-
412
-
413
- class BroadcastResource:
414
- def __init__(self, http: HttpClient):
415
- self.http = http
416
-
417
- def list(self) -> List[Dict[str, Any]]:
418
- return self.http.request("GET", "/v1/broadcasts")
419
-
420
- def create(self, title: str, message: str, scheduled_at: str = None) -> Dict[str, Any]:
421
- body = {"title": title, "message": message}
422
- if scheduled_at:
423
- body["scheduled_at"] = scheduled_at
424
- return self.http.request("POST", "/v1/broadcasts", body)
425
-
426
- def get(self, broadcast_id: str) -> Dict[str, Any]:
427
- return self.http.request("GET", f"/v1/broadcasts/{broadcast_id}")
428
-
429
- def delete(self, broadcast_id: str) -> None:
430
- self.http.request("DELETE", f"/v1/broadcasts/{broadcast_id}")
431
-
432
- def send(self, broadcast_id: str) -> None:
433
- self.http.request("POST", f"/v1/broadcasts/{broadcast_id}/send")
434
-
435
-
436
- class TransformResource:
437
- def __init__(self, http: HttpClient):
438
- self.http = http
439
-
440
- def list(self, endpoint_id: str) -> List[Dict[str, Any]]:
441
- return self.http.request("GET", f"/v1/endpoints/{endpoint_id}/transforms")
442
-
443
- def create(self, endpoint_id: str, name: str, code: str) -> Dict[str, Any]:
444
- return self.http.request("POST", f"/v1/endpoints/{endpoint_id}/transforms", {"name": name, "code": code})
445
-
446
- def get(self, endpoint_id: str, transform_id: str) -> Dict[str, Any]:
447
- return self.http.request("GET", f"/v1/endpoints/{endpoint_id}/transforms/{transform_id}")
448
-
449
- def delete(self, endpoint_id: str, transform_id: str) -> None:
450
- self.http.request("DELETE", f"/v1/endpoints/{endpoint_id}/transforms/{transform_id}")