Give Zapier AI Actions Real Email With Human Oversight

MultiMail adds a dedicated email API and human-approval layer to Zapier AI automations so agents can send, read, and reply without skipping review.


Zapier AI Actions lets you expose Zap automations as callable tools for AI assistants and agentic workflows. When one of those tools involves email — notifying a lead, replying to a support ticket, escalating an alert — the generic Zapier Gmail or Outlook action offers no audit trail, no gating, and no per-tenant policy control.

MultiMail fills that gap. You configure a Zap that calls MultiMail's REST API, expose it as a Zapier AI Action, and your assistant gains a send_email or reply_email tool that routes through MultiMail's oversight layer. Outbound messages queue for human approval under gated_send mode before any bytes leave the server.

Inbound email works the same way in reverse: MultiMail fires a webhook into a Zapier catch hook when mail arrives, giving the AI assistant structured data — sender, subject, body, thread ID — without exposing raw IMAP credentials to your automation stack.

Built for Zapier AI Actions developers

Approval before delivery

Zapier's native email steps send immediately. MultiMail's gated_send mode holds outbound messages until a human approves via the dashboard or the decide_email API endpoint, with a full audit trail attached to every decision.

Per-mailbox oversight policies

Different Zaps warrant different risk tolerance. A CRM follow-up Zap can run under monitored mode while a payment-dispute Zap stays on gated_all. Oversight mode is set per mailbox, not per run, so policies survive Zap edits.

Structured inbound data for downstream steps

MultiMail webhooks emit normalized JSON — thread_id, sender reputation, tag classifications — that Zapier filter and path steps can branch on directly, without a parsing code step.

Tenant isolation for multi-client automations

If you run Zaps on behalf of multiple clients, each client gets their own MultiMail mailbox and API key. Email never crosses tenant boundaries, which matters for GDPR data-processor obligations.

Delivery receipts back into Zap paths

MultiMail webhooks fire on delivery, bounce, and approval events. A Zap path step can branch on approval_granted versus approval_denied and continue automation accordingly, without polling.


Get started in minutes

Calling MultiMail send_email inside a Zap Code step
javascript
const response = await fetch('https://api.multimail.dev/v1/send_email', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: '[email protected]',
    to: inputData.contact_email,
    subject: `Follow-up: ${inputData.deal_name}`,
    body: inputData.generated_body,
    oversight_mode: 'gated_send',
    tags: ['crm', 'zapier-ai'],
    metadata: {
      zap_id: inputData.zap_id,
      deal_id: inputData.deal_id,
    },
  }),
});

const result = await response.json();
if (!response.ok) {
  throw new Error(`MultiMail error: ${result.error}`);
}

"cm">// Return message_id so downstream Zap steps can reference it
output = { message_id: result.message_id, status: result.status };

A Zapier Code (JavaScript) step that calls the MultiMail REST API to queue an outbound email under gated_send oversight. The message ID returned can be stored in a Zapier storage step for later approval tracking.

Exposing MultiMail check_inbox as a Zapier AI Action (Python)
python
import requests

def fetch_unread_via_zapier(zapier_ai_action_id: str, zapier_token: str, mailbox: str) -> dict:
    """Trigger a Zapier AI Action that proxies MultiMail check_inbox."""
    resp = requests.post(
        f"https://actions.zapier.com/api/v1/dynamic/exposed/{zapier_ai_action_id}/execute/",
        headers={"X-API-Key": zapier_token},
        json={
            "instructions": f"Fetch unread emails from {mailbox}",
            "mailbox": mailbox,
            "limit": 10,
            "filter": "unread",
        },
        timeout=15,
    )
    resp.raise_for_status()
    data = resp.json()
    "cm"># The Zap's MultiMail step returns structured messages
    return data.get("results", [])

