Simple webhook sender and receiver with HMAC signatures and retry logic
Project description
py-webhook
Simple webhook sender and receiver for Python/FastAPI. Send webhooks with retry logic, receive with HMAC-SHA256 signature verification.
Features
- HMAC-SHA256 Signatures -- every webhook is signed and verified
- Retry Logic -- configurable retries with exponential backoff
- Async -- built on
httpxfor non-blocking I/O - FastAPI Integration -- drop-in
Depends()for automatic verification - Lightweight -- minimal dependencies, no magic
Installation
pip install py-webhook
Quick Start
Sending Webhooks
import asyncio
from pywebhook import WebhookSender
sender = WebhookSender(max_retries=3, timeout=10.0)
async def main():
response = await sender.send(
url="https://example.com/webhook",
event="order.created",
data={"order_id": 42, "total": 99.99},
secret="your-shared-secret",
)
print(f"Delivered: {response.status_code}")
asyncio.run(main())
The sender automatically:
- Generates a
WebhookPayloadwith a UUID, timestamp, event name, and your data - Signs the JSON body with HMAC-SHA256
- Sends headers:
X-Webhook-Signature,X-Webhook-Event,X-Webhook-Id - Retries failed requests with exponential backoff
Receiving Webhooks (FastAPI)
from fastapi import Depends, FastAPI
from pywebhook import WebhookReceiver
app = FastAPI()
receiver = WebhookReceiver()
@app.post("/webhook")
async def handle_webhook(payload: dict = Depends(receiver.handler("your-shared-secret"))):
print(f"Received event: {payload['event']}")
print(f"Data: {payload['data']}")
return {"status": "ok"}
The handler dependency automatically:
- Reads the raw request body
- Verifies the
X-Webhook-Signatureheader against the shared secret - Returns 401 if the signature is invalid
- Parses and returns the JSON payload
Manual Verification
from pywebhook import WebhookReceiver
receiver = WebhookReceiver()
body = b'{"event":"ping","data":{}}'
signature = "abc123..."
is_valid = receiver.verify(body, signature, secret="your-shared-secret")
Payload Model
from pywebhook import WebhookPayload
payload = WebhookPayload(event="user.signup", data={"user_id": 7})
print(payload.id) # auto-generated UUID
print(payload.timestamp) # auto-generated ISO 8601
print(payload.event) # "user.signup"
print(payload.data) # {"user_id": 7}
Configuration
| Parameter | Default | Description |
|---|---|---|
max_retries |
3 |
Number of delivery attempts |
timeout |
10.0 |
Request timeout in seconds |
backoff_base |
1.0 |
Base delay for exponential backoff (seconds) |
License
MIT -- see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pywebhook_lite-0.1.0.tar.gz.
File metadata
- Download URL: pywebhook_lite-0.1.0.tar.gz
- Upload date:
- Size: 6.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad0886134095e4024749e9b780a9f16c0117c700a808234de14bb96d2f75f512
|
|
| MD5 |
4a32b6b3477fb388babc4643ab406ba4
|
|
| BLAKE2b-256 |
bd01b1c9f3a2a80d8c4dd6c1f3d07ea57f5aab41562cfdd9ae898a0e95119948
|
File details
Details for the file pywebhook_lite-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pywebhook_lite-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0123aebf434c6aa7dff3998a14980e328692bf71085e866da0b8ffd78b5ff874
|
|
| MD5 |
cd3b1241f806a59277a88a660fdcba08
|
|
| BLAKE2b-256 |
41a32599eb365b3f59480db8d881f0a33c3046cda2ad077e65968fe2cc99ccc5
|