Webhook Setup Guide

Step-by-step guide to configure webhooks.

This guide walks you through the complete process of setting up webhooks to receive real-time notifications from AgentMail. You’ll learn how to create an ngrok account, set up an inbox, configure webhooks, and write a simple webhook receiver.

Prerequisites

Before you start, make sure you have:

  • Python 3.8 or higher installed
  • An AgentMail API Key
  • pip package manager
  • Basic familiarity with Python and terminal commands

Installation

First, install the required Python packages:

$pip install agentmail flask ngrok

Step 1: Setting up account on Ngrok

Ngrok creates a secure tunnel from a public URL to your local development server, allowing AgentMail to send webhooks to your machine during development.

1.1 Create an ngrok account

Visit ngrok.com and click “Sign up” to create a free account.

Ngrok homepage

1.2 Choose your platform and install

After logging in, ngrok will guide you through the setup process. Select your operating system and follow the installation instructions.

Ngrok setup instructions

For macOS, you can install ngrok via Homebrew:

$brew install ngrok

After installation, authenticate ngrok with your authtoken (found in your ngrok dashboard):

$ngrok config add-authtoken YOUR_AUTHTOKEN

Step 2: Creating the inbox on AgentMail

Before you can receive webhooks, you need an inbox to receive messages. Create one using the AgentMail API:

1from agentmail import AgentMail
2
3client = AgentMail()
4
5# Create an inbox for your webhook agent
6inbox = client.inboxes.create(
7 username="webhook-demo",
8 client_id="webhook-demo-inbox" # Ensures idempotency
9)
10
11print(f"Inbox created: {inbox.inbox_id}")

The client_id parameter ensures that running this code multiple times won’t create duplicate inboxes. If the inbox already exists, it will return the existing one.

Step 3: Configuring webhook on AgentMail

3.1 Start ngrok tunnel

In your terminal, start an ngrok tunnel to expose your local server (we’ll use port 3000):

$ngrok http 3000

You should see output similar to this:

Ngrok terminal output

Copy the Forwarding URL (e.g., https://your-subdomain.ngrok-free.app). This is the public URL that AgentMail will use to send webhooks.

Use localhost for testing

When viewing your webhook receiver in the browser, use the http://127.0.0.1:3000 URL shown in the “Web Interface” line, not the ngrok URL. The ngrok URL is only for external services like AgentMail.

Why localhost? Safari is stricter than Chrome/Firefox when viewing development servers through HTTPS ngrok tunnels. Safari blocks local WebSockets and some dev-only scripts, which causes the page to show a loading spinner indefinitely due to Hot Module Replacement (HMR). This is expected development behavior and not a documentation issue. Using localhost or static builds avoids this problem.

3.2 Register webhook with AgentMail

Now register your webhook endpoint with AgentMail:

1# Using the ngrok URL you copied
2webhook_url = "https://your-subdomain.ngrok-free.app/webhooks"
3
4webhook = client.webhooks.create(
5 url=webhook_url,
6 client_id="webhook-demo-webhook" # Ensures idempotency
7)
8
9print(f"Webhook created: {webhook.webhook_id}")

Step 4: Code example for receiving webhooks

Create a file named webhook_receiver.py with the following code:

1from flask import Flask, request, Response
2
3app = Flask(__name__)
4
5@app.route('/')
6def home():
7 """Status page to verify server is running"""
8 return """
9 <html>
10 <body style="font-family: sans-serif; max-width: 800px; margin: 50px auto; padding: 20px;">
11 <h1>AgentMail Webhook Receiver</h1>
12 <div style="background: #4CAF50; color: white; padding: 10px 20px;
13 border-radius: 4px; display: inline-block; margin: 20px 0;">
14 Server is running
15 </div>
16 <div style="background: #e3f2fd; padding: 15px; border-radius: 4px;
17 border-left: 4px solid #2196F3;">
18 <h3>Webhook Endpoint Ready</h3>
19 <p>Your webhook endpoint is listening at: <code>POST /webhooks</code></p>
20 </div>
21 <h3>How to use:</h3>
22 <ul>
23 <li>Start ngrok: <code>ngrok http 3000</code></li>
24 <li>Register your webhook with AgentMail using the ngrok URL</li>
25 <li>Send a test email to your AgentMail inbox</li>
26 <li>Watch the console for incoming webhook events</li>
27 </ul>
28 </body>
29 </html>
30 """
31
32@app.route('/webhooks', methods=['POST'])
33def receive_webhook():
34 """Receives webhook events from AgentMail"""
35 payload = request.json
36
37 event_type = payload.get('event_type')
38 message = payload.get('message', {})
39
40 print(f"\nWebhook received: {event_type}")
41 print(f"From: {message.get('from_')}")
42 print(f"Subject: {message.get('subject')}\n")
43
44 return Response(status=200)
45
46if __name__ == '__main__':
47 print("Starting webhook receiver on http://127.0.0.1:3000")
48 app.run(port=3000)

Running your webhook receiver

  1. Make sure ngrok is running in one terminal window
  2. In another terminal, run your webhook receiver:
$python webhook_receiver.py
  1. Send a test email to your AgentMail inbox
  2. Watch the console output for incoming webhook events

Viewing the result

Open your browser and visit http://127.0.0.1:3000 to see the status page confirming your webhook receiver is running:

Webhook receiver status page

Testing Your Setup

To test your webhook setup:

  1. Send an email to your inbox address (e.g., webhook-demo@agentmail.to)
  2. Check your webhook receiver’s console output
  3. You should see the webhook event details printed immediately
Next Steps

Now that your webhook is working, you can extend the receive_webhook() function to:

  • Automatically reply to messages
  • Process attachments
  • Route emails to different handlers based on content
  • Integrate with your AI agent workflows

Check out the Event-Driven Agent Example for a more advanced implementation.

Troubleshooting

  • Verify ngrok is running and the forwarding URL matches your webhook registration
  • Check that your Flask app is running on the correct port (3000)
  • Ensure your webhook URL ends with /webhooks
  • Look for errors in both the Flask console and ngrok web interface

Free ngrok accounts have 2-hour session limits. The tunnel will disconnect and you’ll need to restart ngrok and update your webhook URL with AgentMail.

If port 3000 is already in use, choose a different port:

  • Change the port in app.run(port=XXXX)
  • Update the ngrok command: ngrok http XXXX

Production Considerations

For production deployments:

  • Use a dedicated server: Deploy your webhook receiver to a cloud service (AWS, GCP, Heroku, etc.) instead of using ngrok
  • Implement webhook verification: Validate incoming requests are from AgentMail
  • Add error handling: Implement retry logic and error reporting
  • Use async processing: Return 200 immediately and process webhooks in background jobs
  • Monitor webhook health: Set up logging and alerting for failed webhook deliveries