"cm"># Usage in agent loop
messages = fetch_unread_via_zapier(
    zapier_ai_action_id="01JABCD123",
    zapier_token="sk-zapier-...",
    mailbox="[email protected]",
)
for msg in messages:
    print(msg["subject"], msg["sender"], msg["thread_id"])

Agent code that triggers a Zapier AI Action configured to call MultiMail's check_inbox endpoint. The action returns unread messages the agent can act on without holding raw IMAP credentials.

Handling MultiMail approval webhooks in a Zapier catch hook
javascript
"cm">// Zapier Catch Hook receives MultiMail webhook events
"cm">// Configure webhook URL in MultiMail dashboard under Settings > Webhooks
const event = inputData.event;       "cm">// 'approval.granted' | 'approval.denied'
const messageId = inputData.message_id;
const decisionNote = inputData.note; "cm">// Human reviewer's comment if any

if (event === 'approval.granted') {
  // Message will be delivered by MultiMail automatically
  // Continue Zap path: update CRM, notify Slack, etc.
  output = {
    action: 'continue',
    message_id: messageId,
    note: decisionNote || 'Approved',
  };
} else if (event === 'approval.denied') {
  // Log denial and halt downstream steps
  output = {
    action: 'halt',
    message_id: messageId,
    reason: decisionNote || 'Denied by reviewer',
  };
} else {
  // Unknown event — surface for debugging
  output = { action: 'unknown', event };
}

A Zapier Code step that processes MultiMail's approval.granted or approval.denied event and branches downstream automation — continuing the workflow on approval, logging denial with reason.

MultiMail inbound webhook as a Zapier trigger
javascript
"cm">// Zapier Code step — parse MultiMail inbound webhook payload
"cm">// MultiMail fires this when mail arrives at your mailbox
const payload = JSON.parse(inputData.raw_body || '{}');

const email = {
  message_id:   payload.message_id,
  thread_id:    payload.thread_id,
  from:         payload.from?.address,
  from_name:    payload.from?.name,
  subject:      payload.subject,
  body_text:    payload.body?.text,
  received_at:  payload.received_at,
  "cm">// Reputation fields MultiMail attaches automatically
  sender_score: payload.sender?.reputation_score,
  tags:         (payload.tags || []).join(','),
};

"cm">// Fail loudly if required fields are missing
if (!email.message_id || !email.from) {
  throw new Error('Invalid MultiMail webhook payload — missing message_id or from');
}

output = email;

Configure MultiMail to POST inbound email events to a Zapier catch hook. This Zap path step parses the payload so downstream AI Actions receive clean fields.

Deciding (approving/denying) a pending message via decide_email
javascript
"cm">// inputData.message_id and inputData.decision come from
"cm">// a preceding Zapier approval step or Slack interactive message handler
const { message_id, decision, reviewer_note } = inputData;

const response = await fetch(`https:"cm">//api.multimail.dev/v1/decide_email`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message_id,
    decision,       "cm">// 'approve' | 'deny'
    note: reviewer_note || '',
  }),
});

const result = await response.json();
if (!response.ok) {
  throw new Error(`decide_email failed: ${result.error}`);
}

output = { status: result.status, message_id: result.message_id };

A Zapier Code step that calls MultiMail's decide_email endpoint after a human reviews the message in a Slack approval workflow or similar side-channel.


Step by step

1

Create a MultiMail mailbox and API key

Sign up at multimail.dev and create a mailbox for your Zapier automation (e.g., [email protected]). Copy the mm_live_... API key from the dashboard — you will add this as a Zapier environment variable or secret in the next step.

bash
curl -X POST https://api.multimail.dev/v1/create_mailbox \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d &"cm">#039;{"address": "[email protected]", "oversight_mode": "gated_send"}'
2

Set your MultiMail API key as a Zapier secret

In Zapier, go to your account settings and add MM_API_KEY as an environment variable (Zapier Code steps can read process.env values). For team Zaps, use Zapier's Secret Manager so the key is not stored in plain text inside Zap steps.

3

