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.
@@ -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
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes