Skip to content

Webhooks

Greg Svoboda edited this page Mar 4, 2026 · 1 revision

Webhooks

Webhook management is done through ServerClient. You will need a server API token.

import postmark

client = postmark.ServerClient("your-server-token")

List Webhooks

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())

Get a Webhook

async def main():
    wh = await client.webhooks.get(webhook_id=1234)
    print(f"URL:    {wh.url}")
    print(f"Stream: {wh.message_stream}")

Create a Webhook

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())

Webhook with HTTP Authentication

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},
    },
)

Securing Your Webhook Receiver

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.

Edit a Webhook

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())

Delete a Webhook

async def main():
    await client.webhooks.delete(webhook_id=1234)
    print("Deleted")

Further Reading

Clone this wiki locally