agentmail 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/cjs/BaseClient.js +2 -2
  2. package/dist/cjs/api/resources/messages/types/Message.d.ts +1 -0
  3. package/dist/cjs/api/resources/messages/types/MessageHeaders.d.ts +4 -0
  4. package/dist/cjs/api/resources/messages/types/MessageHeaders.js +3 -0
  5. package/dist/cjs/api/resources/messages/types/MessageItem.d.ts +1 -0
  6. package/dist/cjs/api/resources/messages/types/index.d.ts +1 -0
  7. package/dist/cjs/api/resources/messages/types/index.js +1 -0
  8. package/dist/cjs/serialization/resources/messages/types/Message.d.ts +2 -0
  9. package/dist/cjs/serialization/resources/messages/types/Message.js +2 -0
  10. package/dist/cjs/serialization/resources/messages/types/MessageHeaders.d.ts +7 -0
  11. package/dist/cjs/serialization/resources/messages/types/MessageHeaders.js +39 -0
  12. package/dist/cjs/serialization/resources/messages/types/MessageItem.d.ts +2 -0
  13. package/dist/cjs/serialization/resources/messages/types/MessageItem.js +2 -0
  14. package/dist/cjs/serialization/resources/messages/types/index.d.ts +1 -0
  15. package/dist/cjs/serialization/resources/messages/types/index.js +1 -0
  16. package/dist/cjs/version.d.ts +1 -1
  17. package/dist/cjs/version.js +1 -1
  18. package/dist/esm/BaseClient.mjs +2 -2
  19. package/dist/esm/api/resources/messages/types/Message.d.mts +1 -0
  20. package/dist/esm/api/resources/messages/types/MessageHeaders.d.mts +4 -0
  21. package/dist/esm/api/resources/messages/types/MessageHeaders.mjs +2 -0
  22. package/dist/esm/api/resources/messages/types/MessageItem.d.mts +1 -0
  23. package/dist/esm/api/resources/messages/types/index.d.mts +1 -0
  24. package/dist/esm/api/resources/messages/types/index.mjs +1 -0
  25. package/dist/esm/serialization/resources/messages/types/Message.d.mts +2 -0
  26. package/dist/esm/serialization/resources/messages/types/Message.mjs +2 -0
  27. package/dist/esm/serialization/resources/messages/types/MessageHeaders.d.mts +7 -0
  28. package/dist/esm/serialization/resources/messages/types/MessageHeaders.mjs +3 -0
  29. package/dist/esm/serialization/resources/messages/types/MessageItem.d.mts +2 -0
  30. package/dist/esm/serialization/resources/messages/types/MessageItem.mjs +2 -0
  31. package/dist/esm/serialization/resources/messages/types/index.d.mts +1 -0
  32. package/dist/esm/serialization/resources/messages/types/index.mjs +1 -0
  33. package/dist/esm/version.d.mts +1 -1
  34. package/dist/esm/version.mjs +1 -1
  35. package/dist/llms-full.txt +797 -52
  36. package/dist/llms.txt +3 -1
  37. package/package.json +1 -1
@@ -5,7 +5,7 @@
5
5
  <Tip title="Welcome to AgentMail!" icon="fa-solid fa-star" />
6
6
 
7
7
  <Frame caption="We're excited to have you onboard!">
8
- <img src="file:1a083c39-ceed-4591-acaf-4220b54f7913" alt="We're excited to have you onboard!" />
8
+ <img src="file:e3f88ce1-e53f-439a-aeac-faf190593e5b" alt="We're excited to have you onboard!" />
9
9
  </Frame>
10
10
 
11
11
  AgentMail is an API platform for giving AI agents their own inboxes to send, receive, and act upon emails. This allows agents to assume their own identity and communicate via the universal protocol of email with services, people, and other agents.
@@ -171,7 +171,7 @@ This guide will walk you through installing the AgentMail SDK, authenticating wi
171
171
  <Step title="Create an API Key">
172
172
  Now that you're in the console, you'll need to create an API key to
173
173
  authenticate your requests. Navigate to the API Keys section in your console
174
- dashboard. ![API Key Creation Screenshot](file:20e7f82e-4a12-4165-ba99-4b5cff0ac0f5) Click
174
+ dashboard. ![API Key Creation Screenshot](file:2fa577e4-6c00-4f62-ae2b-9ba5079d20cb) Click
175
175
  "Create New API Key" and give it a descriptive name. Once created, copy the
176
176
  API key and store it securely. Create a `.env` file in your project's root
177
177
  directory and add your key to it. We recommend using environment variables to
@@ -322,7 +322,7 @@ Unlike traditional email providers that are designed for human scale, AgentMail
322
322
 
323
323
  As the diagram below illustrates, your `organization` is the top-level container that holds all your resources. You can provision many `Inboxes` within your `organization`, each with its own `Threads`, `Messages`, and `Attachments`, allowing you to manage a large fleet of agents seamlessly.
324
324
 
325
- <img src="file:17d978ed-f12c-4634-8560-1fe14dfd09a0" alt="AgentMail Organizational Hierarchy" />
325
+ <img src="file:6419a54d-fe30-4f23-b249-ac2842dc7b83" alt="AgentMail Organizational Hierarchy" />
326
326
 
327
327
  <Steps>
328
328
  <Step title="Organization">
@@ -742,7 +742,7 @@ Here is an example of a well-structured and styled HTML header:
742
742
  </CodeBlocks>
743
743
 
744
744
  <Frame caption="Look how pretty this message looks!">
745
- <img src="file:c2086bbe-a796-4972-be4d-5e4534c24ca8" alt="rendered css" />
745
+ <img src="file:10d09a4f-c2d8-4127-899a-025a124b54f1" alt="rendered css" />
746
746
  </Frame>
747
747
 
748
748
  ## Receiving `Messages`
@@ -1981,7 +1981,7 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1981
1981
  After creating your domain in the AgentMail Console, click the "Download BIND Zone File" button to get the complete zone file.
1982
1982
 
1983
1983
  <Frame caption="Downloading BIND zone file from AgentMail Console">
