Skip to content

Commit 995c64b

Browse files
author
bird-release[bot]
committed
Release v0.41.0 (sdk-python/v0.41.0)
1 parent adc07ad commit 995c64b

9 files changed

Lines changed: 126 additions & 1 deletion

File tree

CHANGELOG.md

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

3+
## 0.41.0
4+
5+
- Add the `workspace` resource: `get()` returns the workspace the credential is scoped to, including its id, name, owning organization's id, and notification and logo settings.
6+
37
## 0.40.0
48

59
- A `404` from checking or advancing a verification now says that no verification matched the recipient: either none exists for the exact recipient given, or the most recent one is already resolved as verified, expired, or out of attempts. It also says when to create another — create one when the recipient has no verification, or the last one expired or ran out of attempts, and not when the recipient already passed. The error code is unchanged, so match it exactly as before; a `404` is not evidence the recipient failed to verify, so treat your own record of an earlier `success: true` as the outcome.

examples/examples.gen.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,3 +946,8 @@ async def _ex_141() -> None:
946946
components=[{"type": "body", "parameters": [{"type": "text", "text": "123456"}]}],
947947
)
948948
print(msg.id, msg.status)
949+
950+
951+
async def _ex_142() -> None:
952+
workspace = client.workspace.get()
953+
print(workspace.id, workspace.name)

examples/reference/workspace.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Example source for the generated workspace method.
2+
3+
Each bird:snippet region is harvested for the docs site + README; the keys match
4+
the surface catalog (workspace.get). Hand-written and type-checked (pyright
5+
includes examples/); nothing regenerates over it.
6+
"""
7+
8+
from bird import Bird
9+
10+
client = Bird()
11+
12+
13+
def workspace_get() -> None:
14+
workspace = client.workspace.get()
15+
print(workspace.id, workspace.name)

scripts/surface_ops.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"/v1/email/domains": {"get", "post"},
6868
"/v1/email/domains/{domain_id}": {"delete", "get", "patch"},
6969
"/v1/email/domains/{domain_id}/verify": {"post"},
70+
"/v1/workspace": {"get"},
7071
"/v1/preferences": {"get", "post"},
7172
"/v1/preferences/{preference_id}": {"delete", "get"},
7273
"/v1/contacts": {"get", "post"},

src/bird/_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from bird.resources.lookup_gen import AsyncLookup, Lookup
2929
from bird.resources.numbers import AsyncNumbers, Numbers
3030
from bird.resources.preferences import AsyncPreferences, Preferences
31+
from bird.resources.workspace_gen import AsyncWorkspaceResource, WorkspaceResource
3132
from bird.resources.realtime import AsyncRealtime, Realtime
3233
from bird.resources.sms import AsyncSms, Sms
3334
from bird.resources.sms_keyword_rules_gen import AsyncSmsKeywordRules, SmsKeywordRules
@@ -182,6 +183,7 @@ def __init__(
182183
self.lookup = Lookup(self)
183184
self.numbers = Numbers(self)
184185
self.preferences = Preferences(self)
186+
self.workspace = WorkspaceResource(self)
185187
self.webhooks = Webhooks(webhook_secret)
186188
self.realtime = Realtime(self, realtime_key, realtime_secret, realtime_encryption_master_key)
187189

@@ -308,6 +310,7 @@ def __init__(
308310
self.lookup = AsyncLookup(self)
309311
self.numbers = AsyncNumbers(self)
310312
self.preferences = AsyncPreferences(self)
313+
self.workspace = AsyncWorkspaceResource(self)
311314
self.webhooks = AsyncWebhooks(webhook_secret)
312315
self.realtime = AsyncRealtime(self, realtime_key, realtime_secret, realtime_encryption_master_key)
313316

src/bird/_generated.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,19 @@ class CountryCode(RootModel[str]):
225225
]
226226

227227

228+
class WorkspaceNotificationEmails(BaseModel):
229+
model_config = ConfigDict(
230+
extra="allow",
231+
)
232+
operational: Annotated[
233+
List[str] | None,
234+
Field(
235+
description="Addresses for operational notifications about this workspace (sending domain authentication failures, webhook endpoint degradation). When empty, these notifications go to the organization owners. Maximum 10 addresses.",
236+
examples=[["alerts@example.com"]],
237+
),
238+
] = None
239+
240+
228241
class Timestamps(BaseModel):
229242
model_config = ConfigDict(
230243
extra="allow",
@@ -233,6 +246,38 @@ class Timestamps(BaseModel):
233246
updated_at: Annotated[str, Field(examples=["2026-05-25T16:42:01Z"], min_length=1)]
234247

235248

249+
class Workspace(Timestamps):
250+
model_config = ConfigDict(
251+
extra="allow",
252+
)
253+
id: Annotated[
254+
str,
255+
Field(
256+
examples=["ws_01krdgeqcxet5s7t44vh8rt9mg"],
257+
min_length=1,
258+
pattern="^ws_[0-9a-hjkmnp-tv-z]{26}$",
259+
),
260+
]
261+
organization_id: Annotated[
262+
str,
263+
Field(
264+
examples=["org_01krdgeqcxet5s7t44vh8rt9mg"],
265+
min_length=1,
266+
pattern="^org_[0-9a-hjkmnp-tv-z]{26}$",
267+
),
268+
]
269+
name: Annotated[str, Field(examples=["Production"], min_length=1)]
270+
notification_emails: WorkspaceNotificationEmails
271+
logo_url: Annotated[
272+
str | None,
273+
Field(
274+
description="HTTPS URL to the current workspace logo. `null` when unset."
275+
),
276+
] = None
277+
created_at: str
278+
updated_at: str
279+
280+
236281
class RealtimeAppID(RootModel[str]):
237282
root: Annotated[
238283
str,

src/bird/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.40.0"
1+
__version__ = "0.41.0"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Code generated by surface-gen; DO NOT EDIT.
2+
3+
from __future__ import annotations
4+
5+
from bird._generated import (
6+
Workspace,
7+
)
8+
from bird._resource import AsyncResource, Resource
9+
from bird._types import RequestOptions
10+
11+
12+
class WorkspaceResource(Resource):
13+
def get(
14+
self,
15+
*,
16+
options: RequestOptions | None = None,
17+
) -> Workspace:
18+
"""Fetch the current workspace's ID, name, and the ID of the organization owning it. This is the workspace the current credentials are scoped to.
19+
20+
```python
21+
workspace = client.workspace.get()
22+
print(workspace.id, workspace.name)
23+
```
24+
"""
25+
return self._get(
26+
"/v1/workspace",
27+
{},
28+
Workspace,
29+
options,
30+
)
31+
32+
33+
class AsyncWorkspaceResource(AsyncResource):
34+
async def get(
35+
self,
36+
*,
37+
options: RequestOptions | None = None,
38+
) -> Workspace:
39+
"""Fetch the current workspace's ID, name, and the ID of the organization owning it. This is the workspace the current credentials are scoped to.
40+
41+
```python
42+
workspace = await client.workspace.get()
43+
print(workspace.id, workspace.name)
44+
```
45+
"""
46+
return await self._get(
47+
"/v1/workspace",
48+
{},
49+
Workspace,
50+
options,
51+
)

tests/test_surface_conformance_gen.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def test_surface_conformance() -> None:
8484
assert callable(client.domains.verify)
8585
assert callable(client.domains.update)
8686
assert callable(client.domains.delete)
87+
assert callable(client.workspace.get)
8788
assert callable(client.webhooks.unwrap)
8889
assert callable(client.preferences.list)
8990
assert callable(client.preferences.get)

0 commit comments

Comments
 (0)