Official Python SDK for Postject email API
Project description
Postject Python SDK
Official Python SDK for the Postject email API.
Installation
pip install postject
Quick Start
from postject import Postject
client = Postject(api_key="pk_live_your_api_key_here")
# Send a simple email
result = client.send({
"to": "customer@example.com",
"subject": "Welcome to our platform!",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
})
print(f"Message ID: {result.id}")
print(f"Status: {result.status}")
Features
✅ Full type hints (Pydantic models) ✅ Sync and async support ✅ Automatic retry on rate limits ✅ Comprehensive error handling ✅ All API endpoints covered
Configuration
client = Postject(
api_key="pk_live_your_api_key_here",
base_url="https://api.postject.com", # optional
timeout=30, # optional, in seconds
retries=3, # optional, for rate limits
)
Sending Emails
Simple Email
result = client.send({
"to": "user@example.com",
"from": "noreply@yourapp.com", # optional if identity configured
"subject": "Hello World",
"html": "<p>This is a test email</p>",
"text": "This is a test email", # optional plain text
})
Multiple Recipients
client.send({
"to": ["user1@example.com", "user2@example.com", "user3@example.com"],
"subject": "Bulk announcement",
"html": "<p>Important update</p>",
})
Using Templates
result = client.send_with_template(
template_id="template_id_here",
to="user@example.com",
variables={
"name": "John Doe",
"order_number": "12345",
"order_total": "$99.00",
},
stream_id="transactional_stream_id", # optional
)
Type-Safe Request
from postject import SendEmailRequest
request = SendEmailRequest(
to="user@example.com",
subject="Order Confirmation",
html="<p>Your order has been confirmed</p>",
tags=["order", "confirmation"],
metadata={"order_id": "12345"},
idempotency_key="order_12345", # prevents duplicates
analyze_content=True, # check spam score
)
result = client.send(request)
Managing Resources
Servers
# List all servers
servers = client.get_servers()
# Create a server
server = client.create_server("Production Server")
# Delete a server
client.delete_server("server_id")
Message Streams
# List streams
streams = client.get_streams("server_id")
# Create a stream
stream = client.create_stream(
server_id="server_id",
name="Transactional Emails",
slug="transactional",
description="Order confirmations, password resets, etc.",
stream_type="transactional",
)
# Delete a stream
client.delete_stream("server_id", "stream_id")
Templates
# List templates
templates = client.get_templates("server_id")
# Create a template
template = client.create_template(
server_id="server_id",
name="Welcome Email",
subject="Welcome to {{company_name}}!",
html="<h1>Welcome {{user_name}}!</h1><p>Thanks for signing up.</p>",
)
# Update a template
client.update_template(
server_id="server_id",
template_id="template_id",
subject="Updated subject",
html="<p>Updated content</p>",
)
# Delete a template
client.delete_template("server_id", "template_id")
Webhooks
# Create a webhook
webhook = client.create_webhook(
stream_id="stream_id",
url="https://yourapp.com/webhooks/postject",
events=["delivered", "bounced", "complained"], # or ["*"] for all
)
print(f"Webhook secret: {webhook.secret}") # Use for signature verification
# List webhooks
webhooks = client.get_webhooks("stream_id")
# Get webhook logs
logs_data = client.get_webhook_logs("webhook_id", limit=50, offset=0)
print(f"Total logs: {logs_data['total']}")
for log in logs_data['logs']:
print(f"{log.event_type}: {log.status_code}")
# Test a webhook
client.test_webhook("webhook_id")
# Delete a webhook
client.delete_webhook("stream_id", "webhook_id")
Message Tracking
# Get message details
message = client.get_message("message_id")
print(f"Status: {message.status}")
print(f"Route: {message.route_name}")
print(f"Latency: {message.latency_ms}ms")
# Get message events (full timeline)
events = client.get_message_events("message_id")
for event in events:
print(f"{event.type} at {event.timestamp}")
API Key Management
# List API keys
keys = client.get_api_keys()
# Create a new key
new_key = client.create_api_key(
name="Production Key",
expires_in_days=365,
)
print(f"New API key: {new_key.key}") # SAVE THIS!
# Revoke a key
client.revoke_api_key("key_id")
# Rotate a key
rotated_key = client.rotate_api_key("old_key_id", name="New Production Key")
Content Analysis
# Analyze content before sending
analysis = client.analyze_content(
subject="Your subject line",
html="<html><body>Email content</body></html>",
)
print(f"Overall score: {analysis.overall_score}/100")
print(f"Spam score: {analysis.spam_score}/100")
for issue in analysis.issues:
print(f"[{issue.severity}] {issue.message}")
print(f" Suggestion: {issue.suggestion}")
for recommendation in analysis.recommendations:
print(f"✓ {recommendation}")
Analytics
# Get server overview
analytics = client.get_server_analytics("server_id")
print(f"Total sent: {analytics.total_sent}")
print(f"Delivery rate: {analytics.delivery_rate * 100:.2f}%")
print(f"Bounce rate: {analytics.bounce_rate * 100:.2f}%")
print(f"Avg latency: {analytics.avg_latency}ms")
Error Handling
from postject import (
PostjectError,
AuthenticationError,
RateLimitError,
ValidationError,
NotFoundError,
ServerError,
)
try:
client.send({"to": "user@example.com", "subject": "Test", "html": "..."})
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
print(f"Validation error: {e.response}")
except NotFoundError:
print("Resource not found")
except ServerError as e:
print(f"Server error: {e.status_code}")
except PostjectError as e:
print(f"API error: {e.message}")
Async Support
import asyncio
from postject import AsyncPostject
async def send_email():
async with AsyncPostject(api_key="your_api_key") as client:
result = await client.send({
"to": "user@example.com",
"subject": "Async Email",
"html": "<p>Sent asynchronously</p>",
})
print(f"Sent: {result.id}")
asyncio.run(send_email())
Context Manager
# Automatic client cleanup
with Postject(api_key="your_api_key") as client:
result = client.send({
"to": "user@example.com",
"subject": "Test",
"html": "<p>Email body</p>",
})
# Client automatically closed
Type Hints
Full type hints using Pydantic:
from postject.types import (
SendEmailRequest,
SendEmailResponse,
Server,
MessageStream,
Template,
Webhook,
Message,
Event,
)
def send_welcome_email(email: str) -> SendEmailResponse:
client = Postject(api_key="your_key")
request = SendEmailRequest(
to=email,
subject="Welcome!",
html="<p>Welcome to our platform</p>",
)
return client.send(request)
Examples
# Send transactional email
client.send({
"to": "customer@example.com",
"subject": "Your order #12345 has shipped",
"html": """
<h2>Order Shipped!</h2>
<p>Your order #12345 is on its way.</p>
<p>Tracking: ABC123XYZ</p>
""",
"tags": ["shipping", "order"],
"metadata": {"order_id": "12345"},
})
# Send password reset
client.send_with_template(
template_id="password_reset_template",
to="user@example.com",
variables={
"reset_link": "https://app.com/reset?token=abc123",
"expires_in": "1 hour",
},
)
# Batch send with template
users = [
{"email": "user1@example.com", "name": "Alice"},
{"email": "user2@example.com", "name": "Bob"},
]
for user in users:
client.send_with_template(
template_id="newsletter_template",
to=user["email"],
variables={"name": user["name"]},
stream_id="newsletter_stream",
)
Requirements
- Python 3.8+
- httpx>=0.24.0
- pydantic>=2.0.0
Support
- Documentation: https://postject.com/docs/sdk
- Email: support@postject.com
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
postject-1.0.1.tar.gz
(12.0 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
postject-1.0.1-py3-none-any.whl
(10.2 kB
view details)
File details
Details for the file postject-1.0.1.tar.gz.
File metadata
- Download URL: postject-1.0.1.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33832c5f107d811303e23de07178b119870151f8d252dbdec92d478e8bd1e14a
|
|
| MD5 |
bee65da6be467debe8f91975c9af267a
|
|
| BLAKE2b-256 |
184623178c257b15d10464454874e0408b2b62017c989b1002be7394792f7fe3
|
File details
Details for the file postject-1.0.1-py3-none-any.whl.
File metadata
- Download URL: postject-1.0.1-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10761aa9682bb339b4f4316ab4c251ad06a5a291e2cf85bffb9fc1e4c3a048b1
|
|
| MD5 |
fae820371500e400707bd39466253f6a
|
|
| BLAKE2b-256 |
8af158e02073d8f5237a7e68950f569d1b9a709ca343d4d7b038c0b43bfc9bf1
|