1984
- <img src="file:984a2b44-d86f-47bc-ace2-143e0daf1757" alt="Download BIND Zone File from Console" />
1984
+ <img src="file:bc58b8c2-8e6f-4282-82ae-d5bab90972e4" alt="Download BIND Zone File from Console" />
1985
1985
  </Frame>
1986
1986
 
1987
1987
  <Tabs>
@@ -1992,13 +1992,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1992
1992
  2. Click **"Import zone file"** in the top right corner
1993
1993
 
1994
1994
  <Frame caption="Importing BIND zone file in AWS Route 53">
1995
- <img src="file:9647ee70-c593-4daa-a8bf-3079e41ff670" alt="AWS Route 53 BIND Import" />
1995
+ <img src="file:b13c1ad1-3e9a-4673-992c-fb5ef7d689aa" alt="AWS Route 53 BIND Import" />
1996
1996
  </Frame>
1997
1997
 
1998
1998
  3. Paste the CONTENTS of downloaded BIND zone file
1999
1999
 
2000
2000
  <Frame caption="Open the file with text editor and paste the contents. It should look similar to what we have in this image.">
2001
- <img src="file:8e5863f4-bee3-42c8-a6fe-60fc89f9b534" alt="AWS Route 53 BIND Import" />
2001
+ <img src="file:c44a24d3-4c13-4dc0-a0c8-1acbff875faf" alt="AWS Route 53 BIND Import" />
2002
2002
  </Frame>
2003
2003
 
2004
2004
  4. Review the records and click **"Import"**
@@ -2011,13 +2011,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
2011
2011
  2. Navigate to **DNS > Records**
2012
2012
 
2013
2013
  <Frame caption="This is what the page looks like">
2014
- <img src="file:88185597-fdb9-45aa-a132-7b7284bde354" alt="Cloudflare BIND Import" />
2014
+ <img src="file:780cb57b-57ac-4019-93e9-56db287eadaa" alt="Cloudflare BIND Import" />
2015
2015
  </Frame>
2016
2016
 
2017
2017
  3. Click **"Import and Export"**
2018
2018
 
2019
2019
  <Frame caption="You should be able to just drop the file in">
2020
- <img src="file:7fdc901a-28f8-436a-ad49-d2595e448503" alt="Cloudflare BIND Import" />
2020
+ <img src="file:ff8604b6-bc3f-4665-b21e-35753a033a93" alt="Cloudflare BIND Import" />
2021
2021
  </Frame>
2022
2022
 
2023
2023
  4. Upload the downloaded BIND zone file as is
@@ -2030,13 +2030,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
2030
2030
  2. Navigate to the **DNS** subtab of the domain you want to send from
2031
2031
 
2032
2032
  <Frame caption="Click on this button!">
2033
- <img src="file:ad432f5f-3bdd-4e60-ad17-c9129578a975" alt="Porkbun DNS Management" />
2033
+ <img src="file:e68ed8f1-092a-40cc-971d-adb5bcd868cc" alt="Porkbun DNS Management" />
2034
2034
  </Frame>
2035
2035
 
2036
2036
  3. Scroll down to the quick upload section
2037
2037
 
2038
2038
  <Frame caption="Upload your BIND zone file here">
2039
- <img src="file:9a206318-f766-4423-b0aa-3c6f637edb2a" alt="Porkbun Zone File Import" />
2039
+ <img src="file:5d596ae8-43ee-4c8a-af62-459f250b7301" alt="Porkbun Zone File Import" />
2040
2040
  </Frame>
2041
2041
 
2042
2042
  4. Upload the downloaded BIND zone file as is
@@ -2120,7 +2120,7 @@ Configuring your domain is a three-step process: add the domain via API, copy th
2120
2120
  * **Value:** Can directly copy paste the `value` from the API response (e.g., `{random_letters_numbers}.dkim.amazonses.com`).
2121
2121
 
2122
2122
  <Frame caption="Example of adding a CNAME record in Route 53. Notice that AWS already appends the root domain (agentmail.cc) to the end of the name value!">
2123
- <img src="file:1913b0a8-b4bb-4368-b90d-4989059e598a" alt="AWS Route 53 Record Configuration" />
2123
+ <img src="file:496e2c29-5f47-4ab0-8f86-752e2b9ee25e" alt="AWS Route 53 Record Configuration" />
2124
2124
  </Frame>
2125
2125
 
2126
2126
  * **TXT (DMARC/SPF):**
@@ -2842,13 +2842,13 @@ Ngrok creates a secure tunnel from a public URL to your local development server
2842
2842
 
