# Webhooks and Connect: your mail in your own code, and in the AI you use

_A webhook sends each new message for an address to your server as signed JSON. Connect lets Claude, ChatGPT or another AI app read the mailboxes you choose, tag conversations and write drafts. What each one does, how it works, its limits, and what to watch for._

Published 3 November 2026

imado gives a domain you already own a working email address: you connect the domain, create an address like hello@yourdomain.com, and read and reply in your browser. If you have not tried it, [start here](https://www.imado.cloud/docs/get-started).

Much of the mail a business receives is work to be done somewhere else: an order to record, a question to track, an invoice to file. Two parts of imado help you move that mail out of the inbox and into the place where the work happens. **Webhooks** send each new message for an address to your own server. **Connect** lets the AI app you already use, such as Claude or ChatGPT, read the mailboxes you choose, tag conversations and write drafts. This post covers what each one does, how it works, its limits, and the mistakes that are easy to make.

Neither one sends mail. A webhook only tells your server what arrived, and an AI app's draft waits in Drafts until a person presses Send.

## Webhooks

A webhook is a URL on your server that imado calls, with a `POST`, each time a new message arrives for one of your addresses (the exceptions are under [What to watch for](#what-to-watch-for)). Your code decides what happens next. imado keeps the message in the mailbox as always: the webhook gets a copy of what it says, not the message itself.

### How it works

A project admin who reads the mailbox sets it up: in Setup, open the mailbox, choose **Where new mail goes**, pick the address, and type your endpoint's URL. imado sends a test event straight away and shows the signing secret once. Nothing else is sent until your endpoint answers a test with a `2xx`. Everyone else who reads the mailbox is told by email and can see the webhook in **Mail → Settings**.

Each new message then arrives as one call, signed the [Standard Webhooks](https://www.standardwebhooks.com/) way, so any of its libraries can check it. Trimmed, the body looks like this:

```json
{
  "type": "message.received",
  "data": {
    "address": "orders@example.com",
    "received_at": "2026-11-02T08:59:58.000Z",
    "from": { "address": "shop@example.net", "name": "Example Shop" },
    "subject": "New order #1042",
    "text": "You have a new order from Jane Doe…",
    "attachments": [
      {
        "filename": "invoice-1042.pdf",
        "content_type": "application/pdf",
        "size": 48213
      }
    ],
    "authentication": { "spf": "PASS", "dkim": "PASS", "dmarc": "PASS" },
    "url": "https://www.imado.cloud/mail/…"
  }
}
```

`text` holds the message as plain text. Attachments are listed by name, type and size: to get a file, open `url` and download it in imado. [The webhooks docs](https://www.imado.cloud/docs/webhooks) list every field.

Here is a receiver in Node. It checks the signature with the `verified` function from the docs, saves the event with a `save` function you write, and answers:

```js
import { createServer } from "node:http"

import { verified } from "./verified.js" // copied from imado's webhook docs

const secret = process.env.IMADO_WEBHOOK_SECRET
if (!secret) throw new Error("Set IMADO_WEBHOOK_SECRET to your signing secret")

// Yours to write: insert a row keyed by the event id, ignoring a repeat.
async function save(eventId, message) {
  throw new Error("not written yet")
}

createServer((req, res) => {
  const chunks = []
  req.on("data", (chunk) => chunks.push(chunk))
  req.on("end", async () => {
    const raw = Buffer.concat(chunks).toString("utf8")
    if (!verified(secret, req.headers, raw)) {
      res.writeHead(401).end()
      return
    }
    const event = JSON.parse(raw)
    try {
      if (event.type === "message.received") {
        await save(req.headers["webhook-id"], event.data)
      }
      res.writeHead(200).end()
    } catch {
      res.writeHead(500).end() // imado tries again later
    }
  })
}).listen(8080)
```

The test event, `reaction.test`, gets a `200` straight away. A failed save answers `500`, so imado tries again instead of counting the event as delivered. Until you write `save`, every real message fails this way, so check that the first real message is saved, not only the test.

### What you can do with it

- **Put orders and invoices into your own records.** Point a webhook on `orders@` at your server, and each order notification or supplier invoice becomes a row, and the attachment's name tells you a PDF is waiting in imado. Mail written by a program, such as a shop's order notice, reaches a webhook like any other.
- **Open a task for each support message**, in the tool your team already tracks work in, with the subject, the sender and a link back. The conversation, and your reply, stay in imado.
- **Tell your team about one sender.** Your code can check `from.address` and post a message wherever your team talks. imado itself posts nowhere but your endpoint.
- **Use it without writing a server.** Zapier and n8n can receive the call. Check the signature there too: without it, anyone who finds the URL can send you a fake event.

### The numbers

| What               | The rule                                                                                                                                                                                     |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Body               | At most 64 KB. A long subject, recipient list, attachment list or text is cut to fit, and its `_truncated` field says so.                                                                    |
| Answer             | Your server has 10 seconds to answer.                                                                                                                                                        |
| Retries            | After a `408`, a `429`, a `5xx`, or when we couldn't connect at all: 5 minutes later, then twice as long each time, up to an hour apart, for 24 hours. Never sooner than your `Retry-After`. |
| Calls              | At most 60 new messages an hour to one webhook. One more pauses it.                                                                                                                          |
| Destinations       | Each address can send its new mail to 5 places on Free and 20 with any [pack](https://www.imado.cloud/pricing), webhooks and forwards together.                                                                     |
| Waiting for a test | A webhook that hasn't answered a test with a `2xx` within 7 days of the last test is removed.                                                                                                |
| New secret         | The old and the new secret both sign every event for 24 hours, so you can switch without missing any.                                                                                        |
| History            | Every call of the last 90 days, each try and its status code, on the webhook's **Calls**. Never the sender or the subject.                                                                   |

### What to watch for

- **Answer within 10 seconds, once you have saved the event.** If imado can't connect to your server at all, it tries again. If your server accepts the connection but doesn't answer in time, the event may have arrived, so imado never sends it again. Setup shows it as **No answer, not sent again**. Save the event, answer `200`, then do the slow work.
- **Expect repeats, and events out of order.** A retry carries the same `webhook-id`, so key your rows on it. Order events by `received_at`, not by when they reach you.
- **Check the signature on the raw body**, before your framework parses the JSON, and refuse a timestamp more than five minutes away from your server's clock. Calls come from addresses that change, so a list of IP addresses to allow won't hold.
- **The endpoint must be public `https`** on the standard port. imado never calls an IP address, another port or a name inside a private network, and doesn't follow redirects. To try it from your own computer, use a tunnel that gives you a public `https` address.
- **A webhook is not a copy of the mailbox.** Mail whose spam or virus scan didn't come back clean is never sent, even if someone moves it to the Inbox. Neither is mail that arrived before the webhook answered its test, or while it was paused. The mailbox has all of it.
- **Judge the sender yourself.** Unauthenticated mail is still sent, with its SPF, DKIM and DMARC results for your code to check. `from.name` is `null` unless the sender's domain vouches for it, so a stranger can't pass as someone you know.
- **Don't send mail back to the address.** If your code sends a message to the same address the webhook listens on, that is a loop. imado pauses a webhook that gets more than 60 messages in an hour, calls it a likely loop when at least half of them had one subject, and emails the admins who read the mailbox, at most once a day for each webhook.

## Connect

Connect adds imado to an AI app as an MCP server. MCP is a common standard that AI apps such as Claude, ChatGPT, Gemini, Cursor and Claude Code use to connect to other services. You give the app one URL, `https://www.imado.cloud/api/mcp`, and it opens imado in your browser for you to sign in. There is no key to paste.

### How it works

On imado's page you tick what the app may do, and which mailboxes it may read:

- **Read mail**: list, search and read the conversations in the mailboxes you tick.
- **Write drafts and add tags**: write drafts in those mailboxes, and put the mailbox's tags on conversations. You can tick it only together with Read mail.
- **Manage your setup**: add domains, give you the DNS records, check them, and create mailboxes and addresses. You see it only if you manage a project or haven't added a domain yet.

The page also says whether imado could check where the app comes from. **Identified by claude.ai** means the app's details were published on claude.ai, so it is Claude. **Unverified** means the app described itself and imado couldn't check it. That doesn't make the app harmful, but allow it only if you started connecting it just then. You can disconnect an app at any time in **Account → Connected apps**, and it loses access straight away.

### What you can do with it

- **Catch up.** "What came in to support@ since yesterday, and which need an answer from me?" Reading in the app never marks anything as read, so the people you share the mailbox with still see what's new.
- **Find something.** "Find the invoice from Acme in my imado inbox."
- **Sort.** "Tag every refund request as Refunds." It uses the mailbox's own tags, the ones everyone sees in imado, and each tag shows the app as the one that added it. A name the mailbox doesn't have yet becomes a new tag for everyone, and the app can take tags off as well as put them on.
- **Draft the replies.** "Draft replies to the two people asking about delivery times." The drafts land in the mailbox's Drafts, marked **Drafted by Claude** (or whichever app wrote them) for everyone who reads it. You open one, check it, and press Send.
- **Set up the next address.** "Set up billing@example.com for me on imado." Every change the app makes is listed in **Account → Changes apps made**.

### The numbers

| What         | The rule                                                                                             |
| ------------ | ---------------------------------------------------------------------------------------------------- |
| Reading      | The newest 20 messages of a conversation, up to 10,000 characters each.                              |
| Drafts       | Plain text. At most 50 from one app waiting in one mailbox.                                          |
| Tags         | Up to 200 in a mailbox and 20 on a conversation, each 1 to 40 characters.                            |
| Calls        | 120 a minute, per person, across all their apps. Above that, imado answers `429` with `Retry-After`. |
| A connection | After 30 days unused, the app must sign in again. A password reset disconnects every app.            |

### What to watch for

- **What the app reads goes to the company that runs it**, such as Anthropic or OpenAI, under that company's terms. You choose which mailboxes it reads.
- **Anyone can write to you, and a message can try to steer your AI.** imado tells the app that mail is written by its senders, but an app can still be fooled. Through imado it can't send, forward or delete anything; it can write a draft that sends your information elsewhere if you press Send. Read who a draft goes to before you send it. If it reads mail from people you don't know, use imado in a chat where the app has no other tool that can send mail or post to the web.
- **It can't open attachments.** It sees a file's name and size.
- **A draft is plain text, from the mailbox's usual address**, with no files and no Bcc. The app can't change a draft once it has written it. A conversation has one reply draft: the app won't write one where someone else is already replying, or once a person has edited its draft, and it won't reply to mail in Spam.
- **One app for each job.** If an app can both read your mail and manage your setup, a message someone sends you could ask it to change your setup. imado limits such a connection: it can't add addresses to a mailbox you already have, change the address a mailbox sends from, or rename a mailbox. Still, the safest order is to connect with **Manage your setup** while you set things up, then connect again with **Read mail** only. [The Connect docs](https://www.imado.cloud/docs/agents#set-up-a-domain-then-read-its-mail) give the steps.
- **Some things stay with you**: removing anything, inviting people, spending money, a domain whose mail already arrives at another provider such as Google Workspace, and special addresses such as `postmaster@`. The app gives you a link to do them in imado.
- **A shared mailbox shows its apps.** Everyone who reads it sees which apps can read it, in **Mail → Settings**.

## Using both

The two work side by side and never call each other. Every message stays in the mailbox; a webhook gets its copy as it arrives, and the app reads it when you ask. A small shop might send `orders@` to its own records with a webhook, open a task for each message to `support@` with a second one, and start each day by asking its AI app which support conversations need an answer and to draft the replies. A person reads the drafts and sends them.

**What each one does with a new message**

- A webhook:
  - ✓ Gets new mail for one address, as text, as it arrives
  - ✗ Never gets mail that failed its spam scan, the HTML or the files
  - ✗ Cannot reply, send or change anything in imado
- The AI app you connect:
  - ✓ Reads the mailboxes you tick, when you ask
  - ✓ Tags conversations and writes drafts, if you allow it
  - ✗ Cannot open attachments
  - ✗ Cannot send
- A person who reads the mailbox:
  - ✓ Reads every message and its files
  - ✓ Checks a draft and presses Send

_A webhook and an AI app never call each other: imado keeps every message in the mailbox, and each reads it on its own._

[Webhooks](https://www.imado.cloud/docs/webhooks) and [Connect](https://www.imado.cloud/docs/agents) each have a page with the full steps, and the [fair use page](https://www.imado.cloud/fair-use) lists every limit on what you send and receive.

---

Source: https://www.imado.cloud/blog/webhooks-and-connect · Site summary: https://www.imado.cloud/llms.txt
