Skip to main content

philiprehberger-webhook-relay-client

PyPI version Last updated

Python SDK + HMAC verifier for the Webhook Relay API. Python 3.10+, zero runtime dependencies, PEP 561 typed.

Installation

pip install philiprehberger-webhook-relay-client

Verify an incoming webhook (receiver side)

from philiprehberger_webhook_relay_client import verify_signature

def webhook_handler(request):
    raw = request.body  # bytes — DO NOT json.loads + re-dumps
    if not verify_signature(
        secret=os.environ["WEBHOOK_SECRET"],
        body=raw,
        header=request.headers.get("X-Webhook-Signature"),
    ):
        return Response("Bad signature", status=400)

    event = json.loads(raw)
    # ... handle event

The body must be the exact bytes received. json.dumps(json.loads(...)) will reorder keys or change whitespace and break the signature.

The format matches Stripe and Svix (t=<ts>,v1=<hex> over "{ts}.{body}" with HMAC-SHA256), so the same verifier accepts signatures from any sender using that convention.

Send an event (sender side)

from philiprehberger_webhook_relay_client import WebhookRelayClient

relay = WebhookRelayClient(api_key=os.environ["WEBHOOK_RELAY_KEY"])

event = relay.ingest(
    event_type="order.created",
    payload={"order_id": 42},
    idempotency_key="order-42-created",
)
print(event["id"], event["deliveries_summary"])

The client raises WebhookRelayError on 4xx/5xx with the RFC 7807 problem payload preserved:

from philiprehberger_webhook_relay_client import WebhookRelayError

try:
    relay.ingest(event_type="", payload={})
except WebhookRelayError as err:
    print(err.status, err.title, err.detail)

Subscriptions, deliveries, and the rest

sub = relay.create_subscription(
    url="https://my-app.example.com/webhooks",
    name="orders inbound",
    event_filter="order.*",
)
print(sub["signing_secret"])    # store this now — shown only once

page = relay.list_deliveries(status="failed")

relay.pause_subscription(sub["id"])
relay.resume_subscription(sub["id"])
rotated = relay.rotate_subscription_secret(sub["id"])

For endpoints the typed surface doesn't cover (manual retry, dead-letters, webhook test probe) drop down to request():

relay.request("POST", f"/v1/deliveries/{delivery_id}/retry")

Compatible senders

Use sign_body to stand up a compatible sender for testing, or to verify your verifier matches the wire format:

from philiprehberger_webhook_relay_client import sign_body

signed = sign_body("whsec_shared", raw_body)
requests.post(receiver_url, data=raw_body, headers={"X-Webhook-Signature": signed.header})

Pointing at a different host

relay = WebhookRelayClient(
    api_key=api_key,
    base_url="https://relay.staging.internal",
)

Links

License

MIT

Release files for philiprehberger-webhook-relay-client 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for philiprehberger-webhook-relay-client 0.1.0
File Size Uploaded
philiprehberger_webhook_relay_client-0.1.0.tar.gz 7.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for philiprehberger-webhook-relay-client 0.1.0
File Interpreter ABI Platform
philiprehberger_webhook_relay_client-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 15.2 kB

Release files / philiprehberger_webhook_relay_client-0.1.0.tar.gz

Download URL philiprehberger_webhook_relay_client-0.1.0.tar.gz
Size 7.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f603a353388973948c04a92a2dd8ebba265c93556d0ff53ec230d0931e7eb842
BLAKE2b-256 checksum
How to use checksums
33ee4230385c26ca9b1ab29f74f735485ffff1d9111a311ac1619adc77cacd0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / philiprehberger_webhook_relay_client-0.1.0-py3-none-any.whl

Download URL philiprehberger_webhook_relay_client-0.1.0-py3-none-any.whl
Size 7.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
198361c9fe252f6a051343821ab0f312dd3e8dfca05d75799f0e038512fb9bbf
BLAKE2b-256 checksum
How to use checksums
d5eee662b96ef5c9e182aa22516af5b8e99e0c35430808bed321d6a1fd32f0aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page