2843
2843
  Visit [ngrok.com](https://ngrok.com/) and click "Sign up" to create a free account.
2844
2844
 
2845
- <img src="file:c15f82e4-27f6-4a70-ac26-add0b5b12db0" alt="Ngrok homepage" />
2845
+ <img src="file:12e912a8-9a87-4eca-bf52-b8b22ca64196" alt="Ngrok homepage" />
2846
2846
 
2847
2847
  ### 1.2 Choose your platform and install
2848
2848
 
2849
2849
  After logging in, ngrok will guide you through the setup process. Select your operating system and follow the installation instructions.
2850
2850
 
2851
- <img src="file:4a0b3ee3-7848-45d2-be50-2b5ff7c85295" alt="Ngrok setup instructions" />
2851
+ <img src="file:36deb6da-c444-4272-9156-2afdfe357619" alt="Ngrok setup instructions" />
2852
2852
 
2853
2853
  For macOS, you can install ngrok via Homebrew:
2854
2854
 
@@ -2894,7 +2894,7 @@ ngrok http 3000
2894
2894
 
2895
2895
  You should see output similar to this:
2896
2896
 
2897
- <img src="file:8bcb8b41-cb1c-462c-8fe4-e9e6a1184d0b" alt="Ngrok terminal output" />
2897
+ <img src="file:f0447993-8b76-4dad-af12-a208a27dba82" alt="Ngrok terminal output" />
2898
2898
 
2899
2899
  Copy the **Forwarding URL** (e.g., `https://your-subdomain.ngrok-free.app`). This is the public URL that AgentMail will use to send webhooks.
2900
2900
 
@@ -2991,7 +2991,7 @@ python webhook_receiver.py
2991
2991
 
2992
2992
  Open your browser and visit `http://127.0.0.1:3000` to see the status page confirming your webhook receiver is running:
2993
2993
 
2994
- <img src="file:ca0e6f7a-9ed4-4689-9508-7a56cef9eaf5" alt="Webhook receiver status page" />
2994
+ <img src="file:10c88199-7f82-479b-ab0a-eb727623ef3c" alt="Webhook receiver status page" />
2995
2995
 
2996
2996
  ## Testing Your Setup
2997
2997
 
@@ -3059,6 +3059,381 @@ For production deployments:
3059
3059
  </CardGroup>
3060
3060
 
3061
3061
 
3062
+ # WebSockets
3063
+
3064
+ > Learn how to use WebSockets for instant email notifications without webhooks or polling.
3065
+
3066
+ WebSockets provide a persistent, bidirectional connection to AgentMail for receiving email events in real-time. Unlike webhooks, WebSockets don't require a public URL or external tools like ngrok.
3067
+
3068
+ ## Why Use WebSockets?
3069
+
3070
+ | Feature | Webhook | WebSocket |
3071
+ | ---------- | --------------------------- | ------------------------ |
3072
+ | Setup | Requires public URL + ngrok | No external tools needed |
3073
+ | Connection | HTTP request per event | Persistent connection |
3074
+ | Direction | AgentMail → Your server | Bidirectional |
3075
+ | Firewall | Must expose port | Outbound only |
3076
+ | Latency | HTTP round-trip | Instant streaming |
3077
+
3078
+ ***
3079
+
3080
+ ## Python SDK
3081
+
3082
+ The Python SDK provides both synchronous and asynchronous WebSocket clients.
3083
+
3084
+ ### Async Usage
3085
+
3086
+ ```python
3087
+ import asyncio
3088
+ from agentmail import AsyncAgentMail, Subscribe, Subscribed, MessageReceivedEvent
3089
+
3090
+ client = AsyncAgentMail(api_key="YOUR_API_KEY")
3091
+
3092
+ async def main():
3093
+ async with client.websockets.connect() as socket:
3094
+ # Subscribe to inboxes
3095
+ await socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
3096
+
3097
+ # Process events as they arrive
3098
+ async for event in socket:
3099
+ if isinstance(event, Subscribed):
3100
+ print(f"Subscribed to: {event.inbox_ids}")
3101
+ elif isinstance(event, MessageReceivedEvent):
3102
+ print(f"New email from: {event.message.from_}")
3103
+ print(f"Subject: {event.message.subject}")
3104
+
3105
+ asyncio.run(main())
3106
+ ```
3107
+
3108
+ ### Sync Usage
3109
+
3110
+ ```python
3111
+ from agentmail import AgentMail, Subscribe, Subscribed, MessageReceivedEvent
3112
+
3113
+ client = AgentMail(api_key="YOUR_API_KEY")
3114
+
3115
+ with client.websockets.connect() as socket:
3116
+ # Subscribe to inboxes
3117
+ socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
3118
+
3119
+ # Process events as they arrive
3120
+ for event in socket:
3121
+ if isinstance(event, Subscribed):
3122
+ print(f"Subscribed to: {event.inbox_ids}")
3123
+ elif isinstance(event, MessageReceivedEvent):
3124
+ print(f"New email from: {event.message.from_}")
3125
+ print(f"Subject: {event.message.subject}")
3126
+ ```
3127
+
3128
+ ### Event Handler Pattern
3129
+
3130
+ You can also use event handlers instead of iterating:
3131
+
3132
+ ```python
3133
+ import asyncio
3134
+ from agentmail import AsyncAgentMail, Subscribe, EventType
3135
+
3136
+ client = AsyncAgentMail(api_key="YOUR_API_KEY")
3137
+
3138
+ async def main():
3139
+ async with client.websockets.connect() as socket:
3140
+ # Register event handlers
3141
+ socket.on(EventType.OPEN, lambda _: print("Connected"))
3142
+ socket.on(EventType.MESSAGE, lambda msg: print("Received:", msg))
3143
+ socket.on(EventType.CLOSE, lambda _: print("Disconnected"))
3144
+ socket.on(EventType.ERROR, lambda err: print("Error:", err))
3145
+
3146
+ # Subscribe and start listening
3147
+ await socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
3148
+ await socket.start_listening()
3149
+
3150
+ asyncio.run(main())
3151
+ ```
3152
+
3153
+ For sync usage with event handlers, run the listener in a background thread:
3154
+
3155
+ ```python
3156
+ import threading
3157
+ from agentmail import AgentMail, Subscribe, EventType
3158
+
3159
+ client = AgentMail(api_key="YOUR_API_KEY")
3160
+
3161
+ with client.websockets.connect() as socket:
3162
+ socket.on(EventType.OPEN, lambda _: print("Connected"))
3163
+ socket.on(EventType.MESSAGE, lambda msg: print("Received:", msg))
3164
+ socket.on(EventType.CLOSE, lambda _: print("Disconnected"))
3165
+ socket.on(EventType.ERROR, lambda err: print("Error:", err))
3166
+
3167
+ socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
3168
+
3169
+ # Start listening in background thread
3170
+ listener = threading.Thread(target=socket.start_listening, daemon=True)
3171
+ listener.start()
3172
+ listener.join()
3173
+ ```
3174
+
3175
+ ***
3176
+
3177
+ ## TypeScript SDK
3178
+
3179
+ The TypeScript SDK provides a WebSocket client with automatic reconnection.
3180
+
3181
+ ### Basic Usage
3182
+
3183
+ ```typescript
3184
+ import { AgentMailClient, AgentMail } from "agentmail";
3185
+
3186
+ const client = new AgentMailClient({
3187
+ apiKey: process.env.AGENTMAIL_API_KEY,
3188
+ });
3189
+
3190
+ async function main() {
3191
+ const socket = await client.websockets.connect();
3192
+
3193
+ // Handle events
3194
+ socket.on("open", () => {
3195
+ console.log("Connected");
3196
+
3197
+ // Subscribe to inboxes after connection is open
3198
+ socket.sendSubscribe({
3199
+ type: "subscribe",
3200
+ inboxIds: ["agent@agentmail.to"],
3201
+ });
3202
+ });
3203
+
3204
+ socket.on("message", (event: AgentMail.Subscribed | AgentMail.MessageReceivedEvent) => {
3205
+ if (event.type === "subscribed") {
3206
+ console.log("Subscribed to:", event.inboxIds);
3207
+ } else if (event.type === "message_received") {
3208
+ console.log("New email from:", event.message.from_);
3209
+ console.log("Subject:", event.message.subject);
3210
+ }
3211
+ });
3212
+
3213
+ socket.on("close", (event) => {
3214
+ console.log("Disconnected:", event.code, event.reason);
3215
+ });
3216
+
3217
+ socket.on("error", (error) => {
3218
+ console.error("Error:", error);
3219
+ });
3220
+ }
3221
+
3222
+ main();
3223
+ ```
3224
+
3225
+ ### React/Next.js Usage
3226
+
3227
+ Using the SDK with React:
3228
+
3229
+ ```typescript
3230
+ import { useEffect, useState } from "react";
3231
+ import { AgentMailClient, AgentMail } from "agentmail";
3232
+
3233
+ function useAgentMailWebSocket(apiKey: string, inboxIds: string[]) {
3234
+ const [lastMessage, setLastMessage] = useState<AgentMail.MessageReceivedEvent | null>(null);
3235
+ const [isConnected, setIsConnected] = useState(false);
3236
+
3237
+ useEffect(() => {
3238
+ const client = new AgentMailClient({ apiKey });
3239
+
3240
+ let socket: Awaited<ReturnType<typeof client.websockets.connect>>;
3241
+
3242
+ async function connect() {
3243
+ socket = await client.websockets.connect();
3244
+
3245
+ socket.on("open", () => {
3246
+ setIsConnected(true);
3247
+ socket.sendSubscribe({
3248
+ type: "subscribe",
3249
+ inboxIds,
3250
+ });
3251
+ });
3252
+
3253
+ socket.on("message", (event) => {
3254
+ if (event.type === "message_received") {
3255
+ setLastMessage(event);
3256
+ }
3257
+ });
3258
+
3259
+ socket.on("close", () => setIsConnected(false));
3260
+ }
3261
+
3262
+ connect();
3263
+ return () => socket?.close();
3264
+ }, [apiKey, inboxIds.join(",")]);
3265
+
3266
+ return { lastMessage, isConnected };
3267
+ }
3268
+ ```
3269
+
3270
+ ***
3271
+
3272
+ ## Subscribe Options
3273
+
3274
+ When subscribing to events, you can filter by inbox, pod, or event type:
3275
+
3276
+ **Python:**
3277
+
3278
+ ```python
3279
+ from agentmail import Subscribe
3280
+
3281
+ # Subscribe to specific inboxes
3282
+ Subscribe(inbox_ids=["inbox1@agentmail.to", "inbox2@agentmail.to"])
3283
+
3284
+ # Subscribe to pods
3285
+ Subscribe(pod_ids=["pod-id-1", "pod-id-2"])
3286
+
3287
+ # Subscribe to specific event types
3288
+ Subscribe(
3289
+ inbox_ids=["agent@agentmail.to"],
3290
+ event_types=["message.received", "message.sent"]
3291
+ )
3292
+ ```
3293
+
3294
+ **TypeScript:**
3295
+
3296
+ ```typescript
3297
+ // Subscribe to specific inboxes
3298
+ socket.sendSubscribe({
3299
+ type: "subscribe",
3300
+ inboxIds: ["inbox1@agentmail.to", "inbox2@agentmail.to"],
3301
+ });
3302
+
3303
+ // Subscribe to pods
3304
+ socket.sendSubscribe({
3305
+ type: "subscribe",
3306
+ podIds: ["pod-id-1", "pod-id-2"],
3307
+ });
3308
+
3309
+ // Subscribe to specific event types
3310
+ socket.sendSubscribe({
3311
+ type: "subscribe",
3312
+ inboxIds: ["agent@agentmail.to"],
3313
+ eventTypes: ["message.received", "message.sent"],
3314
+ });
3315
+ ```
3316
+
3317
+ ***
3318
+
3319
+ ## Event Types
3320
+
3321
+ ### Connection Events
3322
+
3323
+ | Event | Python | TypeScript | Description |
3324
+ | ------------ | ------------ | ---------------------- | ---------------------- |
3325
+ | `subscribed` | `Subscribed` | `AgentMail.Subscribed` | Subscription confirmed |
3326
+
3327
+ ### Message Events
3328
+
3329
+ | Event | Python | TypeScript | Description |
3330
+ | -------------------- | ------------------------ | ---------------------------------- | -------------------- |
3331
+ | `message_received` | `MessageReceivedEvent` | `AgentMail.MessageReceivedEvent` | New email received |
3332
+ | `message_sent` | `MessageSentEvent` | `AgentMail.MessageSentEvent` | Email was sent |
3333
+ | `message_delivered` | `MessageDeliveredEvent` | `AgentMail.MessageDeliveredEvent` | Email was delivered |
3334
+ | `message_bounced` | `MessageBouncedEvent` | `AgentMail.MessageBouncedEvent` | Email bounced |
3335
+ | `message_complained` | `MessageComplainedEvent` | `AgentMail.MessageComplainedEvent` | Email marked as spam |
3336
+ | `message_rejected` | `MessageRejectedEvent` | `AgentMail.MessageRejectedEvent` | Email was rejected |
3337
+
3338
+ ### Domain Events
3339
+
3340
+ | Event | Python | TypeScript | Description |
3341
+ | ----------------- | --------------------- | ------------------------------- | ----------------------------- |
3342
+ | `domain_verified` | `DomainVerifiedEvent` | `AgentMail.DomainVerifiedEvent` | Domain verification completed |
3343
+
3344
+ ***
3345
+
3346
+ ## Message Properties
3347
+
3348
+ The `event.message` object contains:
3349
+
3350
+ | Python | TypeScript | Description |
3351
+ | ------------- | ------------- | ----------------------------- |
3352
+ | `inbox_id` | `inboxId` | Inbox that received the email |
3353
+ | `message_id` | `messageId` | Unique message ID |
3354
+ | `thread_id` | `threadId` | Conversation thread ID |
3355
+ | `from_` | `from_` | Sender email address |
3356
+ | `to` | `to` | Recipients list |
3357
+ | `subject` | `subject` | Subject line |
3358
+ | `text` | `text` | Plain text body |
3359
+ | `html` | `html` | HTML body (if present) |
3360
+ | `attachments` | `attachments` | List of attachments |
3361
+
3362
+ ***
3363
+
3364
+ ## Error Handling
3365
+
3366
+ **Python:**
3367
+
3368
+ ```python
3369
+ from agentmail import AsyncAgentMail, Subscribe, MessageReceivedEvent
3370
+ from agentmail.core.api_error import ApiError
3371
+
3372
+ client = AsyncAgentMail(api_key="YOUR_API_KEY")
3373
+
3374
+ async def main():
3375
+ try:
3376
+ async with client.websockets.connect() as socket:
3377
+ await socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
3378
+
3379
+ async for event in socket:
3380
+ if isinstance(event, MessageReceivedEvent):
3381
+ await process_email(event.message)
3382
+
3383
+ except ApiError as e:
3384
+ print(f"API error: {e.status_code} - {e.body}")
3385
+ except Exception as e:
3386
+ print(f"Connection error: {e}")
3387
+ ```
3388
+
3389
+ **TypeScript:**
3390
+
3391
+ ```typescript
3392
+ import { AgentMailClient, AgentMail, AgentMailError } from "agentmail";
3393
+
3394
+ const client = new AgentMailClient({
3395
+ apiKey: process.env.AGENTMAIL_API_KEY,
3396
+ });
3397
+
3398
+ async function main() {
3399
+ try {
3400
+ const socket = await client.websockets.connect();
3401
+
3402
+ socket.on("open", () => {
3403
+ socket.sendSubscribe({
3404
+ type: "subscribe",
3405
+ inboxIds: ["agent@agentmail.to"],
3406
+ });
3407
+ });
3408
+
3409
+ socket.on("message", (event: AgentMail.MessageReceivedEvent) => {
3410
+ if (event.type === "message_received") {
3411
+ processEmail(event.message);
3412
+ }
3413
+ });
3414
+
3415
+ socket.on("error", (error) => {
3416
+ console.error("WebSocket error:", error);
3417
+ });
3418
+
3419
+ socket.on("close", (event) => {
3420
+ console.log("Disconnected:", event.code, event.reason);
3421
+ });
3422
+ } catch (err) {
3423
+ if (err instanceof AgentMailError) {
3424
+ console.error(`API error: ${err.statusCode} - ${err.message}`);
3425
+ } else {
3426
+ console.error("Connection error:", err);
3427
+ }
3428
+ }
3429
+ }
3430
+
3431
+ main();
3432
+ ```
3433
+
3434
+ ***
3435
+
3436
+
3062
3437
  # Email Deliverability
3063
3438
 
3064
3439
  > Learn the strategies and best practices for maximizing your email deliverability with AgentMail.
@@ -3113,7 +3488,7 @@ How you send your emails is just as important as what you send. If you're sendin
3113
3488
  more natural to email providers. AgentMail's ability to create inboxes at
3114
3489
  scale makes this strategy easy to implement.
3115
3490
 
3116
- <img src="file:a620b6d7-d2f7-4925-94ce-afcd6fb2ff4c" alt="Diagram comparing one inbox sending 1000 emails vs. five inboxes sending 200 each." />
3491
+ <img src="file:3417d8c2-94bc-4f35-aaad-c01abf678422" alt="Diagram comparing one inbox sending 1000 emails vs. five inboxes sending 200 each." />
3117
3492
  </Step>
3118
3493
 
3119
3494
  <Step title="Protect Your Reputation with Multiple Domains">
@@ -5132,7 +5507,7 @@ Done
5132
5507
 
5133
5508
  Go to your AgentMail inbox and filter by labels to organize your emails:
5134
5509
 
5135
- <img src="file:2d19dca9-3d2a-43a1-a741-27bc0b88bc19" alt="Test image" />
5510
+ <img src="file:a6b17d0b-afdd-4747-a4bb-eec153ba7fbc" alt="Test image" />
5136
5511
 
5137
5512
  **Filter by sentiment:**
5138
5513
 
@@ -5954,55 +6329,137 @@ We hope this provides a clear and transparent look into why these DNS records ar
5954
6329
 
5955
6330
  # SOC 2 Compliance
5956
6331
 
5957
- > AgentMail's SOC 2 Type II certification and what it means for your data security
6332
+ > AgentMail's SOC 2 Type I achievement and Type II certification progress.
5958
6333
 
5959
- AgentMail is **SOC 2 Type II certified**, demonstrating our commitment to maintaining the highest standards of security, availability, and confidentiality for your data.
6334
+ > AgentMail has **achieved SOC 2 Type I compliance** (July 2025) and is currently working toward **Type II certification** (target: Q1 2026).
5960
6335
 
5961
- <img src="file:7e299fb7-9841-4f90-a033-b5e4878067b1" alt="SOC 2 Type II Certified" />
6336
+ ***
6337
+
6338
+ ## Current Status
6339
+
6340
+ <CardGroup cols={2}>
6341
+ <Card title="Type I Achieved" icon="check-circle">
6342
+ **Completed July 2025** - Controls properly designed and in place
6343
+ </Card>
6344
+
6345
+ <Card title="Type II In Progress" icon="spinner">
6346
+ **Target Q1 2026** - Demonstrating operational effectiveness over time
6347
+ </Card>
6348
+ </CardGroup>
6349
+
6350
+ ### Compliance Timeline
6351
+
6352
+ | Phase | Period | Status |
6353
+ | ------------------------------ | ------------------- | ----------- |
6354
+ | **Type I Preparation** | June 2025 | Completed |
6355
+ | **Type I Assessment** | July 2025 | Completed |
6356
+ | **Type II Observation Period** | Aug 2025 - Dec 2025 | In Progress |
6357
+ | **Type II Certification** | Q1 2026 | Target |
6358
+
6359
+ ***
5962
6360
 
5963
6361
  ## What is SOC 2?
5964
6362
 
5965
- SOC 2 is a rigorous auditing standard developed by the American Institute of Certified Public Accountants (AICPA). It evaluates how organizations manage customer data based on five principles:
6363
+ **SOC 2** is an attestation standard by **AICPA** (The American Institute of Certified Public Accountants) evaluating controls over:
5966
6364
 
5967
- * **Security**: Protection against unauthorized access
5968
- * **Availability**: Systems are operational and accessible as committed
5969
- * **Processing Integrity**: Data processing is complete, accurate, and authorized
5970
- * **Confidentiality**: Information designated as confidential is protected
5971
- * **Privacy**: Personal information is collected, used, and retained appropriately
6365
+ 1. **Security** - Protection against unauthorized access, both physical and logical
6366
+ 2. **Availability** - System accessibility and operational performance as committed
6367
+ 3. **Processing Integrity** - System processing is complete, valid, accurate, timely, and authorized
6368
+ 4. **Confidentiality** - Information designated as confidential is protected
6369
+ 5. **Privacy** - Personal information is collected, used, retained, disclosed, and disposed per privacy commitments
5972
6370
 
5973
- ## What does this mean for you?
6371
+ ### Report Types
5974
6372
 
5975
- When you use AgentMail, you can trust that:
6373
+ * **Type I**: Verifies that security controls are properly **designed** at a point in time.
6374
+ * **Type II**: Validates that controls **operate effectively** over a period (typically 6–12 months).
5976
6375
 
5977
- <AccordionGroup>
5978
- <Accordion title="Your data is protected by enterprise-grade security">
5979
- We've implemented comprehensive security controls that have been
5980
- independently verified by third-party auditors. This includes access
5981
- controls, encryption, and continuous monitoring.
5982
- </Accordion>
6376
+ <Callout intent="success">
6377
+ AgentMail's SOC 2 Type I report confirms that our security infrastructure is properly designed and implemented.
6378
+ </Callout>
5983
6379
 
5984
- <Accordion title="We follow industry best practices">
5985
- Our policies and procedures align with established security frameworks. We
5986
- don't just claim to be secure—we prove it through regular audits.
5987
- </Accordion>
6380
+ ***
5988
6381
 
5989
- <Accordion title="Our controls are continuously monitored">
5990
- SOC 2 Type II certification means our controls were tested over an
5991
- observation period, not just at a single point in time. This demonstrates
5992
- consistent, ongoing compliance.
5993
- </Accordion>
5994
- </AccordionGroup>
6382
+ ## Security Controls Implemented
6383
+
6384
+ The following controls have been audited and verified as part of our SOC 2 Type I compliance:
5995
6385
 
5996
- ## Our Certifications
6386
+ ### Access Control
5997
6387
 
5998
- | Certification | Status | Last Audit |
5999
- | ------------- | ----------- | ------------- |
6000
- | SOC 2 Type I | Compliant | — |
6001
- | SOC 2 Type II | ✅ Compliant | November 2025 |
6388
+ * Role-based access; **least privilege** enforced
6389
+ * **MFA** (Multi-Factor Authentication) for administrative access and sensitive operations
6390
+ * Quarterly access reviews and revocation upon role change
6002
6391
 
6003
- ## Request Compliance Documentation
6392
+ ### Encryption & Key Management
6004
6393
 
6005
- Need our SOC 2 report for your vendor assessment? Contact our team at [founders@agentmail.cc](mailto:founders@agentmail.cc) to request access to our compliance documentation.
6394
+ * **TLS 1.2+** for all service/API communications
6395
+ * Data at rest encrypted using industry-standard ciphers
6396
+ * Centralized **KMS** (Key Management Service) for key generation, rotation, and revocation
6397
+ * **Encrypted point-in-time backups** with 30-day retention
6398
+
6399
+ See [Security Overview](https://agentmail.to/security) for more details.
6400
+
6401
+ ### Email Authentication & Anti-Abuse
6402
+
6403
+ * **SPF, DKIM, DMARC** configured across all sending domains
6404
+ * Real-time scanning of inbound/outbound messages for malware/phishing
6405
+ * IP-based **rate limiting** and behavioral abuse detection
6406
+
6407
+ See [Email Protocols](https://docs.agentmail.to/email-protocols) for technical details.
6408
+
6409
+ ### Monitoring & Incident Response
6410
+
6411
+ * Centralized logging and anomaly detection with alerting
6412
+ * Documented incident response process: detect → triage → contain → eradicate → recover → post-incident review
6413
+ * Responsible disclosure channel for external security researchers
6414
+
6415
+ ### Resilience, Backup & Recovery
6416
+
6417
+ * Daily encrypted backups with **30-day retention**
6418
+ * Regular **restore tests** to validate RTO/RPO targets
6419
+ * Multi-AZ/high-availability architecture for critical components
6420
+
6421
+ ***
6422
+
6423
+ ## SOC 2 Control Mapping
6424
+
6425
+ | Control Area | Implementation | SOC 2 Criteria |
6426
+ | -------------------- | ---------------------------------------------- | -------------- |
6427
+ | Access Control | RBAC, MFA, quarterly reviews | CC6.1–CC6.7 |
6428
+ | Encryption & KMS | TLS 1.2+, at-rest encryption, key rotation | CC6.8–CC6.9 |
6429
+ | Email Authentication | SPF/DKIM/DMARC, anti-abuse filters | CC7.1–CC7.4 |
6430
+ | Threat Monitoring | Centralized logs, alerts, malware scanning | CC7.2–CC7.4 |
6431
+ | Backup & Recovery | Daily backups, 30-day retention, restore tests | CC7.3 |
6432
+ | Incident Response | Runbooks, post-mortems, disclosure program | CC7.4–CC7.5 |
6433
+ | Workforce Security | Security training, NDAs, background checks | CC5.3–CC5.4 |
6434
+
6435
+ > The above mappings reflect our audited Type I controls and are maintained during the Type II observation period.
6436
+
6437
+ ***
6438
+
6439
+ ## Type II Certification Progress
6440
+
6441
+ AgentMail is currently in the **Type II observation period** (August 2025 - December 2025), during which an independent auditor is testing and validating that our security controls operate effectively over time.
6442
+
6443
+ ### What's Being Tested
6444
+
6445
+ * **Continuous Operation**: Controls function consistently without gaps
6446
+ * **Change Management**: Security maintained through system updates and changes
6447
+ * **Evidence Collection**: Logs, tickets, training records, access reviews
6448
+ * **Incident Handling**: Real-world response to security events (if any)
6449
+
6450
+ ### Expected Completion
6451
+
6452
+ **Q1 2026** - Full SOC 2 Type II certification report from independent CPA firm
6453
+
6454
+ Type II certification provides the highest level of assurance that AgentMail's security controls are not only well-designed but also operate effectively over time.
6455
+
6456
+ ***
6457
+
6458
+ ## Accessing SOC 2 Reports
6459
+
6460
+ Organizations evaluating AgentMail can [request SOC 2 documentation](mailto:security@agentmail.to).
6461
+
6462
+ ***
6006
6463
 
6007
6464
 
6008
6465
  # API Welcome
@@ -9724,6 +10181,8 @@ components:
9724
10181
  $ref: '#/components/schemas/type_messages:Addresses'
9725
10182
  type_messages:SendMessageBcc:
9726
10183
  $ref: '#/components/schemas/type_messages:Addresses'
10184
+ type_messages:ReplyAll:
10185
+ type: boolean
9727
10186
  type_messages:MessageText:
9728
10187
  type: string
9729
10188
  type_messages:MessageHtml:
@@ -9766,6 +10225,8 @@ components:
9766
10225
  $ref: '#/components/schemas/type_messages:SendMessageCc'
9767
10226
  bcc:
9768
10227
  $ref: '#/components/schemas/type_messages:SendMessageBcc'
10228
+ reply_all:
10229
+ $ref: '#/components/schemas/type_messages:ReplyAll'
9769
10230
  text:
9770
10231
  $ref: '#/components/schemas/type_messages:MessageText'
9771
10232
  html:
@@ -9934,6 +10395,290 @@ let dataTask = session.dataTask(with: request as URLRequest, completionHandler:
9934
10395
  dataTask.resume()
9935
10396
  ```
9936
10397
 
10398
+ # Reply All Message
10399
+
10400
+ POST https://api.agentmail.to/v0/inboxes/{inbox_id}/messages/{message_id}/reply-all
10401
+ Content-Type: application/json
10402
+
10403
+ Reference: https://docs.agentmail.to/api-reference/inboxes/messages/reply-all
10404
+
10405
+ ## OpenAPI Specification
10406
+
10407
+ ```yaml
10408
+ openapi: 3.1.1
10409
+ info:
10410
+ title: Reply All Message
10411
+ version: endpoint_inboxes/messages.reply-all
10412
+ paths:
10413
+ /v0/inboxes/{inbox_id}/messages/{message_id}/reply-all:
10414
+ post:
10415
+ operationId: reply-all
10416
+ summary: Reply All Message
10417
+ tags:
10418
+ - - subpackage_inboxes
10419
+ - subpackage_inboxes/messages
10420
+ parameters:
10421
+ - name: inbox_id
10422
+ in: path
10423
+ required: true
10424
+ schema:
10425
+ $ref: '#/components/schemas/type_inboxes:InboxId'
10426
+ - name: message_id
10427
+ in: path
10428
+ required: true
10429
+ schema:
10430
+ $ref: '#/components/schemas/type_messages:MessageId'
10431
+ - name: Authorization
10432
+ in: header
10433
+ description: >-
10434
+ Bearer authentication of the form `Bearer <token>`, where token is
10435
+ your auth token.
10436
+ required: true
10437
+ schema:
10438
+ type: string
10439
+ responses:
10440
+ '200':
10441
+ description: Response with status 200
10442
+ content:
10443
+ application/json:
10444
+ schema:
10445
+ $ref: '#/components/schemas/type_messages:SendMessageResponse'
10446
+ '400':
10447
+ description: Error response with status 400
10448
+ content: {}
10449
+ '403':
10450
+ description: Error response with status 403
10451
+ content: {}
10452
+ '404':
10453
+ description: Error response with status 404
10454
+ content: {}
10455
+ requestBody:
10456
+ content:
10457
+ application/json:
10458
+ schema:
10459
+ $ref: '#/components/schemas/type_messages:ReplyAllMessageRequest'
10460
+ components:
10461
+ schemas:
10462
+ type_inboxes:InboxId:
10463
+ type: string
10464
+ type_messages:MessageId:
10465
+ type: string
10466
+ type_messages:MessageLabels:
10467
+ type: array
10468
+ items:
10469
+ type: string
10470
+ type_messages:Addresses:
10471
+ oneOf:
10472
+ - type: string
10473
+ - type: array
10474
+ items:
10475
+ type: string
10476
+ type_messages:SendMessageReplyTo:
10477
+ $ref: '#/components/schemas/type_messages:Addresses'
10478
+ type_messages:MessageText:
10479
+ type: string
10480
+ type_messages:MessageHtml:
10481
+ type: string
10482
+ type_attachments:AttachmentFilename:
10483
+ type: string
10484
+ type_attachments:AttachmentContentType:
10485
+ type: string
10486
+ type_attachments:AttachmentContent:
10487
+ type: string
10488
+ type_attachments:SendAttachment:
10489
+ type: object
10490
+ properties:
10491
+ filename:
10492
+ $ref: '#/components/schemas/type_attachments:AttachmentFilename'
10493
+ content_type:
10494
+ $ref: '#/components/schemas/type_attachments:AttachmentContentType'
10495
+ content:
10496
+ $ref: '#/components/schemas/type_attachments:AttachmentContent'
10497
+ required:
10498
+ - content
10499
+ type_messages:SendMessageAttachments:
10500
+ type: array
10501
+ items:
10502
+ $ref: '#/components/schemas/type_attachments:SendAttachment'
10503
+ type_messages:SendMessageHeaders:
10504
+ type: object
10505
+ additionalProperties:
10506
+ type: string
10507
+ type_messages:ReplyAllMessageRequest:
10508
+ type: object
10509
+ properties:
10510
+ labels:
10511
+ $ref: '#/components/schemas/type_messages:MessageLabels'
10512
+ reply_to:
10513
+ $ref: '#/components/schemas/type_messages:SendMessageReplyTo'
10514
+ text:
10515
+ $ref: '#/components/schemas/type_messages:MessageText'
10516
+ html:
10517
+ $ref: '#/components/schemas/type_messages:MessageHtml'
10518
+ attachments:
10519
+ $ref: '#/components/schemas/type_messages:SendMessageAttachments'
10520
+ headers:
10521
+ $ref: '#/components/schemas/type_messages:SendMessageHeaders'
10522
+ type_threads:ThreadId:
10523
+ type: string
10524
+ type_messages:SendMessageResponse:
10525
+ type: object
10526
+ properties:
10527
+ message_id:
10528
+ $ref: '#/components/schemas/type_messages:MessageId'
10529
+ thread_id:
10530
+ $ref: '#/components/schemas/type_threads:ThreadId'
10531
+ required:
10532
+ - message_id
10533
+ - thread_id
10534
+
10535
+ ```
10536
+
10537
+ ## SDK Code Examples
10538
+
10539
+ ```typescript
10540
+ import { AgentMailClient } from "agentmail";
10541
+
10542
+ async function main() {
10543
+ const client = new AgentMailClient({
10544
+ environment: "https://api.agentmail.to",
10545
+ apiKey: "YOUR_TOKEN_HERE",
10546
+ });
10547
+ await client.inboxes.messages.replyAll("inbox_id", "message_id", {});
10548
+ }
10549
+ main();
10550
+
10551
+ ```
10552
+
10553
+ ```python
10554
+ from agentmail import AgentMail
10555
+
10556
+ client = AgentMail(
10557
+ base_url="https://api.agentmail.to",
10558
+ api_key="YOUR_TOKEN_HERE"
10559
+ )
10560
+
10561
+ client.inboxes.messages.reply_all(
10562
+ inbox_id="inbox_id",
10563
+ message_id="message_id"
10564
+ )
10565
+
10566
+ ```
10567
+
10568
+ ```go
10569
+ package main
10570
+
10571
+ import (
10572
+ "fmt"
10573
+ "strings"
10574
+ "net/http"
10575
+ "io"
10576
+ )
10577
+
10578
+ func main() {
10579
+
10580
+ url := "https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all"
10581
+
10582
+ payload := strings.NewReader("{}")
10583
+
10584
+ req, _ := http.NewRequest("POST", url, payload)
10585
+
10586
+ req.Header.Add("Authorization", "Bearer <api_key>")
10587
+ req.Header.Add("Content-Type", "application/json")
10588
+
10589
+ res, _ := http.DefaultClient.Do(req)
10590
+
10591
+ defer res.Body.Close()
10592
+ body, _ := io.ReadAll(res.Body)
10593
+
10594
+ fmt.Println(res)
10595
+ fmt.Println(string(body))
10596
+
10597
+ }
10598
+ ```
10599
+
10600
+ ```ruby
10601
+ require 'uri'
10602
+ require 'net/http'
10603
+
10604
+ url = URI("https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all")
10605
+
10606
+ http = Net::HTTP.new(url.host, url.port)
10607
+ http.use_ssl = true
10608
+
10609
+ request = Net::HTTP::Post.new(url)
10610
+ request["Authorization"] = 'Bearer <api_key>'
10611
+ request["Content-Type"] = 'application/json'
10612
+ request.body = "{}"
10613
+
10614
+ response = http.request(request)
10615
+ puts response.read_body
10616
+ ```
10617
+
10618
+ ```java
10619
+ HttpResponse<String> response = Unirest.post("https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all")
10620
+ .header("Authorization", "Bearer <api_key>")
10621
+ .header("Content-Type", "application/json")
10622
+ .body("{}")
10623
+ .asString();
10624
+ ```
10625
+
10626
+ ```php
10627
+ <?php
10628
+
10629
+ $client = new \GuzzleHttp\Client();
10630
+
10631
+ $response = $client->request('POST', 'https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all', [
10632
+ 'body' => '{}',
10633
+ 'headers' => [
10634
+ 'Authorization' => 'Bearer <api_key>',
10635
+ 'Content-Type' => 'application/json',
10636
+ ],
10637
+ ]);
10638
+
10639
+ echo $response->getBody();
10640
+ ```
10641
+
10642
+ ```csharp
10643
+ var client = new RestClient("https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all");
10644
+ var request = new RestRequest(Method.POST);
10645
+ request.AddHeader("Authorization", "Bearer <api_key>");
10646
+ request.AddHeader("Content-Type", "application/json");
10647
+ request.AddParameter("application/json", "{}", ParameterType.RequestBody);
10648
+ IRestResponse response = client.Execute(request);
10649
+ ```
10650
+
10651
+ ```swift
10652
+ import Foundation
10653
+
10654
+ let headers = [
10655
+ "Authorization": "Bearer <api_key>",
10656
+ "Content-Type": "application/json"
10657
+ ]
10658
+ let parameters = [] as [String : Any]
10659
+
10660
+ let postData = JSONSerialization.data(withJSONObject: parameters, options: [])
10661
+
10662
+ let request = NSMutableURLRequest(url: NSURL(string: "https://api.agentmail.to/v0/inboxes/inbox_id/messages/message_id/reply-all")! as URL,
10663
+ cachePolicy: .useProtocolCachePolicy,
10664
+ timeoutInterval: 10.0)
10665
+ request.httpMethod = "POST"
10666
+ request.allHTTPHeaderFields = headers
10667
+ request.httpBody = postData as Data
10668
+
10669
+ let session = URLSession.shared
10670
+ let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
10671
+ if (error != nil) {
10672
+ print(error as Any)
10673
+ } else {
10674
+ let httpResponse = response as? HTTPURLResponse
10675
+ print(httpResponse)
10676
+ }
10677
+ })
10678
+
10679
+ dataTask.resume()
10680
+ ```
10681
+
9937
10682
  # Update Message
9938
10683
 
9939
10684
  PATCH https://api.agentmail.to/v0/inboxes/{inbox_id}/messages/{message_id}