Receive & reply

Set up inbound email handling with webhooks, SSE streaming, or polling, and send automatic replies.

1. Create a webhook

curl
curl -X POST https://api.robotomail.com/v1/webhooks \
  -H "Authorization: Bearer $ROBOTOMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/email",
    "events": ["message.received"]
  }'

2. Handle the webhook

When an email arrives, Robotomail sends a POST request to your endpoint with the message data. Verify the signature before processing:

node.js
import crypto from "crypto";

app.post("/webhooks/email", (req, res) => {
  // The signature is computed over the raw request body string, not parsed JSON
  const rawBody = req.body; // use express.raw() or express.text() middleware
  const signature = req.headers["x-robotomail-signature"];
  const expected = crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(rawBody)
    .digest("hex");

  if (signature !== expected) return res.status(401).send("Invalid signature");

  const { event, timestamp, data } = JSON.parse(rawBody);

  if (data.over_limit) {
    // Account is over its monthly inbound cap. The payload omits body and
    // attachments — only identity fields are present. The message is safely
    // persisted; upgrading or the first-of-month reset unlocks it.
    console.log(`[over-limit] message_id=${data.message_id} mailbox=${data.mailbox_id}`);
    return res.status(200).send("OK");
  }

  console.log(`[${event}] from ${data.from}: ${data.subject} at ${timestamp}`);

  res.status(200).send("OK");
});

See 402 INBOUND_LIMIT_EXCEEDED for the full over-limit behavior across webhooks, SSE, and the REST API.

3. Send a reply

Reply to the inbound message by passing its messageId (the RFC 5322 Message-ID header value) in the inReplyTo field:

curl
curl -X POST https://api.robotomail.com/v1/mailboxes/MAILBOX_ID/messages \
  -H "Authorization: Bearer $ROBOTOMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["sender@example.com"],
    "subject": "Re: Their subject",
    "bodyText": "Thanks for your email! Here is my reply.",
    "inReplyTo": "<original-message-id@example.com>"
  }'

This automatically threads the reply with the original message.

Alternative: Polling or SSE

If you can't set up a webhook endpoint, you have two alternatives:

SSE streaming: Open a persistent connection to GET /v1/events for real-time events without a public URL. Use robotomail listen from the CLI, or connect directly. See the Events (SSE) API.

Polling: Poll for new messages using the since parameter:

curl
curl "https://api.robotomail.com/v1/mailboxes/MAILBOX_ID/messages?direction=INBOUND&since=2026-03-11T00:00:00Z" \
  -H "Authorization: Bearer $ROBOTOMAIL_API_KEY"