Skip to content

Conversation

@KMKoushik
Copy link
Member

@KMKoushik KMKoushik commented Jan 18, 2026

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

Summary by cubic

Adds secure webhook verification and typed event handling to the Python SDK, matching the JS SDK. Provides HMAC-SHA256 signature checks with timestamp tolerance and a simple API to construct verified events.

  • New Features
    • Webhooks class with verify() and construct_event(); UseSend.webhooks(secret) factory.
    • HMAC-SHA256 signature verification with timing-safe compare and timestamp tolerance (default 5 minutes).
    • Typed webhook events and payloads for 18 events across email, contact, domain, and test.
    • WebhookVerificationError with clear error codes.
    • Exported webhook header constants and types via init.

Written for commit fbb8197. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Added webhook verification and event parsing functionality to the Python SDK.
    • Introduced support for email, contact, domain, and test webhook events with comprehensive type definitions.
    • Added webhooks() method to access webhook handling capabilities.
    • Added WebhookVerificationError for webhook-specific error handling.

✏️ Tip: You can customize this high-level summary in your review settings.

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
@vercel
Copy link

vercel bot commented Jan 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
unsend-marketing Ready Ready Preview, Comment Jan 18, 2026 8:59pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 18, 2026

Walkthrough

This pull request adds webhook support to the Python SDK. A new webhooks.py module is introduced containing the Webhooks class for validating webhook signatures, verifying timestamps, and parsing webhook payloads into typed events. Related types and payloads for email, contact, domain, and test webhook events are added to types.py. The main UseSend class gains a webhooks() method to instantiate webhook handlers. Public exports in __init__.py expose the Webhooks class, WebhookVerificationError exception, and header constants for integration into the SDK's public API.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(python-sdk): add webhook verification and event handling' clearly and specifically describes the main changes: adding webhook support with verification and event handling capabilities to the Python SDK.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/python-sdk/usesend/webhooks.py">

<violation number="1" location="packages/python-sdk/usesend/webhooks.py:287">
P2: Handle invalid UTF-8 payloads so decode errors surface as WebhookVerificationError rather than an uncaught UnicodeDecodeError.</violation>
</file>

<file name="packages/python-sdk/usesend/types.py">

<violation number="1" location="packages/python-sdk/usesend/types.py:472">
P2: EmailWebhookEventType includes events that require extra detail payloads, but EmailWebhookEvent only uses EmailBasePayloadFull. This makes type checking accept "email.bounced/failed/suppressed/opened/clicked" events without their required detail fields. Restrict EmailWebhookEventType to the base email events and rely on the specialized event types for the detailed ones.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

if isinstance(body, str):
return body
if isinstance(body, bytes):
return body.decode("utf-8")
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Handle invalid UTF-8 payloads so decode errors surface as WebhookVerificationError rather than an uncaught UnicodeDecodeError.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/python-sdk/usesend/webhooks.py, line 287:

<comment>Handle invalid UTF-8 payloads so decode errors surface as WebhookVerificationError rather than an uncaught UnicodeDecodeError.</comment>

<file context>
@@ -0,0 +1,320 @@
+    if isinstance(body, str):
+        return body
+    if isinstance(body, bytes):
+        return body.decode("utf-8")
+    raise WebhookVerificationError(
+        "INVALID_BODY",
</file context>
Fix with Cubic

"domain.deleted",
]

EmailWebhookEventType = Literal[
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: EmailWebhookEventType includes events that require extra detail payloads, but EmailWebhookEvent only uses EmailBasePayloadFull. This makes type checking accept "email.bounced/failed/suppressed/opened/clicked" events without their required detail fields. Restrict EmailWebhookEventType to the base email events and rely on the specialized event types for the detailed ones.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/python-sdk/usesend/types.py, line 472:

<comment>EmailWebhookEventType includes events that require extra detail payloads, but EmailWebhookEvent only uses EmailBasePayloadFull. This makes type checking accept "email.bounced/failed/suppressed/opened/clicked" events without their required detail fields. Restrict EmailWebhookEventType to the base email events and rely on the specialized event types for the detailed ones.</comment>

<file context>
@@ -449,3 +449,407 @@ class CampaignActionResponse(TypedDict, total=False):
+    "domain.deleted",
+]
+
+EmailWebhookEventType = Literal[
+    "email.queued",
+    "email.sent",
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants