Real estate agents lose qualified leads when inquiry responses take hours instead of minutes, destroying conversion rates and customer experience. AgentMail provides an Email Inbox API built for AI agents to monitor inbound messages, extract context, and auto-draft personalized replies at speed. Use AgentMail to search incoming property inquiries, extract buyer details, and generate showing confirmations within seconds—hitting the critical 5-minute response window. Monitor email as a native agent capability rather than manual polling, enabling 24/7 autonomous lead engagement without human delay.
What this tutorial covers
- •Outcome: Build an autonomous workflow that detects new property inquiries, qualifies leads via email content, and drafts personalized showing confirmations ready for review or auto-send.
- •Endpoints used: `GET /v0/inboxes/{inbox_id}/messages/search`, `GET /v0/inboxes/{inbox_id}/messages/{message_id}`, `POST /v0/inboxes/{inbox_id}/drafts`, `PATCH /v0/inboxes/{inbox_id}/drafts/{draft_id}`, `POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply`
- •SDK methods: `searchMessages(inboxId, query)`, `getMessage(inboxId, messageId)`, `createDraft(inboxId, payload)`, `updateDraft(inboxId, draftId, updates)`, `replyToMessage(inboxId, messageId, payload)`
- •Language: typescript
- •Auth: Bearer token (Authorization header)
- •Estimated implementation time: ~18 minutes
Step 1: Search Incoming Property Inquiries with AgentMail
Trigger an agent to poll AgentMail for new inquiry emails using the search endpoint, filtering by sender domain, timestamp, or subject keywords like 'showing' or 'availability'. This retrieves unread or recent messages that match lead qualification criteria, enabling the agent to process them before response windows close.
Query inbox for new inquiries
1const inboxId = process.env.INBOX_ID;
2const apiToken = process.env.API_TOKEN;
3
4const res = await fetch(`https://api.agentmail.to/v0/inboxes/${inboxId}/messages/search`, {
5 method: "GET",
6 headers: {
7 "Authorization": apiToken,
8 "Content-Type": "application/json"
9 }
10});
11const data = await res.json();
12
13for (const message of data.messages) {
14 const labels = message.labels;
15 if (labels.length > 0) {
16 console.log(`Processing inquiry: ${message.message_id} from ${message.timestamp}`);
17 }
18}Response:
1const res = await fetch("https://api.agentmail.to/v0/inboxes/{inbox_id}/messages/search", {
2 method: "GET",
3 headers: {
4 "Authorization": `${process.env.API_TOKEN}`,
5 "Content-Type": "application/json"
6 }
7});
8const data = await res.json();
9// Response shape for incoming property inquiries:
10// { "count": 0, "limit": 0, "next_page_token": "string", "messages": [{ "inbox_id": "string", "thread_id": "string", "message_id": "string", "labels": [], "timestamp": "2026-01-01T00:00:00Z" }] }Step 2: Retrieve Full Message Content for Lead Qualification
Fetch the complete message body and metadata for each inquiry using the get-message endpoint, allowing your agent to extract buyer preferences, property interest, and availability. This context feeds downstream LLM analysis to determine showing eligibility and personalization details.
Load inquiry details
Response:
1const res = await fetch("https://api.agentmail.to/v0/inboxes/{inbox_id}/messages/{message_id}", {
2 method: "GET",
3 headers: {
4 "Authorization": `${process.env.API_TOKEN}`,
5 "Content-Type": "application/json"
6 }
7});
8const data = await res.json();
9// Response shape for full message content:
10const messageContent = {
11 inbox_id: data.inbox_id,
12 thread_id: data.thread_id,
13 message_id: data.message_id,
14 labels: data.labels,
15 timestamp: data.timestamp
16};
17return messageContent;Step 3: Create Personalized Showing Confirmation Drafts
Use AgentMail's draft endpoint to compose a showing confirmation email populated with the buyer's name, property details, and available time slots. Draft mode lets your agent prepare the email without sending it immediately, enabling human review or passing it to another agent for refinement.
Compose confirmation email
Response:
1const res = await fetch("https://api.agentmail.to/v0/inboxes/{inbox_id}/drafts", {
2 method: "POST",
3 headers: {
4 "Authorization": `${process.env.API_TOKEN}`,
5 "Content-Type": "application/json"
6 },
7 body: JSON.stringify({ "labels": ["string"], "reply_to": ["string"], "to": ["string"], "cc": ["string"], "bcc": ["string"] })
8});
9const data = await res.json();
10// Response shape for personalized showing confirmation draft:
11{
12 "inbox_id": "string",
13 "draft_id": "string",
14 "client_id": "string",
15 "labels": ["string"],
16 "reply_to": ["string"]
17}Step 4: Update Drafts Before Sending via AgentMail
Refine your draft by updating subject, body, or recipient fields if additional context becomes available or a human agent approves with edits. AgentMail's patch endpoint allows iterative improvement before final send, reducing errors and improving personalization accuracy.
Refine confirmation message
1const inboxId = "{inbox_id}";
2const draftId = "{draft_id}";
3
4const createRes = await fetch(`https://api.agentmail.to/v0/inboxes/${inboxId}/drafts`, {
5 method: "POST",
6 headers: {
7 "Authorization": `${process.env.API_TOKEN}`,
8 "Content-Type": "application/json"
9 },
10 body: JSON.stringify({ "to": ["recipient@example.com"], "subject": "Initial Draft" })
11});
12const draft = await createRes.json();
13
14const updateRes = await fetch(`https://api.agentmail.to/v0/inboxes/${inboxId}/drafts/${draft.draft_id}`, {
15 method: "PATCH",
16 headers: {
17 "Authorization": `${process.env.API_TOKEN}`,
18 "Content-Type": "application/json"
19 },
20 body: JSON.stringify({ "subject": "Refined Subject with Context", "to": ["newrecipient@example.com"], "cc": ["cc@example.com"] })
21});
22const updated = await updateRes.json();
23console.log("Draft updated:", updated.draft_id);Response:
1const res = await fetch("https://api.agentmail.to/v0/inboxes/{inbox_id}/drafts/{draft_id}", {
2 method: "PATCH",
3 headers: {
4 "Authorization": `${process.env.API_TOKEN}`,
5 "Content-Type": "application/json"
6 },
7 body: JSON.stringify({ "reply_to": ["string"], "to": ["string"], "cc": ["string"], "bcc": ["string"], "subject": "string" })
8});
9const data = await res.json();
10// Response shape: { "inbox_id": "string", "draft_id": "string", "client_id": "string", "labels": ["string"], "reply_to": ["string"] }Step 5: Send Confirmation or Reply via AgentMail
Once the confirmation is finalized, use the reply endpoint to send it back to the original inquiry, threading the response within the same conversation. AgentMail's reply method preserves conversation context and ensures your agent's response is tracked as a reply, maintaining thread integrity for CRM and archive.
Send threaded confirmation
1const inboxId = process.env.INBOX_ID;
2const messageId = process.env.MESSAGE_ID;
3
4const messageRes = await fetch(`https://api.agentmail.to/v0/inboxes/${inboxId}/messages/${messageId}`, {
5 method: "GET",
6 headers: {
7 "Authorization": `${process.env.API_TOKEN}`,
8 "Content-Type": "application/json"
9 }
10});
11const messageData = await messageRes.json();
12
13const replyRes = await fetch(`https://api.agentmail.to/v0/inboxes/${inboxId}/messages/${messageId}/reply`, {
14 method: "POST",
15 headers: {
16 "Authorization": `${process.env.API_TOKEN}`,
17 "Content-Type": "application/json"
18 },
19 body: JSON.stringify({ "labels": ["string"], "reply_to": "string", "to": "string", "cc": "string", "bcc": "string" })
20});
21const replyData = await replyRes.json();
22
23console.log("Reply sent with thread_id:", replyData.thread_id, "message_id:", replyData.message_id);Response:
1const res = await fetch("https://api.agentmail.to/v0/inboxes/{inbox_id}/messages/{message_id}/reply", {
2 method: "POST",
3 headers: {
4 "Authorization": `${process.env.API_TOKEN}`,
5 "Content-Type": "application/json"
6 },
7 body: JSON.stringify({ "labels": ["string"], "reply_to": "string", "to": "string", "cc": "string", "bcc": "string" })
8});
9const data = await res.json();
10// Response shape:
11{
12 "message_id": "string",
13 "thread_id": "string"
14}Step 6: Orchestrate End-to-End Workflow with Agent Logic
Combine AgentMail's endpoints into a continuous loop: poll for inquiries, fetch details, generate confirmations, and send replies—all within your autonomous agent's control flow. This architecture eliminates manual handoff delays and keeps agents responding within the critical 5-minute window that drives real estate conversion.
Complete agent orchestration
The agent continuously monitors your inbox, detects new property inquiries, drafts personalized confirmations, and sends replies within seconds—keeping response times under 5 minutes and maximizing lead conversion.
Common pitfalls when using AgentMail
- •Missing Unread Filter in Search. If you search without 'is:unread', your agent will re-process old inquiries repeatedly. Always include query filters like 'is:unread' or 'timestamp:>2024-01-15' to avoid duplicate confirmations and feedback loops.
- •Timing Gaps Between Poll Cycles. Long intervals between search calls (e.g., 10-minute polls) defeat the 5-minute speed-to-lead window. Run AgentMail searches every 30–60 seconds for new inquiries, or implement webhook listeners if available, to catch leads when they arrive.
- •Hardcoded Property Details in Confirmation. Confirmations mentioning wrong property address, MLS number, or showing times damage trust and waste agent follow-up effort. Extract all property details from the inbound inquiry or query a CRM API before drafting to ensure accuracy.
- •No Human Review Gate for Auto-Send. Sending confirmations directly without agent approval risks errors (wrong email, typos, double-bookings). Keep drafts in draft status, send via email for approval, or add a simple Slack notification for human sign-off before final send.
Ready to eliminate response delays and automate your showing confirmations? Get started with AgentMail and hit the 5-minute lead window every time.
Documentation references
The code examples in this tutorial are grounded in the following docs pages:
- •
Ready to give your agents real email access?
Join leading developers using AgentMail to enable AI agents to send, receive, and search email natively via API.
Read More Blog Posts
Auto-triage incident alerts and escalate with AgentMail
DevOps teams waste time manually sorting noisy alert floods and drafting escalation emails to on-call responders during incidents. AgentMail provides an Email I
Automate order exceptions and supplier escalations with AI agents
Order exceptions like shipment delays and pricing discrepancies require rapid detection and escalation, but manual email coordination slows response. AgentMail

