Skip to content

Commit f5929ab

Browse files
author
bird-release[bot]
committed
Release v0.11.0 (sdk-python/v0.11.0)
1 parent 24135dd commit f5929ab

4 files changed

Lines changed: 58 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 0.11.0
4+
5+
- Add the `rejected` WhatsApp message delivery status, returned when the recipient is on the workspace's suppression list.
6+
- Add the `whatsapp.rejected` webhook event, delivered when Bird rejects a WhatsApp message before sending because the recipient is on the workspace's suppression list.
7+
- Rename voice call webhook event types from voice.call.* to voice_call.* (single-dot resource convention; events were never emitted, so no delivered payload changes)
8+
39
## 0.10.0
410

511
- Add sms.tfn_verification webhook event types

src/bird/_event_types.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@ class WebhookEventType:
5454
SMS_TFN_VERIFICATION_REJECTED: Final = "sms.tfn_verification.rejected"
5555
SMS_TFN_VERIFICATION_SUBMITTED: Final = "sms.tfn_verification.submitted"
5656
SMS_UNDELIVERED: Final = "sms.undelivered"
57-
VOICE_CALL_ANSWERED: Final = "voice.call.answered"
58-
VOICE_CALL_ENDED: Final = "voice.call.ended"
59-
VOICE_CALL_INITIATED: Final = "voice.call.initiated"
57+
VOICE_CALL_ANSWERED: Final = "voice_call.answered"
58+
VOICE_CALL_ENDED: Final = "voice_call.ended"
59+
VOICE_CALL_INITIATED: Final = "voice_call.initiated"
6060
WHATSAPP_ACCEPTED: Final = "whatsapp.accepted"
6161
WHATSAPP_DELIVERED: Final = "whatsapp.delivered"
6262
WHATSAPP_FAILED: Final = "whatsapp.failed"
6363
WHATSAPP_READ: Final = "whatsapp.read"
64+
WHATSAPP_REJECTED: Final = "whatsapp.rejected"
6465
WHATSAPP_SENT: Final = "whatsapp.sent"

src/bird/_generated.py

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,7 @@ class WhatsAppMessageStatus(str, Enum):
24412441
sent = 'sent'
24422442
delivered = 'delivered'
24432443
failed = 'failed'
2444+
rejected = 'rejected'
24442445
canceled = 'canceled'
24452446
received = 'received'
24462447

@@ -2557,7 +2558,7 @@ class WhatsAppError(BaseModel):
25572558
code: Annotated[
25582559
str,
25592560
Field(
2560-
description='Bird-stable failure reason, uniform whether the failure happened internally or was reported by the WhatsApp network. `insufficient_balance`: the workspace could not afford the send. `price_not_found`: no price was configured for this destination/template combination. `internal_error`: an unexpected Bird-side failure. `undeliverable`: the recipient could not be reached (for example not on WhatsApp, or the number is invalid). `service_window_expired`: the 24-hour customer care window has closed and a free-form message cannot be sent; send a template instead. `rate_limited`: the send was throttled. Open enum: new codes may be added over time, so treat any unrecognized value as a future code rather than an error.\n',
2561+
description="Failure reason, uniform whether the failure happened internally or was reported by the WhatsApp network. `insufficient_balance`: the workspace could not afford the send. `price_not_found`: no price was configured for this destination/template combination. `internal_error`: an unexpected Bird-side failure. `undeliverable`: the recipient could not be reached (for example not on WhatsApp, or the number is invalid). `service_window_expired`: the 24-hour customer care window has closed and a free-form message cannot be sent; send a template instead. `rate_limited`: the send was throttled. `recipient_suppressed`: the recipient is on the workspace's suppression list; the message was rejected before sending. Open enum: new codes may be added over time, so treat any unrecognized value as a future code rather than an error.\n",
25612562
min_length=1,
25622563
),
25632564
]
@@ -6878,16 +6879,16 @@ class EventVoiceCallAnsweredData(EventVoiceBase):
68786879

68796880

68806881
class Type41(str, Enum):
6881-
voice_call_answered = 'voice.call.answered'
6882+
voice_call_answered = 'voice_call.answered'
68826883

68836884

