Skip to content

SOP: Set Up Webhooks โ€‹

Fresh ๐ŸŒฑ

Webhooks push real-time events (inbound mail, delivery, bounce, complaint) to a public URL you control. For local development you need a public tunnel such as ngrok.

No tunnel? Use WebSockets

If you would rather not run a tunnel, WebSockets give you the same real-time events over a persistent connection with no external tooling.

Prerequisites โ€‹

  • An AgentMail API key
  • A public HTTPS endpoint (ngrok for local dev)
  • A receiver that responds 200 quickly

1. Expose a local endpoint (dev) โ€‹

bash
pip install agentmail flask ngrok
ngrok config add-authtoken YOUR_AUTHTOKEN
ngrok http 5000   # gives you https://<id>.ngrok-free.app

2. Create the webhook subscription โ€‹

bash
curl -X POST https://api.agentmail.to/v0/webhooks \
  -H "Authorization: Bearer $AGENTMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://<id>.ngrok-free.app/webhook",
        "event_types": ["message.received"] }'
python
client.webhooks.create(
    url="https://<id>.ngrok-free.app/webhook",
    event_types=["message.received"],
)

3. Receive and verify โ€‹

Always verify the signature so you only process authentic AgentMail events.

python
from flask import Flask, request
app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook():
    # verify the signature header before trusting the payload
    event = request.json
    if event["type"] == "message.received":
        msg = event["message"]
        # ... handle inbound mail ...
    return "", 200

app.run(port=5000)

See Webhook verification for the exact signature-checking procedure.

Event types โ€‹

message.received, message.sent, message.delivered, message.bounced, message.rejected, message.complained, domain.verified. Full payload schemas: Webhooks API.