webhook-platform 1.0.0__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.
- webhook_platform-1.0.0/PKG-INFO +298 -0
- webhook_platform-1.0.0/README.md +269 -0
- webhook_platform-1.0.0/pyproject.toml +50 -0
- webhook_platform-1.0.0/setup.cfg +4 -0
- webhook_platform-1.0.0/tests/__init__.py +0 -0
- webhook_platform-1.0.0/tests/test_client.py +288 -0
- webhook_platform-1.0.0/tests/test_webhooks.py +264 -0
- webhook_platform-1.0.0/webhook_platform/__init__.py +54 -0
- webhook_platform-1.0.0/webhook_platform/client.py +322 -0
- webhook_platform-1.0.0/webhook_platform/errors.py +58 -0
- webhook_platform-1.0.0/webhook_platform/types.py +251 -0
- webhook_platform-1.0.0/webhook_platform/webhooks.py +161 -0
- webhook_platform-1.0.0/webhook_platform.egg-info/PKG-INFO +298 -0
- webhook_platform-1.0.0/webhook_platform.egg-info/SOURCES.txt +15 -0
- webhook_platform-1.0.0/webhook_platform.egg-info/dependency_links.txt +1 -0
- webhook_platform-1.0.0/webhook_platform.egg-info/requires.txt +7 -0
- webhook_platform-1.0.0/webhook_platform.egg-info/top_level.txt +3 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: webhook-platform
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for Webhook Platform
|
|
5
|
+
Author-email: Webhook Platform <hello@webhook-platform.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/vadymkykalo/webhook-platform
|
|
8
|
+
Project-URL: Repository, https://github.com/vadymkykalo/webhook-platform
|
|
9
|
+
Project-URL: Documentation, https://github.com/vadymkykalo/webhook-platform#readme
|
|
10
|
+
Keywords: webhook,webhooks,api,events,delivery
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: requests>=2.28.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: types-requests>=2.28.0; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# webhook-platform
|
|
31
|
+
|
|
32
|
+
Official Python SDK for [Webhook Platform](https://github.com/vadymkykalo/webhook-platform).
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install webhook-platform
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from webhook_platform import WebhookPlatform, Event
|
|
44
|
+
|
|
45
|
+
client = WebhookPlatform(
|
|
46
|
+
api_key="wh_live_your_api_key",
|
|
47
|
+
base_url="http://localhost:8080", # optional
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Send an event
|
|
51
|
+
event = client.events.send(
|
|
52
|
+
Event(
|
|
53
|
+
type="order.completed",
|
|
54
|
+
data={
|
|
55
|
+
"order_id": "ord_12345",
|
|
56
|
+
"amount": 99.99,
|
|
57
|
+
"currency": "USD",
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
print(f"Event created: {event.event_id}")
|
|
63
|
+
print(f"Deliveries created: {event.deliveries_created}")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## API Reference
|
|
67
|
+
|
|
68
|
+
### Events
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from webhook_platform import Event
|
|
72
|
+
|
|
73
|
+
# Send event with idempotency key
|
|
74
|
+
event = client.events.send(
|
|
75
|
+
Event(type="order.completed", data={"order_id": "123"}),
|
|
76
|
+
idempotency_key="unique-key",
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Endpoints
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from webhook_platform import EndpointCreateParams, EndpointUpdateParams
|
|
84
|
+
|
|
85
|
+
# Create endpoint
|
|
86
|
+
endpoint = client.endpoints.create(
|
|
87
|
+
project_id,
|
|
88
|
+
EndpointCreateParams(
|
|
89
|
+
url="https://api.example.com/webhooks",
|
|
90
|
+
description="Production webhooks",
|
|
91
|
+
enabled=True,
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# List endpoints
|
|
96
|
+
endpoints = client.endpoints.list(project_id)
|
|
97
|
+
|
|
98
|
+
# Update endpoint
|
|
99
|
+
client.endpoints.update(
|
|
100
|
+
project_id,
|
|
101
|
+
endpoint_id,
|
|
102
|
+
EndpointUpdateParams(enabled=False),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Delete endpoint
|
|
106
|
+
client.endpoints.delete(project_id, endpoint_id)
|
|
107
|
+
|
|
108
|
+
# Rotate secret
|
|
109
|
+
updated = client.endpoints.rotate_secret(project_id, endpoint_id)
|
|
110
|
+
print(f"New secret: {updated.secret}")
|
|
111
|
+
|
|
112
|
+
# Test endpoint connectivity
|
|
113
|
+
result = client.endpoints.test(project_id, endpoint_id)
|
|
114
|
+
print(f"Test {'passed' if result.success else 'failed'}: {result.latency_ms}ms")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Subscriptions
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from webhook_platform import SubscriptionCreateParams
|
|
121
|
+
|
|
122
|
+
# Subscribe endpoint to event types
|
|
123
|
+
subscription = client.subscriptions.create(
|
|
124
|
+
project_id,
|
|
125
|
+
SubscriptionCreateParams(
|
|
126
|
+
endpoint_id=endpoint.id,
|
|
127
|
+
event_types=["order.completed", "order.cancelled"],
|
|
128
|
+
enabled=True,
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# List subscriptions
|
|
133
|
+
subscriptions = client.subscriptions.list(project_id)
|
|
134
|
+
|
|
135
|
+
# Update subscription
|
|
136
|
+
client.subscriptions.update(
|
|
137
|
+
project_id,
|
|
138
|
+
subscription_id,
|
|
139
|
+
event_types=["order.*"],
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Delete subscription
|
|
143
|
+
client.subscriptions.delete(project_id, subscription_id)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Deliveries
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from webhook_platform import DeliveryListParams, DeliveryStatus
|
|
150
|
+
|
|
151
|
+
# List deliveries with filters
|
|
152
|
+
deliveries = client.deliveries.list(
|
|
153
|
+
project_id,
|
|
154
|
+
DeliveryListParams(status=DeliveryStatus.FAILED, page=0, size=20),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
print(f"Total failed: {deliveries.total_elements}")
|
|
158
|
+
|
|
159
|
+
# Get delivery attempts
|
|
160
|
+
attempts = client.deliveries.get_attempts(delivery_id)
|
|
161
|
+
for attempt in attempts:
|
|
162
|
+
print(f"Attempt {attempt.attempt_number}: {attempt.http_status} ({attempt.latency_ms}ms)")
|
|
163
|
+
|
|
164
|
+
# Replay failed delivery
|
|
165
|
+
client.deliveries.replay(delivery_id)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Webhook Signature Verification
|
|
169
|
+
|
|
170
|
+
Verify incoming webhooks in your endpoint:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from webhook_platform import verify_signature, construct_event, WebhookPlatformError
|
|
174
|
+
|
|
175
|
+
# Flask example
|
|
176
|
+
from flask import Flask, request
|
|
177
|
+
|
|
178
|
+
app = Flask(__name__)
|
|
179
|
+
|
|
180
|
+
@app.route("/webhooks", methods=["POST"])
|
|
181
|
+
def handle_webhook():
|
|
182
|
+
payload = request.get_data(as_text=True)
|
|
183
|
+
headers = dict(request.headers)
|
|
184
|
+
secret = os.environ["WEBHOOK_SECRET"]
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
# Option 1: Just verify
|
|
188
|
+
verify_signature(payload, headers.get("X-Signature", ""), secret)
|
|
189
|
+
|
|
190
|
+
# Option 2: Verify and parse
|
|
191
|
+
event = construct_event(payload, headers, secret)
|
|
192
|
+
|
|
193
|
+
print(f"Received {event.type}: {event.data}")
|
|
194
|
+
|
|
195
|
+
# Handle the event
|
|
196
|
+
if event.type == "order.completed":
|
|
197
|
+
handle_order_completed(event.data)
|
|
198
|
+
|
|
199
|
+
return "OK", 200
|
|
200
|
+
|
|
201
|
+
except WebhookPlatformError as e:
|
|
202
|
+
print(f"Webhook verification failed: {e.message}")
|
|
203
|
+
return "Invalid signature", 400
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### FastAPI Example
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from fastapi import FastAPI, Request, HTTPException
|
|
210
|
+
from webhook_platform import construct_event, WebhookPlatformError
|
|
211
|
+
|
|
212
|
+
app = FastAPI()
|
|
213
|
+
|
|
214
|
+
@app.post("/webhooks")
|
|
215
|
+
async def handle_webhook(request: Request):
|
|
216
|
+
payload = await request.body()
|
|
217
|
+
headers = dict(request.headers)
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
event = construct_event(
|
|
221
|
+
payload.decode("utf-8"),
|
|
222
|
+
headers,
|
|
223
|
+
os.environ["WEBHOOK_SECRET"],
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Process event...
|
|
227
|
+
return {"status": "ok"}
|
|
228
|
+
|
|
229
|
+
except WebhookPlatformError as e:
|
|
230
|
+
raise HTTPException(status_code=400, detail=e.message)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Error Handling
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from webhook_platform import (
|
|
237
|
+
WebhookPlatformError,
|
|
238
|
+
RateLimitError,
|
|
239
|
+
AuthenticationError,
|
|
240
|
+
ValidationError,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
try:
|
|
244
|
+
client.events.send(Event(type="test", data={}))
|
|
245
|
+
except RateLimitError as e:
|
|
246
|
+
# Wait and retry
|
|
247
|
+
print(f"Rate limited. Retry after {e.retry_after_ms}ms")
|
|
248
|
+
time.sleep(e.retry_after_ms / 1000)
|
|
249
|
+
except AuthenticationError:
|
|
250
|
+
print("Invalid API key")
|
|
251
|
+
except ValidationError as e:
|
|
252
|
+
print(f"Validation failed: {e.field_errors}")
|
|
253
|
+
except WebhookPlatformError as e:
|
|
254
|
+
print(f"Error {e.status}: {e.message}")
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Configuration
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
client = WebhookPlatform(
|
|
261
|
+
api_key="wh_live_xxx", # Required: Your API key
|
|
262
|
+
base_url="https://api.example.com", # Optional: API base URL
|
|
263
|
+
timeout=30, # Optional: Request timeout in seconds (default: 30)
|
|
264
|
+
)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Type Hints
|
|
268
|
+
|
|
269
|
+
This SDK includes full type hints for better IDE support:
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
from webhook_platform import (
|
|
273
|
+
Event,
|
|
274
|
+
EventResponse,
|
|
275
|
+
Endpoint,
|
|
276
|
+
Delivery,
|
|
277
|
+
DeliveryStatus,
|
|
278
|
+
)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Development
|
|
282
|
+
|
|
283
|
+
### Running Tests
|
|
284
|
+
|
|
285
|
+
**Local (requires Python 3.8+):**
|
|
286
|
+
```bash
|
|
287
|
+
pip install -e ".[dev]"
|
|
288
|
+
pytest
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Docker:**
|
|
292
|
+
```bash
|
|
293
|
+
docker run --rm -v $(pwd):/app -w /app python:3.11-slim sh -c "pip install -e '.[dev]' && pytest"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
MIT
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# webhook-platform
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [Webhook Platform](https://github.com/vadymkykalo/webhook-platform).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install webhook-platform
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from webhook_platform import WebhookPlatform, Event
|
|
15
|
+
|
|
16
|
+
client = WebhookPlatform(
|
|
17
|
+
api_key="wh_live_your_api_key",
|
|
18
|
+
base_url="http://localhost:8080", # optional
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Send an event
|
|
22
|
+
event = client.events.send(
|
|
23
|
+
Event(
|
|
24
|
+
type="order.completed",
|
|
25
|
+
data={
|
|
26
|
+
"order_id": "ord_12345",
|
|
27
|
+
"amount": 99.99,
|
|
28
|
+
"currency": "USD",
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
print(f"Event created: {event.event_id}")
|
|
34
|
+
print(f"Deliveries created: {event.deliveries_created}")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API Reference
|
|
38
|
+
|
|
39
|
+
### Events
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from webhook_platform import Event
|
|
43
|
+
|
|
44
|
+
# Send event with idempotency key
|
|
45
|
+
event = client.events.send(
|
|
46
|
+
Event(type="order.completed", data={"order_id": "123"}),
|
|
47
|
+
idempotency_key="unique-key",
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Endpoints
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from webhook_platform import EndpointCreateParams, EndpointUpdateParams
|
|
55
|
+
|
|
56
|
+
# Create endpoint
|
|
57
|
+
endpoint = client.endpoints.create(
|
|
58
|
+
project_id,
|
|
59
|
+
EndpointCreateParams(
|
|
60
|
+
url="https://api.example.com/webhooks",
|
|
61
|
+
description="Production webhooks",
|
|
62
|
+
enabled=True,
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# List endpoints
|
|
67
|
+
endpoints = client.endpoints.list(project_id)
|
|
68
|
+
|
|
69
|
+
# Update endpoint
|
|
70
|
+
client.endpoints.update(
|
|
71
|
+
project_id,
|
|
72
|
+
endpoint_id,
|
|
73
|
+
EndpointUpdateParams(enabled=False),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Delete endpoint
|
|
77
|
+
client.endpoints.delete(project_id, endpoint_id)
|
|
78
|
+
|
|
79
|
+
# Rotate secret
|
|
80
|
+
updated = client.endpoints.rotate_secret(project_id, endpoint_id)
|
|
81
|
+
print(f"New secret: {updated.secret}")
|
|
82
|
+
|
|
83
|
+
# Test endpoint connectivity
|
|
84
|
+
result = client.endpoints.test(project_id, endpoint_id)
|
|
85
|
+
print(f"Test {'passed' if result.success else 'failed'}: {result.latency_ms}ms")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Subscriptions
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from webhook_platform import SubscriptionCreateParams
|
|
92
|
+
|
|
93
|
+
# Subscribe endpoint to event types
|
|
94
|
+
subscription = client.subscriptions.create(
|
|
95
|
+
project_id,
|
|
96
|
+
SubscriptionCreateParams(
|
|
97
|
+
endpoint_id=endpoint.id,
|
|
98
|
+
event_types=["order.completed", "order.cancelled"],
|
|
99
|
+
enabled=True,
|
|
100
|
+
),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# List subscriptions
|
|
104
|
+
subscriptions = client.subscriptions.list(project_id)
|
|
105
|
+
|
|
106
|
+
# Update subscription
|
|
107
|
+
client.subscriptions.update(
|
|
108
|
+
project_id,
|
|
109
|
+
subscription_id,
|
|
110
|
+
event_types=["order.*"],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Delete subscription
|
|
114
|
+
client.subscriptions.delete(project_id, subscription_id)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Deliveries
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from webhook_platform import DeliveryListParams, DeliveryStatus
|
|
121
|
+
|
|
122
|
+
# List deliveries with filters
|
|
123
|
+
deliveries = client.deliveries.list(
|
|
124
|
+
project_id,
|
|
125
|
+
DeliveryListParams(status=DeliveryStatus.FAILED, page=0, size=20),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
print(f"Total failed: {deliveries.total_elements}")
|
|
129
|
+
|
|
130
|
+
# Get delivery attempts
|
|
131
|
+
attempts = client.deliveries.get_attempts(delivery_id)
|
|
132
|
+
for attempt in attempts:
|
|
133
|
+
print(f"Attempt {attempt.attempt_number}: {attempt.http_status} ({attempt.latency_ms}ms)")
|
|
134
|
+
|
|
135
|
+
# Replay failed delivery
|
|
136
|
+
client.deliveries.replay(delivery_id)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Webhook Signature Verification
|
|
140
|
+
|
|
141
|
+
Verify incoming webhooks in your endpoint:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from webhook_platform import verify_signature, construct_event, WebhookPlatformError
|
|
145
|
+
|
|
146
|
+
# Flask example
|
|
147
|
+
from flask import Flask, request
|
|
148
|
+
|
|
149
|
+
app = Flask(__name__)
|
|
150
|
+
|
|
151
|
+
@app.route("/webhooks", methods=["POST"])
|
|
152
|
+
def handle_webhook():
|
|
153
|
+
payload = request.get_data(as_text=True)
|
|
154
|
+
headers = dict(request.headers)
|
|
155
|
+
secret = os.environ["WEBHOOK_SECRET"]
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
# Option 1: Just verify
|
|
159
|
+
verify_signature(payload, headers.get("X-Signature", ""), secret)
|
|
160
|
+
|
|
161
|
+
# Option 2: Verify and parse
|
|
162
|
+
event = construct_event(payload, headers, secret)
|
|
163
|
+
|
|
164
|
+
print(f"Received {event.type}: {event.data}")
|
|
165
|
+
|
|
166
|
+
# Handle the event
|
|
167
|
+
if event.type == "order.completed":
|
|
168
|
+
handle_order_completed(event.data)
|
|
169
|
+
|
|
170
|
+
return "OK", 200
|
|
171
|
+
|
|
172
|
+
except WebhookPlatformError as e:
|
|
173
|
+
print(f"Webhook verification failed: {e.message}")
|
|
174
|
+
return "Invalid signature", 400
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### FastAPI Example
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from fastapi import FastAPI, Request, HTTPException
|
|
181
|
+
from webhook_platform import construct_event, WebhookPlatformError
|
|
182
|
+
|
|
183
|
+
app = FastAPI()
|
|
184
|
+
|
|
185
|
+
@app.post("/webhooks")
|
|
186
|
+
async def handle_webhook(request: Request):
|
|
187
|
+
payload = await request.body()
|
|
188
|
+
headers = dict(request.headers)
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
event = construct_event(
|
|
192
|
+
payload.decode("utf-8"),
|
|
193
|
+
headers,
|
|
194
|
+
os.environ["WEBHOOK_SECRET"],
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Process event...
|
|
198
|
+
return {"status": "ok"}
|
|
199
|
+
|
|
200
|
+
except WebhookPlatformError as e:
|
|
201
|
+
raise HTTPException(status_code=400, detail=e.message)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Error Handling
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from webhook_platform import (
|
|
208
|
+
WebhookPlatformError,
|
|
209
|
+
RateLimitError,
|
|
210
|
+
AuthenticationError,
|
|
211
|
+
ValidationError,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
client.events.send(Event(type="test", data={}))
|
|
216
|
+
except RateLimitError as e:
|
|
217
|
+
# Wait and retry
|
|
218
|
+
print(f"Rate limited. Retry after {e.retry_after_ms}ms")
|
|
219
|
+
time.sleep(e.retry_after_ms / 1000)
|
|
220
|
+
except AuthenticationError:
|
|
221
|
+
print("Invalid API key")
|
|
222
|
+
except ValidationError as e:
|
|
223
|
+
print(f"Validation failed: {e.field_errors}")
|
|
224
|
+
except WebhookPlatformError as e:
|
|
225
|
+
print(f"Error {e.status}: {e.message}")
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Configuration
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
client = WebhookPlatform(
|
|
232
|
+
api_key="wh_live_xxx", # Required: Your API key
|
|
233
|
+
base_url="https://api.example.com", # Optional: API base URL
|
|
234
|
+
timeout=30, # Optional: Request timeout in seconds (default: 30)
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Type Hints
|
|
239
|
+
|
|
240
|
+
This SDK includes full type hints for better IDE support:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from webhook_platform import (
|
|
244
|
+
Event,
|
|
245
|
+
EventResponse,
|
|
246
|
+
Endpoint,
|
|
247
|
+
Delivery,
|
|
248
|
+
DeliveryStatus,
|
|
249
|
+
)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Development
|
|
253
|
+
|
|
254
|
+
### Running Tests
|
|
255
|
+
|
|
256
|
+
**Local (requires Python 3.8+):**
|
|
257
|
+
```bash
|
|
258
|
+
pip install -e ".[dev]"
|
|
259
|
+
pytest
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Docker:**
|
|
263
|
+
```bash
|
|
264
|
+
docker run --rm -v $(pwd):/app -w /app python:3.11-slim sh -c "pip install -e '.[dev]' && pytest"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
MIT
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "webhook-platform"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Official Python SDK for Webhook Platform"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Webhook Platform", email = "hello@webhook-platform.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["webhook", "webhooks", "api", "events", "delivery"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"requests>=2.28.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0.0",
|
|
35
|
+
"pytest-cov>=4.0.0",
|
|
36
|
+
"mypy>=1.0.0",
|
|
37
|
+
"types-requests>=2.28.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/vadymkykalo/webhook-platform"
|
|
42
|
+
Repository = "https://github.com/vadymkykalo/webhook-platform"
|
|
43
|
+
Documentation = "https://github.com/vadymkykalo/webhook-platform#readme"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["."]
|
|
47
|
+
|
|
48
|
+
[tool.mypy]
|
|
49
|
+
python_version = "3.8"
|
|
50
|
+
strict = true
|
|
File without changes
|