68846885
class EventVoiceCallAnswered(BaseModel):
68856886
model_config = ConfigDict(
68866887
extra='allow',
68876888
)
68886889
type: Annotated[
6889-
Literal['voice.call.answered'],
6890-
Field(description='Event type.', examples=['voice.call.answered']),
6890+
Literal['voice_call.answered'],
6891+
Field(description='Event type.', examples=['voice_call.answered']),
68916892
]
68926893
timestamp: Annotated[
68936894
str,
@@ -6944,16 +6945,16 @@ class EventVoiceCallEndedData(EventVoiceBase):
69446945

69456946

69466947
class Type42(str, Enum):
6947-
voice_call_ended = 'voice.call.ended'
6948+
voice_call_ended = 'voice_call.ended'
69486949

69496950

69506951
class EventVoiceCallEnded(BaseModel):
69516952
model_config = ConfigDict(
69526953
extra='allow',
69536954
)
69546955
type: Annotated[
6955-
Literal['voice.call.ended'],
6956-
Field(description='Event type.', examples=['voice.call.ended']),
6956+
Literal['voice_call.ended'],
6957+
Field(description='Event type.', examples=['voice_call.ended']),
69576958
]
69586959
timestamp: Annotated[
69596960
str,
@@ -6973,16 +6974,16 @@ class EventVoiceCallInitiatedData(EventVoiceBase):
69736974

69746975

69756976
class Type43(str, Enum):
6976-
voice_call_initiated = 'voice.call.initiated'
6977+
voice_call_initiated = 'voice_call.initiated'
69776978

69786979

69796980
class EventVoiceCallInitiated(BaseModel):
69806981
model_config = ConfigDict(
69816982
extra='allow',
69826983
)
69836984
type: Annotated[
6984-
Literal['voice.call.initiated'],
6985-
Field(description='Event type.', examples=['voice.call.initiated']),
6985+
Literal['voice_call.initiated'],
6986+
Field(description='Event type.', examples=['voice_call.initiated']),
69866987
]
69876988
timestamp: Annotated[
69886989
str,
@@ -7170,13 +7171,46 @@ class EventWhatsAppRead(BaseModel):
71707171
data: EventWhatsAppReadData
71717172

71727173

7173-
class EventWhatsAppSentData(EventWhatsAppBase):
7174+
class EventWhatsAppRejectedData(EventWhatsAppBase):
71747175
model_config = ConfigDict(
71757176
extra='allow',
71767177
)
7178+
error: Annotated[
7179+
WhatsAppError | None,
7180+
Field(description='Why the message was rejected before sending.'),
7181+
]
71777182

71787183

71797184
class Type48(str, Enum):
7185+
whatsapp_rejected = 'whatsapp.rejected'
7186+
7187+
7188+
class EventWhatsAppRejected(BaseModel):
7189+
model_config = ConfigDict(
7190+
extra='allow',
7191+
)
7192+
type: Annotated[
7193+
Literal['whatsapp.rejected'],
7194+
Field(description='Event type.', examples=['whatsapp.rejected']),
7195+
]
7196+
timestamp: Annotated[
7197+
str,
7198+
Field(
7199+
description='Time the rejection was recorded.',
7200+
examples=['2026-07-23 12:00:00+00:00'],
7201+
min_length=1,
7202+
),
7203+
]
7204+
data: EventWhatsAppRejectedData
7205+
7206+
7207+
class EventWhatsAppSentData(EventWhatsAppBase):
7208+
model_config = ConfigDict(
7209+
extra='allow',
7210+
)
7211+
7212+
7213+
class Type49(str, Enum):
71807214
whatsapp_sent = 'whatsapp.sent'
71817215

71827216

@@ -7243,6 +7277,7 @@ class WebhookEvent(
72437277
| EventWhatsAppDelivered
72447278
| EventWhatsAppFailed
72457279
| EventWhatsAppRead
7280+
| EventWhatsAppRejected
72467281
| EventWhatsAppSent
72477282
]
72487283
):
@@ -7289,6 +7324,7 @@ class WebhookEvent(
72897324
| EventWhatsAppDelivered
72907325
| EventWhatsAppFailed
72917326
| EventWhatsAppRead
7327+
| EventWhatsAppRejected
72927328
| EventWhatsAppSent,
72937329
Field(
72947330
description="Discriminated union of every webhook event the Bird platform emits.\n\nEach variant is the full delivery body: `type` names the event, `timestamp` is when the\nevent occurred, and `data` carries the event-specific payload. The `type` property\nselects the variant, and the generated SDK types narrow on it, so your code can switch\non the event id and read the variant-specific payload fields without casting.\n\nDelivery metadata (the event id and per-attempt signature headers) rides in HTTP headers\nper Standard Webhooks and is handled by the SDK's webhook verification helper, which\nreturns one of these variants. See the [webhooks guide](/docs/guides/webhooks) for\nheader names and the verification recipe.\n",

src/bird/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.10.0"
1+
__version__ = "0.11.0"

0 commit comments

Comments
 (0)