Build the send Zap with a MultiMail Code step

Create a new Zap with a Webhook or AI Action trigger. Add a Code (JavaScript) step that calls POST https://api.multimail.dev/v1/send_email using the API key from process.env.MM_API_KEY. Map the trigger fields (to, subject, body) into the request body. Set oversight_mode to gated_send.

bash
// Zap Code step — send via MultiMail
const res = await fetch(&"cm">#039;https://api.multimail.dev/v1/send_email', {
  method: &"cm">#039;POST',
  headers: {
    &"cm">#039;Authorization': `Bearer ${process.env.MM_API_KEY}`,
    &"cm">#039;Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: &"cm">#039;[email protected]',
    to: inputData.recipient,
    subject: inputData.subject,
    body: inputData.body,
    oversight_mode: &"cm">#039;gated_send',
  }),
});
const data = await res.json();
output = { message_id: data.message_id };
4

Register the Zap as a Zapier AI Action

In the Zapier AI Actions dashboard, expose this Zap as a callable tool. Give it a clear name (e.g., 'Send CRM follow-up email') and description so the AI assistant can select it correctly. The action takes recipient, subject, and body as inputs and returns message_id.

5

Configure the approval webhook (optional but recommended)

In the MultiMail dashboard under Settings > Webhooks, add your second Zapier catch hook URL as the approval event endpoint. This Zap receives approval.granted and approval.denied events so you can update downstream systems (CRM records, Slack threads) without polling.

bash
curl -X POST https://api.multimail.dev/v1/webhooks \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d &"cm">#039;{"url": "https://hooks.zapier.com/hooks/catch/YOUR_HOOK_ID/", "events": ["approval.granted", "approval.denied", "message.delivered"]}'

Common questions

Does MultiMail have a native Zapier app?
Not yet. The integration uses Zapier Code steps (JavaScript or Python) that call MultiMail's REST API directly. This gives you full control over request shape and error handling. A native Zapier app with pre-built actions is on the roadmap.
Which oversight mode works best for most Zapier automations?
gated_send is the default and the right choice for most Zaps. Reads (check_inbox, read_email) run autonomously, but outbound sends queue for human approval. For high-volume notification Zaps where content is templated and low-risk, monitored mode is appropriate — the agent sends autonomously and humans are notified but not blocking.
Can I use MultiMail inbound webhooks as a Zapier trigger?
Yes. Set up a Zapier catch hook and register its URL in MultiMail under Settings > Webhooks with the message.received event. MultiMail will POST normalized email data to that hook whenever mail arrives at your mailbox, triggering the Zap.
How do I pass the approval decision back to MultiMail from Zapier?
Add a Zapier path or filter step after an approval side-channel (Slack message, email approval link, etc.). The downstream code step calls POST https://api.multimail.dev/v1/decide_email with the message_id and decision ('approve' or 'deny'). MultiMail then delivers or discards the message accordingly.
How do I handle multiple clients with separate mailboxes?
Create one MultiMail mailbox per client tenant and store each client's mm_live_... API key in Zapier Secret Manager keyed by tenant ID. The Zap looks up the correct key at runtime based on the triggering record's tenant field. Email never crosses tenant boundaries in MultiMail's data model.
Are there rate limits I need to account for in Zap design?
MultiMail rate limits are per API key. On the Builder plan, the limit is 5,000 emails per month. For Zaps that could fire at high volume, add a Zapier filter step before the MultiMail code step to discard duplicates, and handle 429 responses in your code step by surfacing them as Zap errors for Zapier's built-in retry logic.
Does this integration satisfy GDPR requirements for email data?
MultiMail processes email data as a data processor under GDPR. Each tenant's data is isolated. For Zapier automations processing EU personal data, ensure your Zapier account's data region is set to EU, and review the MultiMail DPA (available from the dashboard) before going live.

Explore more

The only agent email with a verifiable sender

Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 38-tool MCP server. Formally verified in Lean 4.