Webhooks Overview

Get real-time notifications for email events.

Webhooks are the best way to get real-time information about what’s happening with your emails. Instead of constantly asking the AgentMail API if there’s a new email (a process called polling), you can register a URL, and we will send you a POST request with the details as soon as an event happens.

This event-driven approach is more efficient and allows you to build fast, responsive agents that can react instantly to incoming messages.

Why Use Webhooks?

  • Real-Time Speed: Build conversational agents that can reply to incoming emails in seconds.
  • Efficiency: Eliminates the need for constant polling, which saves you computational resources and simplifies your application logic.

The Webhook Workflow

The process is straightforward:

1

1. Create a Webhook Endpoint

This is a public URL on your server that can accept POST requests. For local development, a tool like ngrok is perfect for creating a secure, public URL that tunnels to your local machine. Your endpoint should immediately return a 200 OK response to acknowledge receipt and process the payload in the background to avoid timeouts.

2

2. Register the Endpoint with AgentMail

You can register your URL using the AgentMail API. When you create a webhook, you’ll specify your endpoint’s URL. As AgentMail currently only supports the message.received event, there’s no need to specify event types.

1client.webhooks.create(
2 url="https://<your-ngrok-url>.ngrok-free.app/webhooks"
3)
3

3. AgentMail Sends Events

When a new message is received in one of your inboxes, AgentMail will immediately send a POST request with a JSON payload to your registered URL.

Payload Structure

When AgentMail sends a webhook, the payload will have the following structure.

Webhook Payload
1{
2 "event_type": "message.received",
3 "event_id": "evt_123abc...",
4 "message": {
5 "from_": ["sender@example.com"],
6 "organization_id": "org_abc123...",
7 "inbox_id": "inbox_def456...",
8 "thread_id": "thd_ghi789...",
9 "message_id": "msg_jkl012...",
10 "labels": ["received"],
11 "timestamp": "2023-10-27T10:00:00Z",
12 "reply_to": ["reply-to@example.com"],
13 "to": ["recipient@example.com"],
14 "cc": ["cc-recipient@example.com"],
15 "bcc": ["bcc-recipient@example.com"],
16 "subject": "Email Subject",
17 "preview": "A short preview of the email text...",
18 "text": "The full text body of the email.",
19 "html": "<html>...</html>",
20 "attachments": [
21 {
22 "attachment_id": "att_pqr678...",
23 "filename": "document.pdf",
24 "content_type": "application/pdf",
25 "size": 123456,
26 "inline": false
27 }
28 ],
29 "in_reply_to": "msg_parent456...",
30 "references": ["msg_ref1...", "msg_ref2..."],
31 "sort_key": "some-sort-key",
32 "updated_at": "2023-10-27T10:00:05Z",
33 "created_at": "2023-10-27T10:00:00Z"
34 }
35}

Field Descriptions

  • event_type (string): The name of the event. Currently, this will always be message.received.
  • event_id (string): A unique identifier for this specific event delivery.
  • message (object): A dictionary containing the full details of the received email message.
    • from_ (array<string>): The sender’s email address. Note the trailing underscore to avoid conflict with the Python keyword.
    • organization_id (string): The ID of your organization.
    • inbox_id (string): The ID of the inbox that received the message.
    • thread_id (string): The ID of the conversation thread.
    • message_id (string): The unique ID of this specific message.
    • labels (array<string>): Labels associated with the message (e.g., received, sent).
    • subject (string): The subject line of the email.
    • preview (string): A short plain-text preview of the email body.
    • text (string): The full plain-text body of the email.
    • html (string): The full HTML body of the email, if present.
    • attachments (array<object>): A list of attachments, each with its own attachment_id, filename, content_type, size, and inline status.
    • in_reply_to (string): The message_id of the email this message is a reply to, if applicable.

Next Steps