Subscribe
Send asubscribe message to start receiving events. You can filter by inbox, event type, or both.
Subscribe to all inboxes and all events
Subscribe to specific inboxes
Subscribe to specific event types
subscribed confirmation that echoes back your active subscriptions:
inbox_ids is empty in the response, you are subscribed to all inboxes on your account. When event_types is empty, you receive all event types. Otherwise, the arrays list your specific filters.
Subscriptions accumulate — sending multiple subscribe messages adds to your existing subscriptions.
When subscribing to specific
inbox_ids, OpenMail verifies you own each inbox. Unowned inbox IDs return an error.Unsubscribe
Remove subscriptions without disconnecting.Unsubscribe from specific inboxes
Unsubscribe from everything
subscribe message.
Event replay with last_event_id
If your client disconnects and reconnects, pass last_event_id in the subscribe message to resume from where you left off:
Track the
event_id of each event you process. On reconnect, pass the last one you successfully handled. If the ID is not found or doesn’t belong to your account, you’ll receive an error.Receiving events
Events arrive as JSON messages on the WebSocket. The payload is identical to the webhook event payload.Ping / pong
Send an application-levelping to check the connection is alive:
Message reference
Client → Server
| Message | Fields | Description |
|---|---|---|
subscribe | inbox_ids?, event_types?, last_event_id? | Subscribe to events. Omit filters to get all events for all inboxes. Pass last_event_id to replay missed events. |
unsubscribe | inbox_ids? | Remove subscriptions. Empty = unsubscribe from all. |
ping | Application-level keepalive. |
Server → Client
| Message | Fields | Description |
|---|---|---|
subscribed | inbox_ids, event_types | Subscription confirmed. Empty arrays = all inboxes / all event types. |
unsubscribed | inbox_ids | Unsubscription confirmed. |
error | message | Error details (invalid JSON, unknown type, unauthorized inbox, rate limit, revoked key). |
pong | Response to ping. | |
| (event) | Same as webhook payload | Email event pushed in real-time. |
Connection management
Heartbeat
The server sends WebSocket protocol-level pings every 30 seconds. Connections that don’t respond within 10 seconds are terminated.Reconnection
Implement exponential backoff on the client. Start at 1 second, cap at 30 seconds. Reset the counter on successful connection. Uselast_event_id to resume without data loss.
The Python websockets library handles reconnection automatically with async for ws in connect(...).
Connection limits
You can open up to 10 WebSocket connections per account. Events are delivered to all connections whose subscriptions match. Exceeding the limit returns an error and closes the new connection.Rate limiting
Each connection is limited to 30 messages per 10-second window. Exceeding the limit closes the connection with an error.Re-authentication
The server periodically verifies your API key is still valid. If your key is revoked or rotated, existing connections are closed with an error.Error codes
| Close code | Meaning |
|---|---|
1001 | Server shutting down (reconnect) |
4001 | Unauthorized (invalid or revoked API key) |
4008 | Connection limit exceeded |
4029 | Rate limit exceeded |