-
Notifications
You must be signed in to change notification settings - Fork 0
Webhooks
Greg Svoboda edited this page Mar 4, 2026
·
1 revision
Webhook management is done through ServerClient. You will need a server API token.
import postmark
client = postmark.ServerClient("your-server-token")import asyncio
async def main():
webhooks = await client.webhooks.list()
print(f"Total webhooks: {len(webhooks)}")
for wh in webhooks:
print(f" [{wh.id}] {wh.url}")
print(f" Stream: {wh.message_stream}")
print(f" Opens: {wh.triggers.open.enabled}")
print(f" Bounces: {wh.triggers.bounce.enabled}")
asyncio.run(main())async def main():
wh = await client.webhooks.get(webhook_id=1234)
print(f"URL: {wh.url}")
print(f"Stream: {wh.message_stream}")Webhooks can be scoped to a specific message stream and configured with individual trigger types.
import asyncio
async def main():
wh = await client.webhooks.create(
url="https://example.com/webhook",
message_stream="outbound",
triggers={
"Open": {"Enabled": True, "PostFirstOpenOnly": False},
"Click": {"Enabled": True},
"Bounce": {"Enabled": True, "IncludeContent": False},
"SpamComplaint": {"Enabled": True, "IncludeContent": False},
},
)
print(f"Created webhook ID: {wh.id}")
print(f"URL: {wh.url}")
print(f"Opens: {wh.triggers.open.enabled}")
print(f"Bounces: {wh.triggers.bounce.enabled}")
asyncio.run(main())wh = await client.webhooks.create(
url="https://example.com/webhook",
message_stream="outbound",
http_auth={"Username": "myuser", "Password": "secret"},
triggers={
"Bounce": {"Enabled": True, "IncludeContent": True},
},
)Postmark supports three options for authenticating incoming webhook requests. Use at least one in production.
HTTP Basic Authentication — credentials are verified on every delivery attempt:
wh = await client.webhooks.create(
url="https://example.com/webhook",
http_auth={"Username": "myuser", "Password": "secret"},
)Custom headers — add a shared secret that your receiver checks:
wh = await client.webhooks.create(
url="https://example.com/webhook",
http_headers=[{"Name": "X-Webhook-Secret", "Value": "my-shared-secret"}],
)IP allowlisting — restrict delivery to Postmark's published IP ranges. This is configured in your receiver's firewall or load balancer, not in the SDK.
For Postmark's full security recommendations see the Webhooks Overview.
Update the triggers or other settings on an existing webhook.
import asyncio
async def main():
wh = await client.webhooks.edit(
webhook_id=1234,
triggers={
"Open": {"Enabled": False, "PostFirstOpenOnly": False},
"Bounce": {"Enabled": True, "IncludeContent": True},
},
)
print(f"Updated: opens={wh.triggers.open.enabled} bounces={wh.triggers.bounce.enabled}")
asyncio.run(main())async def main():
await client.webhooks.delete(webhook_id=1234)
print("Deleted")