SDKs
Python
Official Python SDK for MisarMail — sync and async clients for Django, FastAPI, Flask, and scripts
The misarmail PyPI package is the official Python SDK for MisarMail. A single MisarMailClient exposes both sync methods and a-prefixed async variants (e.g. email.send / email.asend), built on httpx.
Installation
pip install misarmail
# or
uv add misarmail
# or
poetry add misarmailRequirements: Python ≥ 3.9, httpx ≥ 0.27
Quick Start
from misarmail import MisarMailClient
client = MisarMailClient(api_key="msk_your_key_here")
result = client.email.send({
"from": {"email": "hello@yourapp.com", "name": "Your App"},
"to": [{"email": "user@example.com"}],
"subject": "Welcome!",
"html": "<p>Welcome aboard!</p>",
})
print(result["message_id"])Configuration
import os
from misarmail import MisarMailClient
client = MisarMailClient(
api_key=os.environ.get("MISARMAIL_API_KEY", "msk_your_key_here"),
base_url="https://api.misar.io/mail/v1", # Default
timeout=30.0, # Seconds. Default: 30
max_retries=3, # Default: 3
)Available Methods
| Method | Description |
|---|---|
client.email.send(request) | Send a transactional email |
client.contacts.list(**params) | List contacts with filters |
client.contacts.create(**params) | Create a contact |
client.contacts.get(id) | Get a single contact |
client.contacts.update(id, **params) | Update contact fields |
client.contacts.delete(id) | Delete a contact |
client.contacts.import_contacts(**params) | Bulk import/upsert contacts |
client.campaigns.list(**params) | List campaigns |
client.campaigns.create(**params) | Create a draft campaign |
client.campaigns.get(id) | Get a campaign |
client.campaigns.update(id, **params) | Update a campaign |
client.campaigns.send(id) | Send/schedule a campaign |
client.campaigns.delete(id) | Delete a campaign |
client.templates.list(**params) | List email templates |
client.templates.create(**params) | Create a template |
client.templates.get(id) | Get a template |
client.templates.update(id, **params) | Update a template |
client.templates.delete(id) | Delete a template |
client.templates.render(data) | Render a template with merge data |
client.automations.list(**params) | List automation workflows |
client.automations.create(**params) | Create an automation |
client.automations.get(id) | Get an automation |
client.automations.update(id, **params) | Update an automation |
client.automations.delete(id) | Delete an automation |
client.automations.activate(id) | Activate/deactivate an automation |
client.domains.list() | List sending domains |
client.domains.create(**params) | Add a sending domain |
client.domains.get(id) | Get a domain |
client.domains.verify(id) | Trigger domain DNS verification |
client.domains.delete(id) | Delete a domain |
client.aliases.list(**params) | List email aliases |
client.aliases.create(**params) | Create an alias |
client.aliases.get(id) | Get an alias |
client.aliases.update(id, **params) | Update an alias |
client.aliases.delete(id) | Delete an alias |
client.dedicated_ips.list() | List dedicated IPs |
client.dedicated_ips.create(**params) | Purchase a dedicated IP |
client.dedicated_ips.update(id, **params) | Update IP pool assignment |
client.dedicated_ips.delete(id) | Release a dedicated IP |
client.ab_tests.list(**params) | List A/B tests |
client.ab_tests.create(**params) | Create an A/B test |
client.ab_tests.get(id) | Get an A/B test |
client.ab_tests.set_winner(id, variant) | Manually set the winning variant |
client.sandbox.send(**params) | Send in sandbox mode (no real delivery) |
client.sandbox.list(**params) | List sandbox sent messages |
client.sandbox.delete(id) | Delete a sandbox message |
client.inbound.list(**params) | List inbound routing rules |
client.inbound.create(**params) | Create an inbound route |
client.inbound.get(id) | Get an inbound route |
client.inbound.delete(id) | Delete an inbound route |
client.analytics.overview(**params) | Get send/open/click/bounce analytics |
client.track.event(**params) | Track a custom event |
client.track.purchase(**params) | Track a purchase event |
client.keys.list() | List API keys |
client.keys.create(**params) | Create an API key |
client.keys.get(id) | Get an API key |
client.keys.revoke(id) | Revoke an API key |
client.validate.email(address) | Validate an email address |
client.webhooks.list(**params) | List webhooks |
client.webhooks.create(**params) | Create a webhook endpoint |
client.webhooks.get(id) | Get a webhook |
client.webhooks.update(id, **params) | Update a webhook |
client.webhooks.delete(id) | Delete a webhook |
client.webhooks.test(id) | Send a test event to a webhook |
client.usage.get(**params) | Get API usage stats |
client.billing.subscription() | Get current subscription details |
client.billing.checkout(**params) | Create a billing checkout session |
client.workspaces.list() | List workspaces |
client.workspaces.create(**params) | Create a workspace |
client.workspaces.get(id) | Get a workspace |
client.workspaces.update(id, **params) | Update a workspace |
client.workspaces.delete(id) | Delete a workspace |
client.workspaces.list_members(id) | List workspace members |
client.workspaces.invite_member(id, **params) | Invite a member to workspace |
client.workspaces.update_member(id, user_id, **params) | Update member role |
client.workspaces.remove_member(id, user_id) | Remove a member from workspace |
Examples
Webhooks
webhook = client.webhooks.create({
"url": "https://yourapp.com/webhooks/mail",
"events": ["email.delivered", "email.opened", "email.bounced"],
})
client.webhooks.test(webhook["id"])Async Usage
The same client exposes a-prefixed async variants — call email.asend(...) instead of email.send(...). No separate async class is needed.
import asyncio
from misarmail import MisarMailClient
async def main():
client = MisarMailClient(api_key="msk_your_key_here")
result = await client.email.asend({
"from": {"email": "hello@yourapp.com"},
"to": [{"email": "user@example.com"}],
"subject": "Hello",
"html": "<p>Hi!</p>",
})
print(result["message_id"])
asyncio.run(main())Error Handling
from misarmail import MisarMailError, MisarMailNetworkError
try:
client.email.send({...})
except MisarMailError as e:
print(e.status, e.message)