Repository navigation
Stats
Greg Svoboda edited this page Oct 28, 2026
·
2 revisions
Statistics retrieval is done through ServerClient. You will need a server API token.
import postmark
client = postmark.ServerClient("your-server-token")All stat methods support optional from_date, to_date, tag, and message_stream filters.
Postmark leaves out any category whose count is zero (for example a day with only desktop opens has no Mobile entry). The SDK reports those as 0, and an empty result has days == [], so you can read every field without checking for it first.
Get a high-level summary of all outbound activity.
import asyncio
from datetime import date
async def main():
result = await client.stats.overview(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Sent: {result.sent}")
print(f"Bounced: {result.bounced}")
print(f"Bounce rate: {result.bounce_rate:.2%}")
print(f"Spam complaints: {result.spam_complaints}")
print(f"Opens: {result.opens}")
print(f"Unique opens: {result.unique_opens}")
print(f"Total clicks: {result.total_clicks}")
asyncio.run(main())Daily breakdown of sent message counts.
from datetime import date
async def main():
result = await client.stats.sent_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Total sent: {result.sent}")
for day in result.days:
print(f" {day.date}: {day.sent} sent")Daily breakdown of bounces by type.
from datetime import date
async def main():
result = await client.stats.bounce_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Hard bounces: {result.hard_bounce}")
print(f"Soft bounces: {result.soft_bounce}")
for day in result.days:
print(f" {day.date}: hard={day.hard_bounce} soft={day.soft_bounce}")async def main():
result = await client.stats.spam_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Spam complaints: {result.spam_complaint}")
for day in result.days:
print(f" {day.date}: {day.spam_complaint}")async def main():
result = await client.stats.tracked_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Tracked: {result.tracked}")async def main():
result = await client.stats.open_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Opens: {result.opens} Unique: {result.unique}")
for day in result.days:
print(f" {day.date}: opens={day.opens} unique={day.unique}")Device/platform breakdown for opens (desktop, mobile, webmail).
async def main():
result = await client.stats.platform_usage(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Desktop: {result.desktop}")
print(f"Mobile: {result.mobile}")
print(f"Unknown: {result.unknown}")
print(f"Webmail: {result.web_mail}")async def main():
result = await client.stats.email_client_usage(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
# Client names are dynamic keys, so each day is a plain dict
for day in result.days:
print(day) # {"Date": "2024-01-01", "Apple Mail": 12, "Gmail": 7, ...}
print(result.model_extra) # totals per client, e.g. {"Apple Mail": 12, "Gmail": 7}async def main():
result = await client.stats.read_times(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
# Read-time buckets are dynamic keys, so each day is a plain dict
for day in result.days:
print(day) # {"Date": "2024-01-01", "<bucket>": 5, ...}
print(result.model_extra) # totals per bucketasync def main():
result = await client.stats.click_counts(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Clicks: {result.clicks} Unique: {result.unique}")
for day in result.days:
print(f" {day.date}: clicks={day.clicks} unique={day.unique}")async def main():
result = await client.stats.browser_usage(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
# Browser names are dynamic keys, so each day is a plain dict
for day in result.days:
print(day) # {"Date": "2024-01-01", "Chrome": 12, "Safari": 3, ...}
print(result.model_extra) # totals per browser, e.g. {"Chrome": 12, "Safari": 3}async def main():
result = await client.stats.browser_platform_usage(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"Desktop: {result.desktop}")
print(f"Mobile: {result.mobile}")
print(f"Unknown: {result.unknown}")async def main():
result = await client.stats.click_location(
from_date=date(2024, 1, 1),
to_date=date(2024, 1, 31),
)
print(f"HTML: {result.html} Text: {result.text}")
for day in result.days:
print(f" {day.date}: html={day.html} text={day.text}")