daimon.email
Webhooks

WebSocket (Coming Soon)

Real-time bidirectional communication

WebSocket (Coming Soon)

Info

Status: Planned for Sprint 4 (Q3 2026). WebSocket support is not yet available but represents the next evolution of real-time communication in daimon.email.

WebSocket connections will provide real-time, bidirectional communication between your agents and daimon.email, offering lower latency and more efficient resource usage than webhooks or polling.

Why WebSockets?

Lower Latency

Sub-10ms event delivery vs 100-500ms for webhooks. Perfect for conversational agents.

Bidirectional

Agents can send commands and receive events over the same connection.

Less Overhead

No HTTP handshake per event. Single persistent connection uses fewer resources.

No Public Endpoint

Agents don't need a publicly accessible webhook URL. Works behind NAT/firewalls.

Comparison: Polling vs Webhooks vs WebSockets

FeaturePollingWebhooksWebSockets
Latency5-60 seconds100-500ms<10ms
Resource usageHigh (constant API calls)LowVery low
Public endpoint requiredNoYes (HTTPS)No
ComplexityLowMediumMedium
ReliabilityHighMedium (retries)High
Best forSimple agents, low-trafficProduction agentsConversational AI, high-traffic

How WebSockets Will Work

Establish connection

Connect to the WebSocket endpoint with authentication:

import WebSocket from 'ws';

const ws = new WebSocket('wss://ws.daimon.email/v1/stream', {
  headers: {
    'Authorization': `Bearer ${inboxApiKey}`
  }
});

ws.on('open', () => {
  console.log('Connected to daimon.email WebSocket');
});

Receive events in real-time

Listen for events as they happen:

ws.on('message', (data) => {
  const event = JSON.parse(data.toString());

  if (event.type === 'message.received') {
    console.log('New message:', event.payload.message.subject);
    // Process the message immediately
  }
});

Send commands

Send commands over the same connection:

// Mark message as read
ws.send(JSON.stringify({
  action: 'mark_as_read',
  message_id: 'msg_abc123'
}));

// Send an email
ws.send(JSON.stringify({
  action: 'send_email',
  inbox_id: 'inbox_abc123',
  to: 'user@example.com',
  subject: 'Hello',
  body: 'Message from agent'
}));

Handle connection lifecycle

Implement reconnection logic for reliability:

ws.on('close', (code, reason) => {
  console.log(`WebSocket closed: ${code} ${reason}`);
  // Reconnect after 5 seconds
  setTimeout(() => connectWebSocket(), 5000);
});

ws.on('error', (error) => {
  console.error('WebSocket error:', error);
});

Planned Features

Event Streaming

Receive all webhook events via WebSocket:

ws.on('message', (data) => {
  const event = JSON.parse(data.toString());

  switch (event.type) {
    case 'message.received':
      handleNewMessage(event.payload.message);
      break;

    case 'message.bounced':
      handleBounce(event.payload);
      break;

    case 'message.complaint':
      handleComplaint(event.payload);
      break;

    case 'account.upgraded':
      handleUpgrade(event.payload);
      break;
  }
});

Command Execution

Execute API commands over WebSocket instead of HTTP:

// Send email
ws.send(JSON.stringify({
  action: 'send_email',
  inbox_id: 'inbox_abc123',
  params: {
    to: 'user@example.com',
    subject: 'Hello',
    body: 'Message from agent'
  }
}));

// Listen for response
ws.on('message', (data) => {
  const response = JSON.parse(data.toString());

  if (response.request_id === 'send_email_123') {
    console.log('Email sent:', response.result.message_id);
  }
});

Multiplexing (Multiple Inboxes)

Subscribe to events from multiple inboxes over a single WebSocket connection:

// Subscribe to multiple inboxes
ws.send(JSON.stringify({
  action: 'subscribe',
  inbox_ids: ['inbox_abc123', 'inbox_def456', 'inbox_ghi789']
}));

// Receive events from all subscribed inboxes
ws.on('message', (data) => {
  const event = JSON.parse(data.toString());

  console.log(`Event from ${event.inbox_id}: ${event.type}`);
});

Ping/Pong Heartbeats

Keep connections alive with automatic heartbeats:

// Server sends ping every 30 seconds
ws.on('ping', () => {
  ws.pong(); // Client responds with pong
});

// Client can also send pings
setInterval(() => {
  ws.ping();
}, 30000);

Backpressure Handling

Handle slow consumers gracefully:

ws.on('message', async (data) => {
  const event = JSON.parse(data.toString());

  // Pause receiving events while processing
  ws.pause();

  await processEvent(event);

  // Resume receiving events
  ws.resume();
});

Authentication

WebSocket authentication will support multiple methods:

Use inbox or account API key in the connection header:

const ws = new WebSocket('wss://ws.daimon.email/v1/stream', {
  headers: {
    'Authorization': `Bearer ${apiKey}`
  }
});

2. Query Parameter

Pass API key as query parameter (less secure, use only if headers not supported):

const ws = new WebSocket(`wss://ws.daimon.email/v1/stream?key=${apiKey}`);

3. Connection Token (Future)

Generate short-lived connection tokens for enhanced security:

curl -X POST https://api.daimon.email/v1/websocket/token \
  -H "Authorization: Bearer dm_live_inbox123..."

Response

{
  "result": {
    "token": "wst_abc123...",
    "expires_at": "2026-03-16T11:00:00Z"
  }
}
const ws = new WebSocket('wss://ws.daimon.email/v1/stream', {
  headers: {
    'Authorization': `Bearer ${connectionToken}`
  }
});

Client Libraries

Official WebSocket client libraries will be provided:

