messagebird-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- messagebird_sdk-0.1.0/.gitignore +8 -0
- messagebird_sdk-0.1.0/LICENSE +21 -0
- messagebird_sdk-0.1.0/PKG-INFO +185 -0
- messagebird_sdk-0.1.0/README.md +152 -0
- messagebird_sdk-0.1.0/pyproject.toml +70 -0
- messagebird_sdk-0.1.0/src/bird/__init__.py +65 -0
- messagebird_sdk-0.1.0/src/bird/_base_client.py +256 -0
- messagebird_sdk-0.1.0/src/bird/_client.py +278 -0
- messagebird_sdk-0.1.0/src/bird/_constants.py +8 -0
- messagebird_sdk-0.1.0/src/bird/_exceptions.py +227 -0
- messagebird_sdk-0.1.0/src/bird/_generated.py +1390 -0
- messagebird_sdk-0.1.0/src/bird/_models.py +43 -0
- messagebird_sdk-0.1.0/src/bird/_response.py +37 -0
- messagebird_sdk-0.1.0/src/bird/_types.py +123 -0
- messagebird_sdk-0.1.0/src/bird/_version.py +1 -0
- messagebird_sdk-0.1.0/src/bird/pagination.py +115 -0
- messagebird_sdk-0.1.0/src/bird/py.typed +0 -0
- messagebird_sdk-0.1.0/src/bird/resources/__init__.py +4 -0
- messagebird_sdk-0.1.0/src/bird/resources/email.py +366 -0
- messagebird_sdk-0.1.0/src/bird/resources/webhooks.py +111 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bird
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: messagebird-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The official Python SDK for the Bird email platform.
|
|
5
|
+
Project-URL: Homepage, https://github.com/messagebird/bird-sdk-python#readme
|
|
6
|
+
Project-URL: Repository, https://github.com/messagebird/bird-sdk-python.git
|
|
7
|
+
Project-URL: Issues, https://github.com/messagebird/bird-sdk-python/issues
|
|
8
|
+
Author: Bird
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,bird,email,sdk,webhooks
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Communications :: Email
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: pydantic>=2.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pyright>=1.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
29
|
+
Requires-Dist: pyyaml>=6; extra == 'dev'
|
|
30
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# Bird Python SDK
|
|
35
|
+
|
|
36
|
+
The official Python SDK for the [Bird](https://bird.com) email platform.
|
|
37
|
+
|
|
38
|
+
> **Status:** in development. The PyPI distribution name is `messagebird-sdk`; the import package is `bird`.
|
|
39
|
+
|
|
40
|
+
Requires Python 3.10+.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install messagebird-sdk # or: uv add messagebird-sdk
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> This SDK is generated from Bird's public OpenAPI bundle inside Bird's internal monorepo, which is the single source of truth; this repository tracks tagged releases. Generation runs in the monorepo, so `make generate` won't work from a clone here — see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
49
|
+
|
|
50
|
+
## Quickstart
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from bird import Bird
|
|
54
|
+
|
|
55
|
+
client = Bird(api_key="bk_eu1_...") # region inferred from the key prefix
|
|
56
|
+
|
|
57
|
+
message = client.email.send(
|
|
58
|
+
from_="hello@acme.com",
|
|
59
|
+
to=["customer@example.com"],
|
|
60
|
+
subject="Welcome to Acme",
|
|
61
|
+
html="<h1>Welcome</h1>",
|
|
62
|
+
)
|
|
63
|
+
print(message.id, message.status)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`api_key` and `base_url` fall back to the `BIRD_API_KEY` / `BIRD_BASE_URL` environment variables, so `Bird()` with no arguments works when they are set. Use the client as a context manager (`with Bird(...) as client:`) to close the underlying HTTP connection pool.
|
|
67
|
+
|
|
68
|
+
## Email
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
# Send
|
|
72
|
+
message = client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="hello")
|
|
73
|
+
|
|
74
|
+
# Fetch
|
|
75
|
+
message = client.email.get("em_01krd…")
|
|
76
|
+
|
|
77
|
+
# List — iterating the page auto-paginates across cursors
|
|
78
|
+
for message in client.email.list(status="delivered"):
|
|
79
|
+
print(message.id, message.status)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Client-wide email defaults
|
|
83
|
+
|
|
84
|
+
Defaults fill any unset `send` field; a per-send value always wins.
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
client = Bird(
|
|
88
|
+
api_key="bk_eu1_...",
|
|
89
|
+
email_defaults={"from_": "noreply@acme.com", "reply_to": ["support@acme.com"]},
|
|
90
|
+
)
|
|
91
|
+
client.email.send(to=["c@x.com"], subject="Receipt", text="…") # uses noreply@acme.com
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Webhooks
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from bird import Bird, WebhookVerificationError
|
|
98
|
+
|
|
99
|
+
client = Bird(api_key="bk_eu1_...", webhook_secret="whsec_...")
|
|
100
|
+
|
|
101
|
+
# In your web handler — pass the RAW request body (bytes) and the request headers
|
|
102
|
+
try:
|
|
103
|
+
event = client.webhooks.unwrap(request.body, request.headers)
|
|
104
|
+
except WebhookVerificationError:
|
|
105
|
+
return Response(status=400)
|
|
106
|
+
|
|
107
|
+
if event.root.type == "email.delivered":
|
|
108
|
+
print("delivered:", event.root.data.message_id)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> Endpoint management (registering/listing webhook endpoints) is not in this release; it returns once the delivery substrate stabilises.
|
|
112
|
+
|
|
113
|
+
## Errors
|
|
114
|
+
|
|
115
|
+
Every failure raises a typed exception rooted at `BirdError`. `APIError` covers anything that goes wrong issuing a request — including transport failures — so a single `except APIError` is enough; `APIStatusError` carries the HTTP `status_code`.
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from bird import APIStatusError, RateLimitError, ValidationError
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="…")
|
|
122
|
+
except RateLimitError as err:
|
|
123
|
+
retry_in = err.retry_after # seconds, parsed from Retry-After
|
|
124
|
+
except ValidationError as err:
|
|
125
|
+
print(err.status_code, err.details) # 422 + per-field detail
|
|
126
|
+
except APIStatusError as err:
|
|
127
|
+
print(err.status_code, err.code, err.request_id)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Transient failures (timeouts, 429, 5xx) retry automatically with jittered backoff that honors `Retry-After`; a mutation reuses one idempotency key across attempts, so a retried write never double-applies.
|
|
131
|
+
|
|
132
|
+
## Raw response
|
|
133
|
+
|
|
134
|
+
Reach the status, headers, and `request_id` alongside the parsed model:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
raw = client.email.with_raw_response.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="…")
|
|
138
|
+
print(raw.status_code, raw.request_id)
|
|
139
|
+
message = raw.parse()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Async
|
|
143
|
+
|
|
144
|
+
`AsyncBird` mirrors `Bird` method-for-method — `await` each call and `async for` over a list:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import asyncio
|
|
148
|
+
from bird import AsyncBird
|
|
149
|
+
|
|
150
|
+
async def main() -> None:
|
|
151
|
+
async with AsyncBird(api_key="bk_eu1_...") as client:
|
|
152
|
+
await client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="hello")
|
|
153
|
+
async for message in client.email.list(status="delivered"):
|
|
154
|
+
print(message.id)
|
|
155
|
+
|
|
156
|
+
asyncio.run(main())
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Configuration
|
|
160
|
+
|
|
161
|
+
| Option | Description |
|
|
162
|
+
| ------------------------ | ------------------------------------------------------------------------------ |
|
|
163
|
+
| `api_key` | API key; falls back to `BIRD_API_KEY`. |
|
|
164
|
+
| `region` / `base_url` | Region (or explicit base URL); falls back to the key prefix / `BIRD_BASE_URL`. |
|
|
165
|
+
| `timeout`, `max_retries` | Request timeout and retry budget; overridable per call via `options`. |
|
|
166
|
+
| `webhook_secret` | Signing secret for `webhooks.unwrap`. |
|
|
167
|
+
| `email_defaults` | Client-wide `send` defaults. |
|
|
168
|
+
| `http_client` | Inject your own `httpx.Client` / `AsyncClient`. |
|
|
169
|
+
|
|
170
|
+
`client.with_options(...)` derives a new client (reusing the connection pool); every method also takes a trailing `options` for per-call `timeout` / `max_retries` / `idempotency_key` / `extra_headers`.
|
|
171
|
+
|
|
172
|
+
## Escape hatch
|
|
173
|
+
|
|
174
|
+
Any endpoint outside the typed surface is reachable through the verb methods, with the same auth, retries, and idempotency:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from bird import EmailMessage
|
|
178
|
+
|
|
179
|
+
message = client.get("/v1/email/messages/em_01krd…", cast_to=EmailMessage)
|
|
180
|
+
client.post("/v1/some/new/endpoint", body={"key": "value"})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Design
|
|
184
|
+
|
|
185
|
+
The wire models are generated from the OpenAPI spec into `bird._generated`; this package is the hand-written idiomatic layer on top.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Bird Python SDK
|
|
2
|
+
|
|
3
|
+
The official Python SDK for the [Bird](https://bird.com) email platform.
|
|
4
|
+
|
|
5
|
+
> **Status:** in development. The PyPI distribution name is `messagebird-sdk`; the import package is `bird`.
|
|
6
|
+
|
|
7
|
+
Requires Python 3.10+.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install messagebird-sdk # or: uv add messagebird-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> This SDK is generated from Bird's public OpenAPI bundle inside Bird's internal monorepo, which is the single source of truth; this repository tracks tagged releases. Generation runs in the monorepo, so `make generate` won't work from a clone here — see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
16
|
+
|
|
17
|
+
## Quickstart
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from bird import Bird
|
|
21
|
+
|
|
22
|
+
client = Bird(api_key="bk_eu1_...") # region inferred from the key prefix
|
|
23
|
+
|
|
24
|
+
message = client.email.send(
|
|
25
|
+
from_="hello@acme.com",
|
|
26
|
+
to=["customer@example.com"],
|
|
27
|
+
subject="Welcome to Acme",
|
|
28
|
+
html="<h1>Welcome</h1>",
|
|
29
|
+
)
|
|
30
|
+
print(message.id, message.status)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`api_key` and `base_url` fall back to the `BIRD_API_KEY` / `BIRD_BASE_URL` environment variables, so `Bird()` with no arguments works when they are set. Use the client as a context manager (`with Bird(...) as client:`) to close the underlying HTTP connection pool.
|
|
34
|
+
|
|
35
|
+
## Email
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
# Send
|
|
39
|
+
message = client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="hello")
|
|
40
|
+
|
|
41
|
+
# Fetch
|
|
42
|
+
message = client.email.get("em_01krd…")
|
|
43
|
+
|
|
44
|
+
# List — iterating the page auto-paginates across cursors
|
|
45
|
+
for message in client.email.list(status="delivered"):
|
|
46
|
+
print(message.id, message.status)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Client-wide email defaults
|
|
50
|
+
|
|
51
|
+
Defaults fill any unset `send` field; a per-send value always wins.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
client = Bird(
|
|
55
|
+
api_key="bk_eu1_...",
|
|
56
|
+
email_defaults={"from_": "noreply@acme.com", "reply_to": ["support@acme.com"]},
|
|
57
|
+
)
|
|
58
|
+
client.email.send(to=["c@x.com"], subject="Receipt", text="…") # uses noreply@acme.com
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Webhooks
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from bird import Bird, WebhookVerificationError
|
|
65
|
+
|
|
66
|
+
client = Bird(api_key="bk_eu1_...", webhook_secret="whsec_...")
|
|
67
|
+
|
|
68
|
+
# In your web handler — pass the RAW request body (bytes) and the request headers
|
|
69
|
+
try:
|
|
70
|
+
event = client.webhooks.unwrap(request.body, request.headers)
|
|
71
|
+
except WebhookVerificationError:
|
|
72
|
+
return Response(status=400)
|
|
73
|
+
|
|
74
|
+
if event.root.type == "email.delivered":
|
|
75
|
+
print("delivered:", event.root.data.message_id)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
> Endpoint management (registering/listing webhook endpoints) is not in this release; it returns once the delivery substrate stabilises.
|
|
79
|
+
|
|
80
|
+
## Errors
|
|
81
|
+
|
|
82
|
+
Every failure raises a typed exception rooted at `BirdError`. `APIError` covers anything that goes wrong issuing a request — including transport failures — so a single `except APIError` is enough; `APIStatusError` carries the HTTP `status_code`.
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from bird import APIStatusError, RateLimitError, ValidationError
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="…")
|
|
89
|
+
except RateLimitError as err:
|
|
90
|
+
retry_in = err.retry_after # seconds, parsed from Retry-After
|
|
91
|
+
except ValidationError as err:
|
|
92
|
+
print(err.status_code, err.details) # 422 + per-field detail
|
|
93
|
+
except APIStatusError as err:
|
|
94
|
+
print(err.status_code, err.code, err.request_id)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Transient failures (timeouts, 429, 5xx) retry automatically with jittered backoff that honors `Retry-After`; a mutation reuses one idempotency key across attempts, so a retried write never double-applies.
|
|
98
|
+
|
|
99
|
+
## Raw response
|
|
100
|
+
|
|
101
|
+
Reach the status, headers, and `request_id` alongside the parsed model:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
raw = client.email.with_raw_response.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="…")
|
|
105
|
+
print(raw.status_code, raw.request_id)
|
|
106
|
+
message = raw.parse()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Async
|
|
110
|
+
|
|
111
|
+
`AsyncBird` mirrors `Bird` method-for-method — `await` each call and `async for` over a list:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
import asyncio
|
|
115
|
+
from bird import AsyncBird
|
|
116
|
+
|
|
117
|
+
async def main() -> None:
|
|
118
|
+
async with AsyncBird(api_key="bk_eu1_...") as client:
|
|
119
|
+
await client.email.send(from_="hi@acme.com", to=["c@x.com"], subject="Hi", text="hello")
|
|
120
|
+
async for message in client.email.list(status="delivered"):
|
|
121
|
+
print(message.id)
|
|
122
|
+
|
|
123
|
+
asyncio.run(main())
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
| Option | Description |
|
|
129
|
+
| ------------------------ | ------------------------------------------------------------------------------ |
|
|
130
|
+
| `api_key` | API key; falls back to `BIRD_API_KEY`. |
|
|
131
|
+
| `region` / `base_url` | Region (or explicit base URL); falls back to the key prefix / `BIRD_BASE_URL`. |
|
|
132
|
+
| `timeout`, `max_retries` | Request timeout and retry budget; overridable per call via `options`. |
|
|
133
|
+
| `webhook_secret` | Signing secret for `webhooks.unwrap`. |
|
|
134
|
+
| `email_defaults` | Client-wide `send` defaults. |
|
|
135
|
+
| `http_client` | Inject your own `httpx.Client` / `AsyncClient`. |
|
|
136
|
+
|
|
137
|
+
`client.with_options(...)` derives a new client (reusing the connection pool); every method also takes a trailing `options` for per-call `timeout` / `max_retries` / `idempotency_key` / `extra_headers`.
|
|
138
|
+
|
|
139
|
+
## Escape hatch
|
|
140
|
+
|
|
141
|
+
Any endpoint outside the typed surface is reachable through the verb methods, with the same auth, retries, and idempotency:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from bird import EmailMessage
|
|
145
|
+
|
|
146
|
+
message = client.get("/v1/email/messages/em_01krd…", cast_to=EmailMessage)
|
|
147
|
+
client.post("/v1/some/new/endpoint", body={"key": "value"})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Design
|
|
151
|
+
|
|
152
|
+
The wire models are generated from the OpenAPI spec into `bird._generated`; this package is the hand-written idiomatic layer on top.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Python SDK for the Bird email platform (ADR-0045).
|
|
2
|
+
# Distribution name is `messagebird-sdk` on PyPI; the import package is `bird`.
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["hatchling"]
|
|
5
|
+
build-backend = "hatchling.build"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "messagebird-sdk"
|
|
9
|
+
description = "The official Python SDK for the Bird email platform."
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "Bird" }]
|
|
13
|
+
dynamic = ["version"]
|
|
14
|
+
requires-python = ">=3.10"
|
|
15
|
+
keywords = ["bird", "email", "webhooks", "sdk", "api"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Communications :: Email",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"pydantic>=2.0",
|
|
30
|
+
"httpx>=0.27",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/messagebird/bird-sdk-python#readme"
|
|
35
|
+
Repository = "https://github.com/messagebird/bird-sdk-python.git"
|
|
36
|
+
Issues = "https://github.com/messagebird/bird-sdk-python/issues"
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest>=8",
|
|
41
|
+
"pytest-asyncio>=0.24",
|
|
42
|
+
"respx>=0.21",
|
|
43
|
+
"ruff>=0.6",
|
|
44
|
+
"pyright>=1.1",
|
|
45
|
+
"pyyaml>=6",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[tool.hatch.version]
|
|
49
|
+
path = "src/bird/_version.py"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.build.targets.wheel]
|
|
52
|
+
packages = ["src/bird"]
|
|
53
|
+
|
|
54
|
+
# Curate the sdist: ship the package, README, and LICENSE — not the internal agent
|
|
55
|
+
# docs (AGENTS.md / CLAUDE.md), tests, or the generator script.
|
|
56
|
+
[tool.hatch.build.targets.sdist]
|
|
57
|
+
include = ["/src/bird", "/README.md", "/LICENSE"]
|
|
58
|
+
|
|
59
|
+
[tool.pytest.ini_options]
|
|
60
|
+
asyncio_mode = "auto"
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
line-length = 100
|
|
64
|
+
target-version = "py310"
|
|
65
|
+
extend-exclude = ["src/bird/_generated.py"] # generated; never hand-edited
|
|
66
|
+
|
|
67
|
+
[tool.pyright]
|
|
68
|
+
include = ["src", "tests", "examples"]
|
|
69
|
+
ignore = ["src/bird/_generated.py"] # generated; not held to the hand-written type bar
|
|
70
|
+
pythonVersion = "3.10"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""The official Python SDK for the Bird email platform (ADR-0045).
|
|
2
|
+
|
|
3
|
+
The wire models are generated from the OpenAPI spec into ``bird._generated`` and
|
|
4
|
+
never hand-edited; this package is the hand-written, idiomatic layer on top — a
|
|
5
|
+
synchronous ``Bird`` client and an asynchronous ``AsyncBird`` client, a typed
|
|
6
|
+
exception hierarchy, safe retries, pagination, and webhook verification.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from bird._client import AsyncBird, Bird
|
|
12
|
+
from bird._response import APIResponse
|
|
13
|
+
from bird._types import (
|
|
14
|
+
Attachment,
|
|
15
|
+
EmailDefaults,
|
|
16
|
+
EmailListParams,
|
|
17
|
+
EmailSendParams,
|
|
18
|
+
RequestOptions,
|
|
19
|
+
)
|
|
20
|
+
from bird._generated import (
|
|
21
|
+
EmailMessage,
|
|
22
|
+
WebhookEvent,
|
|
23
|
+
WebhookEventType,
|
|
24
|
+
)
|
|
25
|
+
from bird._exceptions import (
|
|
26
|
+
APIConnectionError,
|
|
27
|
+
APIError,
|
|
28
|
+
APIStatusError,
|
|
29
|
+
APITimeoutError,
|
|
30
|
+
BirdError,
|
|
31
|
+
ErrorDetail,
|
|
32
|
+
ErrorType,
|
|
33
|
+
RateLimitError,
|
|
34
|
+
ValidationError,
|
|
35
|
+
WebhookVerificationError,
|
|
36
|
+
)
|
|
37
|
+
from bird.pagination import AsyncPage, SyncPage
|
|
38
|
+
from bird._version import __version__
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"Bird",
|
|
42
|
+
"AsyncBird",
|
|
43
|
+
"RequestOptions",
|
|
44
|
+
"EmailDefaults",
|
|
45
|
+
"Attachment",
|
|
46
|
+
"EmailSendParams",
|
|
47
|
+
"EmailListParams",
|
|
48
|
+
"APIResponse",
|
|
49
|
+
"SyncPage",
|
|
50
|
+
"AsyncPage",
|
|
51
|
+
"EmailMessage",
|
|
52
|
+
"WebhookEvent",
|
|
53
|
+
"WebhookEventType",
|
|
54
|
+
"BirdError",
|
|
55
|
+
"APIError",
|
|
56
|
+
"APIStatusError",
|
|
57
|
+
"RateLimitError",
|
|
58
|
+
"ValidationError",
|
|
59
|
+
"APIConnectionError",
|
|
60
|
+
"APITimeoutError",
|
|
61
|
+
"WebhookVerificationError",
|
|
62
|
+
"ErrorDetail",
|
|
63
|
+
"ErrorType",
|
|
64
|
+
"__version__",
|
|
65
|
+
]
|