Skip to main content
For developers building AI agents with OpenClaw, LangChain, n8n, Make, Vercel AI SDK, or any agent framework. This guide uses OpenClaw as the example—the same pattern (create inbox, inject env vars, route inbound by inbox_id) works with other frameworks.

Prerequisites

Use this pre-built prompt to get started faster.

CursorOpen in Cursor

Step 1: Create an inbox

One API call. Create an inbox and map inbox_id to your user/container in your app for routing.
const fs = require("fs/promises");

const OPENMAIL_API_KEY = process.env.OPENMAIL_API_KEY;

async function createAgentInbox(userId, containerEnvPath) {
  const response = await fetch("https://api.openmail.sh/v1/inboxes", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${OPENMAIL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ mailboxName: userId }),
  });

  if (!response.ok) throw new Error(`OpenMail: ${response.status}`);

  const inbox = await response.json();
  // inbox.id      → "inb_8f3a1b2c"
  // inbox.address → "jane@openmail.sh"

  await fs.appendFile(
    containerEnvPath,
    [
      `OPENMAIL_API_KEY=${OPENMAIL_API_KEY}`,
      `OPENMAIL_INBOX_ID=${inbox.id}`,
      `OPENMAIL_ADDRESS=${inbox.address}`,
    ].join("\n") + "\n"
  );

  return inbox;
}

Step 2: Write env vars into the container

Three variables per container. The API key is shared across all agents; the inbox ID and address are unique.
OPENMAIL_API_KEY=om_...
OPENMAIL_INBOX_ID=inb_8f3a1b2c
OPENMAIL_ADDRESS=jane@openmail.sh
For OpenClaw, set these in ~/.openclaw/.env or in ~/.openclaw/openclaw.json under skills.entries.openmail.env. For other frameworks, inject them into your agent’s environment (e.g. LangChain tool config, n8n node credentials).

Step 3: Add the skill file

This file teaches the agent how to send and receive email. OpenClaw loads it into the LLM’s system prompt; other frameworks use similar patterns (system prompts, tool descriptions). The agent calls the API via curl—no CLI binary needed. For OpenClaw, place at ~/.openclaw/skills/openmail/SKILL.md or pre-bake into your Docker image. For other frameworks, adapt the path—the skill content is the same.
SKILL.md
---
name: openmail
description: Send and receive email via OpenMail
requires:
  env:
    - OPENMAIL_API_KEY
    - OPENMAIL_INBOX_ID
    - OPENMAIL_ADDRESS
---

# OpenMail

Your email address is $OPENMAIL_ADDRESS. Use it when introducing yourself or sharing contact info.

## Send an email

```bash
curl -s -X POST "https://api.openmail.sh/v1/inboxes/$OPENMAIL_INBOX_ID/send" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "to": "recipient@example.com",
    "subject": "Subject",
    "body": "Message body"
  }'
```

Save the `threadId` from the response to reply in the same thread later.

## Reply in a thread

```bash
curl -s -X POST "https://api.openmail.sh/v1/inboxes/$OPENMAIL_INBOX_ID/send" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "to": "recipient@example.com",
    "subject": "Re: Original subject",
    "body": "Reply body",
    "threadId": "thr_..."
  }'
```

## Check for new messages

```bash
curl -s "https://api.openmail.sh/v1/inboxes/$OPENMAIL_INBOX_ID/messages?direction=inbound&limit=10" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"
```

## List threads

```bash
curl -s "https://api.openmail.sh/v1/inboxes/$OPENMAIL_INBOX_ID/threads?limit=10" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"
```

## Read a thread

```bash
curl -s "https://api.openmail.sh/v1/threads/{thread_id}/messages" \
  -H "Authorization: Bearer $OPENMAIL_API_KEY"
```

## Notes

- Always include `Idempotency-Key` when sending (prevents duplicates on retry)
- Use `threadId` when replying so the email threads correctly in the recipient's client
- `$OPENMAIL_*` variables are read from the container environment at runtime
Pre-bake into Docker - the skill file is identical for every agent. Only the env vars differ per container. For OpenClaw: COPY skills/openmail/SKILL.md /root/.openclaw/skills/openmail/SKILL.md

Step 4: Handle inbound email

Choose your delivery method. WebSockets are recommended for agents - no public URL needed, instant delivery. Webhooks work for traditional server-to-server integrations. The event payload is identical for both methods:
Event payload
{
  "event": "message.received",
  "event_id": "evt_7f2a3b4c",
  "inbox_id": "inb_8f3a1b2c",
  "thread_id": "thr_9d4e5f6a",
  "message": {
    "id": "msg_4c8d5e6f",
    "from": "customer@example.com",
    "to": "jane@openmail.sh",
    "subject": "Re: Your order",
    "body_text": "Thanks for following up...",
    "attachments": [],
    "received_at": "2026-02-24T10:05:00.000Z"
  }
}

Verify the integration

  1. Create inbox - confirm OPENMAIL_INBOX_ID and OPENMAIL_ADDRESS appear in the container’s env
  2. Send - tell the agent “send an email to your-test@email.com” - confirm it arrives
  3. Inbound - reply to that email; confirm the event arrives over your WebSocket connection (or webhook) and routes to the container
  4. Thread - tell the agent “reply to the last email” - confirm the reply threads correctly in the recipient’s client

Reference

WhatWhereWhen
Skill file (SKILL.md)Agent’s skills/config dirPre-baked in Docker or mounted at runtime
OPENMAIL_API_KEYAgent envSet once from your secrets
OPENMAIL_INBOX_IDAgent envWritten when you create the inbox
OPENMAIL_ADDRESSAgent envWritten when you create the inbox
WebSocket client or Webhook handlerYour backendConnect to wss://api.openmail.sh/v1/ws or configure webhook URL in dashboard