Skip to main content
Platforms like lobster.works can use openmail to provide email capabilities to their users. This guide walks through the integration flow.

Overview

As an integration platform, you will:
  1. Create inboxes for your users when they enable email
  2. Receive inbound emails via webhooks when messages arrive
  3. Send emails on behalf of users via the API
  4. Map inboxes to your users using externalId

Authentication

Use your API key: Authorization: Bearer om_live_...

Base URL

https://api.openmail.sh

Step 1: Create inboxes for users

When a user enables email in your app, create an inbox and store the mapping:
curl -X POST https://api.openmail.sh/v1/inboxes \
  -H "Authorization: Bearer om_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "user_abc123",
    "username": "support"
  }'
externalId is your user/workspace ID. Use it to map inbound webhooks back to the right context. username is optional — we’ll generate one (e.g. a1b2c3d4) if omitted.
Response:
{
  "id": "inb_92ma...",
  "address": "support@yourdomain.openmail.sh",
  "externalId": "user_abc123",
  "createdAt": "2024-03-21T10:00:00.000Z"
}
Store id and address in your database. The user can now receive email at address.

Step 2: Configure webhooks

During onboarding, you provide a webhook URL and webhook secret. openmail sends message.received events when inbound email arrives.
Your webhook endpoint must respond with 200 within 15 seconds. We retry failed deliveries up to 5 times with exponential backoff.

Webhook payload

{
  "event": "message.received",
  "event_id": "evt_abc123",
  "occurred_at": "2024-03-21T10:05:00.000Z",
  "delivered_at": "2024-03-21T10:05:01.000Z",
  "attempt": 1,
  "inbox_id": "inb_92ma...",
  "external_id": "user_abc123",
  "thread_id": "thr_xyz...",
  "message": {
    "id": "msg_...",
    "rfc_message_id": "<original@message.id>",
    "from": "customer@example.com",
    "to": "support@yourdomain.openmail.sh",
    "cc": [],
    "subject": "Help with my order",
    "body_text": "Hi, I need help...",
    "attachments": [
      {
        "filename": "invoice.pdf",
        "contentType": "application/pdf",
        "sizeBytes": 12345,
        "url": "https://api.openmail.sh/v1/attachments/msg_.../invoice.pdf"
      }
    ],
    "received_at": "2024-03-21T10:05:00.000Z"
  }
}
Use external_id to look up the user in your system. Attachment URLs are signed and expire; fetch them promptly.

Verify webhook signatures

Always verify the X-Signature header to ensure the request came from openmail:
const crypto = require('crypto');

function verifyWebhook(payload, timestamp, signature, secret) {
  const signed = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${payload}`)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(signed, 'hex'));
}

// In your webhook handler:
app.post('/webhooks/openmail', (req, res) => {
  const payload = JSON.stringify(req.body);
  const timestamp = req.headers['x-timestamp'];
  const signature = req.headers['x-signature'];

  if (!verifyWebhook(payload, timestamp, signature, process.env.OPENMAIL_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const { event, external_id, message } = req.body;
  if (event === 'message.received') {
    // Handle inbound email for user external_id
  }
  res.status(200).send('OK');
});

Step 3: Send email on behalf of users

Use the send endpoint with the inbox ID. Include an Idempotency-Key header (e.g. UUID) to avoid duplicate sends on retries:
curl -X POST https://api.openmail.sh/v1/inboxes/inb_92ma.../send \
  -H "Authorization: Bearer om_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "to": "customer@example.com",
    "subject": "Re: Help with my order",
    "body": "Thanks for reaching out. We are looking into it.",
    "threadId": "thr_xyz..."
  }'
Use threadId when replying so the conversation stays threaded. Get it from the webhook payload or from GET /v1/inboxes/:id/threads.

Step 4: List messages and threads

Fetch messages and threads for an inbox:
# List messages (optionally filter by direction)
curl "https://api.openmail.sh/v1/inboxes/inb_92ma.../messages?direction=inbound&limit=20" \
  -H "Authorization: Bearer om_live_YOUR_API_KEY"

# List threads
curl "https://api.openmail.sh/v1/inboxes/inb_92ma.../threads?limit=20" \
  -H "Authorization: Bearer om_live_YOUR_API_KEY"

# Get messages in a thread
curl "https://api.openmail.sh/v1/threads/thr_xyz.../messages" \
  -H "Authorization: Bearer om_live_YOUR_API_KEY"

Rate limits

ResourceLimit
Inbox creation100 per day
Send (per inbox)10 per minute, 200 per day
Cold outreachPer-recipient limits apply

Next steps