Python SDK
boundry is the synchronous typed client for Boundry’s regional API. It ships a py.typed marker so type checkers can use its generated models.
Install
pip install boundryQuickstart
Set BOUNDRY_API_KEY, then send from a domain verified in this project. The display-name form is valid; an unverified sending domain returns 422.
import os
from boundry import Boundry
boundry = Boundry(api_key=os.environ["BOUNDRY_API_KEY"], region="au")
email = boundry.emails.send({
"from": "Acme <hello@acme.com>",
"to": ["ava@northwind.com.au"],
"subject": "Welcome to Acme",
"html": "<p>It works.</p>",
})
print(email["id"])Client options
| Option | Type | Purpose |
|---|---|---|
api_key | str | Project API key. Defaults to BOUNDRY_API_KEY when available. |
region | str | Regional endpoint selector. Sydney is the current supported region. |
base_url | str | Full API base URL. Takes precedence over region when explicitly supplied. |
timeout | float | httpx.Timeout | Per-request deadline in seconds. Defaults to 30.0. |
max_retries | int | Retries after the first attempt. Defaults to 2. |
http_client / transport | httpx.Client / httpx.BaseTransport | Inject an HTTP client or transport for advanced use and tests. |
Resources and methods
These rows are derived from the public OpenAPI operations and link to the generated endpoint reference. Request dictionaries are generated TypedDict models; where appropriate, the Python client also accepts documented keyword arguments.
| SDK method | What it does | API reference |
|---|---|---|
boundry.api_keys.list() | List API keys | View endpoint → |
boundry.api_keys.create(params) | Create an API key | View endpoint → |
boundry.api_keys.delete(key_id) | Delete an API key | View endpoint → |
boundry.domains.list() | List domains | View endpoint → |
boundry.domains.create(params) | Create a domain | View endpoint → |
boundry.domains.delete(domain_id) | Delete a domain | View endpoint → |
boundry.domains.get(domain_id) | Get a domain | View endpoint → |
boundry.domains.update(domain_id, params) | Update domain tracking | View endpoint → |
boundry.domains.verify_action(domain_id) | Verify a domain (compatibility action) | View endpoint → |
boundry.domains.verify(domain_id) | Verify a domain | View endpoint → |
boundry.emails.list() | List sent emails | View endpoint → |
boundry.emails.send(params, *, idempotency_key=None) | Send an email | View endpoint → |
boundry.emails.get(email_id) | Get a sent email | View endpoint → |
boundry.emails.list_attachments(email_id) | List email attachments | View endpoint → |
boundry.emails.get_attachment(email_id, attachment_id) | Download an email attachment | View endpoint → |
boundry.emails.send_batch(params, *, idempotency_key=None) | Send a batch of emails | View endpoint → |
boundry.events.list() | List project events | View endpoint → |
boundry.events.get(event_id) | Get a project event | View endpoint → |
boundry.inbound.list(*, id=None) | List received emails | View endpoint → |
boundry.inbound.get(email_id) | Get a received email | View endpoint → |
boundry.inbound.ingest(params) | Ingest an inbound email | View endpoint → |
boundry.logs.list() | List event logs | View endpoint → |
boundry.openapi.get() | Get the OpenAPI document | View endpoint → |
boundry.webhooks.list() | List webhooks | View endpoint → |
boundry.webhooks.create(params) | Create a webhook | View endpoint → |
boundry.webhooks.delete(webhook_id) | Delete a webhook | View endpoint → |
boundry.webhooks.get(webhook_id) | Get a webhook | View endpoint → |
boundry.webhooks.update(webhook_id, params) | Update a webhook | View endpoint → |
boundry.webhooks.list_deliveries(webhook_id, *, id=None) | List webhook deliveries | View endpoint → |
boundry.webhooks.get_delivery(webhook_id, delivery_id) | Get webhook delivery detail | View endpoint → |
boundry.webhooks.retry_delivery(webhook_id, delivery_id) | Retry a webhook delivery | View endpoint → |
boundry.webhooks.rotate_secret(webhook_id, params) | Rotate a webhook signing secret | View endpoint → |
boundry.webhooks.test(webhook_id, params) | Send a synthetic webhook event | View endpoint → |
boundry.webhooks.verify(webhook_id) | Send a webhook ownership challenge | View endpoint → |
Errors
Non-success responses raise BoundryAPIError, which carries status, code, message, and request_id. Transport failures raise BoundryConnectionError; timeouts raise BoundryTimeoutError. Both inherit from BoundryError.
import os
from boundry import Boundry, BoundryAPIError
boundry = Boundry(api_key=os.environ["BOUNDRY_API_KEY"])
try:
boundry.emails.send({
"from": "Acme <hello@acme.com>",
"to": ["ava@northwind.com.au"],
"subject": "Welcome to Acme",
"html": "<p>It works.</p>",
})
except BoundryAPIError as error:
print(error.status, error.code, error.request_id)
finally:
boundry.close()Retries, idempotency, and context managers
The client retries connection failures and 408, 429, and 5xx responses with exponential backoff and jitter, up to max_retries (2 by default), while honouring Retry-After. emails.send and emails.send_batch automatically send an idempotency key; pass idempotency_key="..." to make it stable across your own retry.
import os
from boundry import Boundry
with Boundry(api_key=os.environ["BOUNDRY_API_KEY"], region="au") as boundry:
email = boundry.emails.send({
"from": "Acme <hello@acme.com>",
"to": ["ava@northwind.com.au"],
"subject": "Welcome to Acme",
"text": "It works.",
})
print(email["id"])Regions and local development
region="au" resolves to https://api.au.boundry.dev. Set base_url explicitly only when you need to override region.
import os
from boundry import Boundry
boundry = Boundry(
api_key=os.environ["BOUNDRY_API_KEY"],
base_url="https://api.au.boundry.dev",
)