TypeScript
import { DaimonWebSocket } from 'daimon-email';

const client = new DaimonWebSocket({
  apiKey: inboxApiKey,
  autoReconnect: true,
  reconnectDelay: 5000
});

client.on('message.received', (message) => {
  console.log('New message:', message.subject);
});

client.on('connected', () => {
  console.log('WebSocket connected');
});

client.on('disconnected', (reason) => {
  console.log('WebSocket disconnected:', reason);
});

await client.connect();
Python
from daimon_email import DaimonWebSocket

client = DaimonWebSocket(
    api_key=inbox_api_key,
    auto_reconnect=True,
    reconnect_delay=5
)

@client.on('message.received')
def handle_message(message):
    print(f"New message: {message.subject}")

@client.on('connected')
def handle_connected():
    print('WebSocket connected')

@client.on('disconnected')
def handle_disconnected(reason):
    print(f"WebSocket disconnected: {reason}")

await client.connect()
Go
package main

import (
    "github.com/daimon-email/go-sdk/websocket"
)

func main() {
    client := websocket.New(websocket.Config{
        APIKey:         inboxAPIKey,
        AutoReconnect:  true,
        ReconnectDelay: 5 * time.Second,
    })

    client.OnMessageReceived(func(msg *websocket.Message) {
        fmt.Printf("New message: %s\n", msg.Subject)
    })

    client.OnConnected(func() {
        fmt.Println("WebSocket connected")
    })

    client.OnDisconnected(func(reason string) {
        fmt.Printf("WebSocket disconnected: %s\n", reason)
    })

    client.Connect()
}

Use Cases

Conversational AI Agent

Real-time email conversation handling:

const ws = new DaimonWebSocket({ apiKey: inboxApiKey });

ws.on('message.received', async (message) => {
  console.log(`New email from ${message.from}: ${message.subject}`);

  // Generate AI response
  const response = await generateResponse(message.body);

  // Send reply immediately (no HTTP round-trip)
  await ws.send({
    action: 'send_email',
    inbox_id: message.inbox_id,
    to: message.from,
    subject: `Re: ${message.subject}`,
    body: response,
    in_reply_to: message.message_id
  });

  console.log('Reply sent');
});

await ws.connect();

Latency comparison:

  • Polling: 5-60 seconds (depending on poll interval)
  • Webhooks: 100-500ms (HTTP overhead + processing)
  • WebSocket: <10ms (instant)

Multi-Agent Dashboard

Monitor multiple agents from a single connection:

const ws = new DaimonWebSocket({ apiKey: accountApiKey });

// Subscribe to all inboxes
ws.send({
  action: 'subscribe',
  inbox_ids: ['inbox_1', 'inbox_2', 'inbox_3', 'inbox_4']
});

ws.on('message.received', (message) => {
  // Update dashboard in real-time
  updateDashboard(message.inbox_id, message);
});

ws.on('message.bounced', (bounce) => {
  // Show alert for bounced emails
  showAlert(`Bounce: ${bounce.recipient}`);
});

await ws.connect();

Email Notification System

Real-time notifications for critical emails:

const ws = new DaimonWebSocket({ apiKey: inboxApiKey });

ws.on('message.received', (message) => {
  // Check if email is urgent
  if (message.subject.includes('[URGENT]') || message.labels.includes('priority')) {
    // Send push notification to operator
    sendPushNotification({
      title: 'Urgent Email',
      body: `From: ${message.from} - ${message.subject}`
    });
  }
});

await ws.connect();

Migration Path

We'll support a gradual migration from webhooks to WebSockets:

Hybrid mode (recommended for transition)

Use both webhooks and WebSockets during migration:

// Keep existing webhook for reliability
// Add WebSocket for low-latency events

const ws = new DaimonWebSocket({ apiKey: inboxApiKey });

ws.on('message.received', (message) => {
  // Fast path: process via WebSocket
  processMessage(message);
});

// Webhook still processes events if WebSocket is down
app.post('/webhook', (req, res) => {
  const event = req.body;

  // Check if already processed via WebSocket
  if (!isProcessed(event.event_id)) {
    processMessage(event.message);
  }

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

WebSocket-only mode

Once stable, disable webhooks and use WebSocket exclusively:

const ws = new DaimonWebSocket({
  apiKey: inboxApiKey,
  autoReconnect: true,
  reconnectDelay: 5000
});

ws.on('message.received', async (message) => {
  await processMessage(message);
});

await ws.connect();

Frequently Asked Questions

When will WebSockets be available?

Sprint 4 (Q3 2026). We'll announce the exact release date via email and status.daimon.email.

Will webhooks still be supported?

Yes. Webhooks will remain fully supported. WebSockets are an additional option, not a replacement.

Can I use both webhooks and WebSockets?

Yes. You can use both simultaneously during migration or for redundancy.

What happens if my WebSocket disconnects?
  • Auto-reconnect: Client libraries will automatically reconnect
  • Event replay: On reconnect, you'll receive missed events (up to 5 minutes)
  • Fallback: Use webhooks as a backup delivery mechanism
Are WebSockets available on all tiers?

Yes. WebSockets will be available on all tiers (free, developer, growth, enterprise).

How many WebSocket connections can I have?
  • Free tier: 1 connection
  • Developer tier: 10 connections
  • Growth tier: 100 connections
  • Enterprise tier: Unlimited
Can agents behind NAT/firewalls use WebSockets?

Yes. WebSockets work behind NAT/firewalls because the agent initiates the outbound connection. No public endpoint required.

Get Notified

Want to be notified when WebSocket support launches?

Join the Waitlist

Sign up for early access and beta testing opportunities

Next Steps