Skip to content

Commit c81b480

Browse files
feat(webhooks): type get_webhook_sample_payload return as TypedDict union
Parity with `tango-node`'s `WebhookSamplePayloadResponse` discriminated union. The endpoint can return one of two response shapes depending on whether `event_type` is supplied: - Single-event: `{event_type, sample_delivery, signature_header, note}` - All-events: `{samples, usage, signature_header, note}` Added `WebhookSampleDelivery`, `WebhookSamplePayloadSingleResponse`, `WebhookSamplePayloadAllResponse`, and the union alias `WebhookSamplePayloadResponse` as TypedDict classes (structural, no runtime conversion). Exported from the top-level `tango` package and used as the return annotation on `client.get_webhook_sample_payload()`. No behavior change — just better static typing. Verified against the live API: - single (`alerts.contract.match`): returns 4 keys matching the Single shape - all: returns 4 keys matching the All shape All 285 unit tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6cb9b91 commit c81b480

3 files changed

Lines changed: 41 additions & 5 deletions

File tree

tango/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
WebhookEndpoint,
2525
WebhookEventType,
2626
WebhookEventTypesResponse,
27+
WebhookSampleDelivery,
28+
WebhookSamplePayloadAllResponse,
29+
WebhookSamplePayloadResponse,
30+
WebhookSamplePayloadSingleResponse,
2731
WebhookTestDeliveryResult,
2832
)
2933
from .shapes import (
@@ -62,6 +66,10 @@
6266
"WebhookEndpoint",
6367
"WebhookEventType",
6468
"WebhookEventTypesResponse",
69+
"WebhookSampleDelivery",
70+
"WebhookSamplePayloadAllResponse",
71+
"WebhookSamplePayloadResponse",
72+
"WebhookSamplePayloadSingleResponse",
6573
"WebhookTestDeliveryResult",
6674
"ShapeParser",
6775
"ModelFactory",

tango/client.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
WebhookEndpoint,
4747
WebhookEventType,
4848
WebhookEventTypesResponse,
49+
WebhookSamplePayloadResponse,
4950
WebhookTestDeliveryResult,
5051
)
5152
from tango.shapes import (
@@ -2592,17 +2593,20 @@ def test_webhook_delivery(self, endpoint_id: str | None = None) -> WebhookTestDe
25922593
test_payload=data.get("test_payload"),
25932594
)
25942595

2595-
def get_webhook_sample_payload(self, event_type: str | None = None) -> dict[str, Any]:
2596+
def get_webhook_sample_payload(
2597+
self, event_type: str | None = None
2598+
) -> WebhookSamplePayloadResponse:
25962599
"""
25972600
Fetch Tango-shaped sample webhook deliveries.
25982601
2599-
- If event_type is provided, returns the single-event response.
2600-
- Otherwise returns a `samples` mapping for all supported event types.
2602+
- If ``event_type`` is provided, returns a :class:`WebhookSamplePayloadSingleResponse`.
2603+
- Otherwise returns a :class:`WebhookSamplePayloadAllResponse` with a ``samples``
2604+
mapping keyed by event type.
26012605
"""
26022606
params: dict[str, Any] = {}
26032607
if event_type:
26042608
params["event_type"] = event_type
2605-
return self._get("/api/webhooks/endpoints/sample-payload/", params)
2609+
return self._get("/api/webhooks/endpoints/sample-payload/", params) # type: ignore[return-value]
26062610

26072611
# ============================================================================
26082612
# Webhook Alerts (filter-based subscriptions)

tango/models.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from dataclasses import dataclass
1414
from datetime import date, datetime
1515
from decimal import Decimal
16-
from typing import Any, Final, Literal, TypeVar
16+
from typing import Any, Final, Literal, TypedDict, TypeVar
1717

1818
T = TypeVar("T")
1919

@@ -580,6 +580,30 @@ class WebhookEventTypesResponse:
580580
event_types: list[WebhookEventType]
581581

582582

583+
class WebhookSampleDelivery(TypedDict):
584+
timestamp: str
585+
events: list[dict[str, Any]]
586+
587+
588+
class WebhookSamplePayloadSingleResponse(TypedDict):
589+
event_type: str
590+
sample_delivery: WebhookSampleDelivery
591+
signature_header: str
592+
note: str
593+
594+
595+
class WebhookSamplePayloadAllResponse(TypedDict):
596+
samples: dict[str, dict[str, Any]]
597+
usage: str
598+
signature_header: str
599+
note: str
600+
601+
602+
WebhookSamplePayloadResponse = (
603+
WebhookSamplePayloadSingleResponse | WebhookSamplePayloadAllResponse
604+
)
605+
606+
583607
@dataclass
584608
class WebhookEndpoint:
585609
id: str

0 commit comments

Comments
 (0)