Automate booking confirmations, access notifications, and member billing emails with AI agents that stay in sync with your facility management systems.
Coworking and flexible workspace operators manage a continuous stream of transactional and operational email: booking confirmations, keycard access events, membership renewals, billing receipts, and community announcements. At scale — especially across multiple locations — this volume exceeds what human staff can reliably handle without errors or delays. AI agents can own the full operational email loop, but access control and billing communications carry enough sensitivity that oversight matters. MultiMail's monitored mode is the right default here: agents send autonomously, staff receive notification copies, and the audit trail is available for any dispute.
Members book desks, offices, and conference rooms continuously. Confirmation emails must reflect current availability and room details at send time, not cached state. Stale confirmations cause member conflicts and front-desk overhead.
Keycard provisioning, door code changes, and after-hours access events need to reach the right member immediately. Broadcasting access details to the wrong audience is a physical security risk.
A member with desks in London and San Francisco triggers GDPR for their EU data and CCPA for California. Promotional and community emails must honor each region's consent requirements independently.
Membership renewal reminders and failed payment notices must reflect live billing state. Sending a renewal reminder after a member has already paid, or missing a failed payment alert, erodes trust.
Visitor pre-authorization emails and contractor access notices contain building-specific details that should only reach the sponsoring member and relevant facility staff — not the broader community list.
Configure agents to handle booking confirmations, access provisioning notices, and billing events autonomously. With monitored mode, every outbound message is logged and facility managers receive notification copies without approving each send. Agents move at system speed; humans retain visibility.
For high-sensitivity events — master keycode resets, after-hours override notices, or building incident alerts — route sends through gated_send mode. The agent drafts and queues the message; a staff member approves before delivery. list_pending and decide_email give ops teams a clear approval queue.
Member newsletters, event invites, and community updates are lower-risk and consent-based. Agents can send these autonomously after verifying unsubscribe status via check_inbox and tag_email to track opt-outs. Monitored mode keeps a human informed without slowing the send.
Agents running in gated_all mode can draft responses to tour requests and membership inquiries for staff review before sending. This keeps response times fast while ensuring sales messaging is reviewed before it goes out.
import httpx
from datetime import datetime
def send_booking_confirmation(
member_email: str,
member_name: str,
room_name: str,
location: str,
start_time: datetime,
end_time: datetime,
booking_id: str,
api_key: str,
) -> dict:
payload = {
"to": member_email,
"from": "[email protected]",
"subject": f"Booking confirmed: {room_name} on {start_time.strftime(&"cm">#039;%b %d, %Y')}",
"body": (
f"Hi {member_name},\n\n"
f"Your booking is confirmed.\n\n"
f"Room: {room_name}\n"
f"Location: {location}\n"
f"Date: {start_time.strftime(&"cm">#039;%A, %B %d, %Y')}\n"
f"Time: {start_time.strftime(&"cm">#039;%I:%M %p')} – {end_time.strftime('%I:%M %p')}\n"
f"Booking ID: {booking_id}\n\n"
f"To modify or cancel, reply to this email or visit your member portal."
),
"metadata": {
"booking_id": booking_id,
"location": location,
"event_type": "booking_confirmation",
},
}
resp = httpx.post(
"https://api.multimail.dev/v1/send_email",
json=payload,
headers={"Authorization": f"Bearer {api_key}"},
timeout=10,
)
resp.raise_for_status()
return resp.json()
Send a booking confirmation immediately after a reservation is created. Pulls room details from your facility system and sends via the MultiMail REST API.
import httpx
from datetime import date, timedelta
API_KEY = "$MULTIMAIL_API_KEY"
BASE = "https://api.multimail.dev/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def send_renewal_reminder_if_needed(
member_email: str,
member_name: str,
plan_name: str,
renewal_date: date,
mailbox: str = "[email protected]",
) -> str:
"cm"># Check whether we already sent a renewal notice this cycle
inbox_resp = httpx.post(
f"{BASE}/check_inbox",
json={
"mailbox": mailbox,
"query": f"from:{member_email} OR to:{member_email}",
"since": (date.today() - timedelta(days=7)).isoformat(),
"limit": 10,
},
headers=HEADERS,
timeout=10,
)
inbox_resp.raise_for_status()
recent = inbox_resp.json().get("messages", [])
already_sent = any(
"renewal" in (m.get("subject") or "").lower() for m in recent
)
if already_sent:
return "skipped: renewal notice already sent this cycle"
send_resp = httpx.post(
f"{BASE}/send_email",
json={
"to": member_email,
"from": mailbox,
"subject": f"Your {plan_name} membership renews on {renewal_date.strftime(&"cm">#039;%B %d')}",
"body": (
f"Hi {member_name},\n\n"
f"Your {plan_name} membership renews on {renewal_date.strftime(&"cm">#039;%B %d, %Y')}.\n"
f"No action is needed if your payment method is current.\n\n"
f"To update billing details, visit your member portal."
),
"metadata": {"event_type": "renewal_reminder", "plan": plan_name},
},
headers=HEADERS,
timeout=10,
)
send_resp.raise_for_status()
return send_resp.json()["message_id"]
Query the member's inbox for recent billing activity before sending a renewal reminder, avoiding duplicate sends when payment has already processed.
import httpx
API_KEY = "$MULTIMAIL_API_KEY"
BASE = "https://api.multimail.dev/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def queue_access_alert(
member_email: str,
member_name: str,
event_type: str, "cm"># e.g. "keycode_reset", "after_hours_override"
location: str,
details: str,
) -> dict:
"""Queue an access alert. Stays in pending until a staff member approves via decide_email."""
resp = httpx.post(
f"{BASE}/send_email",
json={
"to": member_email,
"from": "[email protected]",
"subject": f"Access update: {location}",
"body": (
f"Hi {member_name},\n\n"
f"{details}\n\n"
f"If you did not request this change, contact the front desk immediately."
),
"oversight_mode": "gated_send",
"metadata": {
"event_type": event_type,
"location": location,
},
},
headers=HEADERS,
timeout=10,
)
resp.raise_for_status()
return resp.json() "cm"># includes message_id for use with decide_email
def approve_pending_access_alerts(staff_mailbox: str) -> list[dict]:
"""List and approve all pending access alerts queued for this mailbox."""
pending_resp = httpx.get(
f"{BASE}/list_pending",
params={"mailbox": staff_mailbox},
headers=HEADERS,
timeout=10,
)
pending_resp.raise_for_status()
results = []
for msg in pending_resp.json().get("pending", []):
if msg.get("metadata", {}).get("event_type") in ("keycode_reset", "after_hours_override"):
decision = httpx.post(
f"{BASE}/decide_email",
json={"message_id": msg["message_id"], "action": "approve"},
headers=HEADERS,
timeout=10,
)
decision.raise_for_status()
results.append(decision.json())
return results
Queue an access alert for staff approval before it reaches members. Uses gated_send mode via the decide_email tool after listing pending approvals.
import httpx
from typing import List
API_KEY = "$MULTIMAIL_API_KEY"
BASE = "https://api.multimail.dev/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def get_opted_out_members(mailbox: str) -> set[str]:
"""Return emails of members who have unsubscribed."""
resp = httpx.post(
f"{BASE}/manage_contacts",
json={"mailbox": mailbox, "tag": "unsubscribed"},
headers=HEADERS,
timeout=10,
)
resp.raise_for_status()
return {c["email"] for c in resp.json().get("contacts", [])}
def send_community_announcement(
members: List[dict],
subject: str,
body: str,
mailbox: str = "[email protected]",
) -> dict:
opted_out = get_opted_out_members(mailbox)
sent, skipped = [], []
for member in members:
email = member["email"]
if email in opted_out:
skipped.append(email)
continue
resp = httpx.post(
f"{BASE}/send_email",
json={
"to": email,
"from": mailbox,
"subject": subject,
"body": body + "\n\nTo unsubscribe from community emails, reply with UNSUBSCRIBE.",
"metadata": {"event_type": "community_announcement"},
},
headers=HEADERS,
timeout=10,
)
if resp.status_code == 200:
sent.append(email)
return {"sent": len(sent), "skipped_opted_out": len(skipped)}
Before sending a community newsletter, tag opted-out members and skip them. Uses tag_email to record consent state and manage_contacts to filter the send list.
| Regulation | Requirement | How MultiMail helps |
|---|---|---|
| GDPR | Member email addresses, booking history, and access logs are personal data under GDPR. Processing requires a lawful basis — typically contract performance for operational emails, and explicit consent for marketing. Members in the EU have the right to erasure, which includes suppressing their email address from future sends. | MultiMail's tag_email tool lets agents mark contacts with consent state and suppression flags. manage_contacts filters send lists against those tags before any message goes out. Mailbox-level metadata stores the lawful basis for each communication type, giving you a documented record for GDPR Article 30 processing registers. |
| CCPA | California members can opt out of sale or sharing of their personal information, which may include email engagement data shared with third-party marketing platforms. CAN-SPAM requires a working unsubscribe mechanism on all commercial emails and prohibits deceptive subject lines. | Unsubscribe replies are automatically tagged via tag_email when an inbound message contains UNSUBSCRIBE keywords. The check_inbox endpoint lets agents poll for opt-out requests before each campaign send. All outbound email headers include List-Unsubscribe per CAN-SPAM requirements. |
| Local Building and Access Regulations | Building access events — keycard provisioning, visitor pre-authorization, contractor access — may be subject to local property and data protection rules. Access details must be communicated only to authorized parties. Audit trails for who received which access credentials may be required by lease agreements or insurance. | MultiMail's metadata field on every send_email call captures the recipient's role (member, visitor, contractor) and the access event type. The full send history is queryable via check_inbox and get_thread, providing a timestamped audit trail. gated_send mode ensures a staff member reviews access emails before delivery, adding a human checkpoint to the audit record. |
| CAN-SPAM | All commercial emails must include accurate sender identification, a physical address, and a functional opt-out mechanism honored within 10 business days. Transactional emails (booking confirmations, billing receipts) are exempt from opt-out requirements but must still have accurate headers. | MultiMail enforces valid From headers and allows agents to classify each send as transactional or commercial via the metadata field. The tag_email tool records opt-out processing timestamps so you can demonstrate the 10-day compliance window to regulators. |
Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.