Files
GibSend/packages/python-sdk/example/webhook-test-project/README.md
T
KM Koushik 09bdb8aaad feat(python-sdk): add webhook verification and event handling (#344)
* feat(python-sdk): add webhook verification and event handling

Add webhook support to the Python SDK matching the JS SDK implementation:
- Add Webhooks class with verify() and construct_event() methods
- Implement HMAC-SHA256 signature verification with timing-safe comparison
- Add timestamp validation with configurable tolerance (default 5 minutes)
- Add comprehensive webhook event types (18 events: email, contact, domain, test)
- Add WebhookVerificationError with typed error codes
- Export webhook constants (headers) and types

* fix(python-sdk): harden webhook parsing and typing

Normalize invalid UTF-8 webhook payloads to INVALID_BODY errors so verify() safely returns false, and narrow base email webhook event types to avoid discriminated-union overlap. Add regression tests for both paths.

* chore(python-sdk): bump package version to 0.2.9

* feat(python-sdk): add local webhook test example project

Add a runnable Flask receiver and signed webhook sender under packages/python-sdk/example, and link it from the Python SDK README for local verification.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-08 08:18:14 +11:00

865 B

Webhook Test Project (Flask)

This example project helps you validate Python SDK webhook signature verification locally.

What it includes

  • receiver.py: local webhook endpoint that verifies and parses events
  • send_test_webhook.py: sends a signed test webhook request to your local endpoint

Setup

cd packages/python-sdk/example/webhook-test-project
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Run

Terminal 1:

python receiver.py

Terminal 2:

python send_test_webhook.py

You should see:

  • 200 response from the receiver
  • parsed webhook event output in the receiver terminal

Environment variables

  • USESEND_WEBHOOK_SECRET (default: whsec_test)
  • WEBHOOK_URL (default: http://127.0.0.1:8000/webhook)

Use the same USESEND_WEBHOOK_SECRET for both scripts.