---
title: "WebSocket Notifications"
method: GET
path: "/v1/ws"
tags: ["WebSockets"]
---

# WebSocket Notifications

`GET /v1/ws`

## Request

- Base URL: `https://api.forwardemail.net`
- URL: `https://api.forwardemail.net/v1/ws`
- Auth: one of:
  - HTTP basic
  - HTTP basic
  - none

Connect to the WebSocket endpoint for real-time push notifications.

**Connection URL:** `wss://api.forwardemail.net/v1/ws`

**Authentication (Optional):**
- **Authenticated Clients:** Provide credentials via `Authorization` header to receive both per-alias events (IMAP, CalDAV, CardDAV) and global broadcast events (`newRelease`).
- **Unauthenticated Clients:** Connect without credentials to receive only global broadcast events (`newRelease`). This is useful for clients that only need to be notified of app updates.

**Authentication Methods:**

Authentication **must** be provided via the `Authorization` header using HTTP Basic Authentication, or from a browser in the first message after connecting (Option 3). Query parameters that carry credentials are **NOT supported**.

**Option 1: Alias Password Authentication (Recommended)**

Use your alias email address and generated password:

```javascript
const ws = new WebSocket("wss://api.forwardemail.net/v1/ws", {
  headers: {
    Authorization: `Basic ${btoa("user@domain.com:alias-password")}`
  }
});
```

**Option 2: API Token Authentication**

Use your API token (requires `?alias_id=` query parameter):

```javascript
const ws = new WebSocket("wss://api.forwardemail.net/v1/ws?alias_id=YOUR_ALIAS_ID", {
  headers: {
    Authorization: `Basic ${btoa("YOUR_API_TOKEN:")}` // Note: password is empty
  }
});
```

**Option 3: First Message (Browsers)**

Browsers cannot set headers on a WebSocket handshake. Connect with `?auth=message` and send the credentials as the first message within 5 seconds. Nothing is sent until they are accepted; otherwise the connection is closed with `4400` (malformed message), `4401` (wrong credentials) or `4403` (not allowed). For an API token, send it as `username` with an empty `password` and an `alias_id`:

```javascript
const ws = new WebSocket("wss://api.forwardemail.net/v1/ws?auth=message");
ws.onopen = () => ws.send(JSON.stringify({
  event: "auth",
  username: "user@domain.com",
  password: "alias-password"
}));
```

**Option 4: Unauthenticated (Broadcast-Only)**

Connect without authentication to receive only global broadcast events:

```javascript
const ws = new WebSocket("wss://api.forwardemail.net/v1/ws");
```

**Connection Responses:**

Upon successful connection, the server sends a `connected` event:

- **Authenticated:** `{"event":"connected","aliasId":"<your-alias-id>"}`
- **Unauthenticated:** `{"event":"connected","broadcastOnly":true}`

If you receive `broadcastOnly: true`, no credentials were provided, and you will only receive global broadcast events.

**msgpackr Encoding:** By default, messages are sent as JSON text frames. Pass `?msgpackr=true` to receive binary msgpackr-encoded frames for reduced bandwidth.

**Behavior:**
- Read-only channel: client messages are silently discarded
- Server sends a `connected` event upon successful connection
- Server sends periodic `ping` frames; client must respond with `pong`
- Per-IP rate limit: 30 connections/minute
- Per-alias connection limit (authenticated): 10 concurrent connections
- Per-IP unauthenticated connection limit: 3 concurrent connections
- Global connection limit: 10,000

**Event Payloads:** Each event is one flat object with `event` (the type), `timestamp`, `notificationId` and the fields of that event. `newMessage`, `newRelease` and the CalDAV and CardDAV events carry a resource object (`message`, `release`, `calendar`, `calendarEvent`, `contact`, or `addressBook`) that mirrors the REST API response. The other IMAP events name the mailbox and the UIDs that changed.

**Per-Alias Events (Authenticated Only):**
- **IMAP:** `newMessage`, `messagesMoved`, `messagesCopied`, `flagsUpdated`, `labelsUpdated`, `messagesExpunged`, `mailboxCreated`, `mailboxDeleted`, `mailboxRenamed`
- **CalDAV:** `calendarCreated`, `calendarUpdated`, `calendarDeleted`, `calendarEventCreated`, `calendarEventUpdated`, `calendarEventDeleted`
- **CardDAV:** `contactCreated`, `contactUpdated`, `contactDeleted`, `addressBookCreated`, `addressBookUpdated`, `addressBookDeleted`

**Broadcast Events (All Clients):**
- `newRelease` — Broadcast when a new version of the Forward Email Mail App (https://github.com/forwardemail/mail.forwardemail.net) is published on GitHub. The server polls GitHub every 15 minutes and uses a content-based fingerprint to detect changes. **Asset Gating**: When a new release is detected but has no assets yet, the broadcast is deferred until assets appear.

**Important Notes:**
- Query parameters `?token=`, `?username=`, `?password=` are **NOT supported** for authentication
- Authentication **must** be via `Authorization` header using HTTP Basic Authentication, or the first message of a `?auth=message` connection
- If credentials are supplied and fail, the handshake is refused with `401 Unauthorized` (a `?auth=message` connection is closed with `4401`); only connections without any credentials receive `broadcastOnly: true`
- If the alias password or API token changes (or the account is banned), open connections are closed with code `4001`; reconnect with the new credentials
- For API token authentication, the `?alias_id=` query parameter is **required**

## Query parameters

- `alias_id` string
- `msgpackr` 'true' | 'false'
- `auth` 'message'

## Other responses

- `101`: WebSocket connection established. Events are streamed as messages.
- `400`: Bad Request - Missing or invalid authentication parameters
- `401`: Unauthorized - Invalid API token or alias credentials. Note: authentication is optional; this error only occurs when credentials are provided but are invalid.
- `404`: Not Found - Alias not found for the provided credentials
- `429`: Too Many Requests - Rate limit exceeded (30 connections/minute per IP)
- `503`: Service Unavailable - Global connection limit reached

---

[API](https://skmtc.dev/forwardemail/apis/forward-email-api.md) · [All operations](https://skmtc.dev/forwardemail/apis/forward-email-api/llms.txt) · [OpenAPI document](https://skmtc.dev/forwardemail/apis/forward-email-api/revisions/ecefab4527f6?raw)
