> For the complete documentation index, see [llms.txt](https://docs.openalgo.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openalgo.in/change-log/release/version-2.0.1.1-released.md).

# Version 2.0.1.1 Released

**Date: 17th May 2026**

**Major Feature Release: WhatsApp Bot Integration — Event-Driven Alerts + Slash-Command Queries, Plus a WebSocket Reliability Sweep Across 14 Brokers, New Broker Integrations (IIFLCapital Streaming, Groww Option Chain + WS Depth, Upstox GLOBAL\_INDEX), and Per-Install Fernet Salt Rotation with Crash-Safe Auto-Migration**

This release spans **70+ commits** since v2.0.1.0. The headline change is **WhatsApp** — a self-hosted, event-driven WhatsApp bot that fires order alerts on the same event bus that drives Telegram, accepts slash-command queries (`/orderbook`, `/positions`, `/quote`, …) from the operator's own phone, and exposes a single send endpoint over REST. Pairing happens once from the OpenAlgo admin UI with a QR scan; the encrypted session blob is then stored in `openalgo.db` and the bot auto-reconnects on every server boot. Alongside WhatsApp, this release lands a WebSocket reliability sweep — subscribe batching across 6+ brokers, reconnect hardening across 4+ brokers, file-descriptor leak fixes in two streaming layers, and proxy-level fixes (ZMQ bind, mode normalization, request\_id correlation). Three new broker integrations land: IIFLCapital streaming, Groww option chain + WS depth, and Upstox GLOBAL\_INDEX world feeds. Security: a per-install random `FERNET_SALT` now feeds the Fernet KDF, with a crash-safe online migration of existing ciphertext.

***

**Highlights**

* **WhatsApp Bot — event-driven alerts + slash-command queries** — Brand-new `/whatsapp` admin page with auto-rotating QR pair flow, a single trader-facing `POST /api/v1/whatsapp/notify` endpoint that accepts text + image + document attachments, a dedicated worker thread that satisfies wars's PyO3 unsendable contract, and a `subscribers/whatsapp_subscriber` that wires every order topic on the existing event bus so order/position/batch events fire WhatsApp messages in parallel with Telegram. Single-user gate via WhatsApp's own `is_from_me=True` mark — random contacts who message the operator's number cannot drive the bot.
* **`client.whatsapp()` in the openalgo Python SDK (1.0.50)** — One unified call for every common case: send to self, to a single E.164 number, to up to 5 numbers (ToS-safety cap), with text, image, or document payloads. `wait_for_delivery=True` by default so the response carries a real per-recipient delivery report.
* **WebSocket reliability sweep across 14 brokers** — Subscribe batching for Kotak (HSI multi-scrip frames + 50ms debounce), AliceBlue, Nubra, Shoonya, Angel, Flattrade. Reconnect hardening for Dhan (auto-resubscribe + data-stall watchdog), Dhan-Sandbox (eventlet-safe asyncio + single-loop reconnect), Upstox (stall-vs-network reconnect logging), Fyers TBT (batch queue + pong validation + exponential backoff + health check). Cold-subscribe latency cut \~5× on Shoonya; Zerodha lost a \~4s sleep floor.
* **WebSocket-proxy + client fixes** — Bind ZMQ publisher to `ZMQ_HOST` instead of all interfaces (#1378), normalize subscribe/unsubscribe mode case-insensitively (#1375), correlate ack via request\_id (#1376), route cache invalidation through `SharedZmqPublisher` to eliminate the PUB→PUB topology (#1374).
* **Three new broker integrations** — **IIFLCapital streaming** (full WS adapter; file-descriptor leaks closed across reconnect cycles, #1416 + #1430), **Groww** (full option chain + WS depth, expiry filter for expired contracts, broker-symbol mangling fix, #1392), **Upstox GLOBAL\_INDEX** (US30 / JAPAN225 / HANGSENG world feeds via the existing Upstox WS adapter).
* **Per-install random Fernet salt** — `FERNET_SALT` env var is now provisioned per install (32-byte hex, generated by `utils/env_check.py`) and feeds the Fernet KDF in `database/auth_db.py`. Crash-safe online migration moves existing ciphertext from the legacy static salt to the new one; if the process dies mid-migration the next boot resumes from the persisted state. Tightens broker-auth-token confidentiality and is the same domain-separated salt the new WhatsApp session blob uses.
* **Platform version bump** — `2.0.1.0` → `2.0.1.1`. SDK pin (`openalgo`) `1.0.49` → `1.0.50`.

***

**WhatsApp Bot — feature deep dive**

WhatsApp brings parity with Telegram for both outbound alerts and interactive command queries, with security choices tuned for the single-user-per-deployment model OpenAlgo runs under.

**Architecture in one sentence:** the wars (PyO3 over whatsapp-rust) library hosts a fully linked WhatsApp Web device inside the Flask process; outgoing alerts flow event-bus → `whatsapp_subscriber` → `WhatsAppBotThread` → `wars.send()`; incoming slash-commands flow `wars.on_message` → `is_from_me=True` gate → command dispatcher → OpenAlgo SDK call → reply via the same bot thread.

**Pairing (admin only)** — `c44a420b`:

* `POST /whatsapp/pair` (session-cookie auth) spawns a temp-DB wars instance, registers an `on_qr` callback that streams `whatsapp_qr` SocketIO events with a `data:image/png` URL, and waits on `wait_until_ready(timeout=300)` for the phone-side scan
* QR refreshes \~every 30 seconds; React `/whatsapp` page swaps the `<img>` source on each `whatsapp_qr` event without polling
* On pair success: `export_session()` → Fernet-encrypted → persisted to `whatsapp_config.session_blob` in `openalgo.db` → temp file unlinked
* Pair-code path (`POST /whatsapp/pair` with `phone` parameter) for users who prefer not to scan a QR

**Encryption at rest** — `database/whatsapp_db.py`:

* Fernet key derived via PBKDF2-SHA256(`API_KEY_PEPPER`, `FERNET_SALT + b":whatsapp-session"`, 100k iters), 32-byte output, base64-urlsafe encoded
* Domain separator (`:whatsapp-session`) means the same `(PEPPER, FERNET_SALT)` pair derives **different** Fernet keys for broker auth tokens, Telegram bot tokens, and WhatsApp session blob — compromising one channel's ciphertext gives no leverage against the others
* Idempotent SQLite `ALTER TABLE ADD COLUMN` migration runs at every init so existing installs pick up the `owner_user_id` / `owner_username` columns without manual schema work

**The unsendable PyO3 trap** — `c44a420b`:

* `wars.WhatsApp` is `#[pyclass(unsendable)]` — every method call panics if invoked from a thread other than its creator
* Solution: a dedicated `WhatsAppBotThread` owns the wars instance for its lifetime; request threads enqueue `(op, args, result_holder, event)` on a `queue.Queue` and wait on a `threading.Event` for the worker to dispatch `wars.send()`
* Re-entrant: command handlers (which wars dispatches on the bot thread itself) bypass the queue via a `threading.get_ident() == self._bot_thread_id` check so they don't deadlock on themselves
* Same shape Telegram uses for python-telegram-bot, for the same reason

**REST surface — intentionally narrow** — `restx_api/whatsapp_bot.py`:

* `POST /api/v1/whatsapp/notify` is the **only** public endpoint
* Pairing, start/stop, config, users, broadcast, stats, preferences live behind the session-authed `/whatsapp/*` blueprint — admin only
* A leaked API key cannot re-pair the device, enumerate linked recipients, change rate limits, or fan out to the operator's contact list
* Hard precheck — every send path refuses with `409 "WhatsApp is not paired or not connected. Pair the device first from the /whatsapp page in OpenAlgo before sending."` if `is_ready()` is false; we explicitly do not queue when unpaired

**Send paths — one unified call**:

* `client.whatsapp("Build #482 deployed")` → wars's single-arg `send("text")` form, routes to the paired device's own number (no need to know own JID)
* `client.whatsapp("hi", to="919876543210")` → single recipient
* `client.whatsapp("alert", to=[...])` → broadcast (capped at 5 server-side — anything beyond is dropped; ToS-safety guardrail)
* `client.whatsapp("EOD chart", to="919...", image="/srv/charts/nifty.png", caption="...")` → image with caption
* `client.whatsapp("report", username="alice", document="/srv/reports/eod.pdf", filename="EOD.pdf")` → document
* Attachment paths validated against `WHATSAPP_ATTACHMENT_ROOTS` allowlist (default: `<openalgo>/db/attachments/`); paths with `..`, paths under `/etc /proc /sys /root /var/log /C:\Windows`, or paths that resolve outside the allowlist are rejected with `400 image_path is not allowed`

**Inbound commands** — `services/whatsapp_bot_service.py`:

| Command                    | Maps to                                   |
| -------------------------- | ----------------------------------------- |
| `/help`, `/menu`, `/start` | Command list                              |
| `/status`                  | Bot connection + paired status            |
| `/orderbook`               | `client.orderbook()`                      |
| `/tradebook`               | `client.tradebook()`                      |
| `/positions`               | `client.positionbook()`                   |
| `/holdings`                | `client.holdings()`                       |
| `/funds`                   | `client.funds()`                          |
| `/pnl`                     | `client.pnl()` or `client.positionbook()` |
| `/quote SYM [EXCH]`        | `client.quotes()`                         |
| `/closeall`                | `client.closeposition()`                  |
| `/mode`                    | live or analyze                           |

Auth: the bot only responds when `is_from_me=True` (WhatsApp's multi-device protocol marks messages mirrored from the operator's primary phone with this flag). Random contacts who message the operator's WhatsApp number arrive with `is_from_me=False` and are silently ignored. The OpenAlgo SDK calls run with the operator's API key, looked up from `auth_db` by the `owner_username` captured at pair time — there is no `/link` flow because there is no second user to authorize.

**Auto-reconnect on app boot** — `app.py:_autostart_whatsapp_bot`:

* Background thread spawned during `_init_databases_and_schedulers` (after `db_ready.set()`)
* Loads the encrypted session blob, calls `wars.WhatsApp.from_bytes(blob)`, starts the worker thread, registers handlers
* No QR scan on restart — `is_ready()` flips to true within \~1s of boot
* If wars isn't installed (fresh checkout that hasn't `uv sync`'d), the autostart logs a warning and degrades gracefully — the rest of the Flask app boots normally

**Frontend** — `frontend/src/pages/whatsapp/WhatsAppIndex.tsx`:

* Single-page React UI: Status card with Pair QR + Disconnect button, "Send a one-off message" card, no Linked-Users table (single-user app)
* SocketIO subscriptions for `whatsapp_qr` (auto-rotates the QR image), `whatsapp_pair_code`, `whatsapp_paired`, `whatsapp_pair_status`, `whatsapp_status`
* New `MessageCircle` icon in the profile dropdown so WhatsApp visually differs from Telegram's `MessageSquare`

**RUST\_LOG quieting** — `services/whatsapp_bot_service.py`:

* Three known-noisy targets silenced at module import (before any `import wars`): `wacore::send` (stale-device warnings), `whatsapp_rust::message` (PN→LID migration chatter), `wacore_libsignal::protocol::session_cipher` (no-current-session errors that the upper layer already handles)
* `os.environ.setdefault("RUST_LOG", ...)` — operator can still override via shell or `.env` for diagnostics

**openalgo Python SDK 1.0.50** — released to PyPI alongside this version:

* New `WhatsAppAPI` mix-in adds `client.whatsapp(...)` with the four recipient forms and image/document payloads
* Mirrors the `client.telegram()` ergonomics for traders already familiar with the SDK
* Available at <https://pypi.org/project/openalgo/1.0.50/>

***

**WebSocket reliability sweep — 14 brokers touched**

| Broker           | Change                                                                                                                                                         | Commit                                             |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| **IIFLCapital**  | Full websocket adapter integrated + file-descriptor leaks closed across reconnect cycles                                                                       | `0ad69cf3` (#1416), `15179371` (#1430)             |
| **Paytm**        | NSE\_INDEX/BSE\_INDEX symbol normalization + fd-leak fixes in streaming layer + batch ws subscribe + graceful empty for option chain / OI tracker / historical | `8dba1ea3` (#1413)                                 |
| **Kotak**        | Batch subscribe via HSI multi-scrip frames + cut batch debounce 500ms → 50ms + log emitted scrips                                                              | `8fef2a57` (#1399)                                 |
| **Groww**        | Full option chain + websocket depth integration + drop expired expiries + stop mangling broker symbols                                                         | `440b78ef` (#1392)                                 |
| **AliceBlue**    | Batch ws subscriptions like Zerodha + event-driven connect + leading-edge subscribe debounce                                                                   | `09667a6e` (#1389)                                 |
| **Dhan-Sandbox** | Eventlet-safe asyncio + heartbeat align + single-loop reconnect + batch queue                                                                                  | `b5675653` (#1344)                                 |
| **Nubra**        | Coalesce per-symbol subscribes into batched SDK calls                                                                                                          | `6473aa2e` (#1366)                                 |
| **Shoonya**      | Batch queue + auth-fail short-circuit + env-var tuning + interruptible sleeps; cold-subscribe latency cut \~5× via leading-edge debounce                       | `4b8578d6` (#1381)                                 |
| **Dhan**         | Auto-resubscribe on reconnect + data-stall watchdog                                                                                                            | `d214a598` (#1372)                                 |
| **Upstox**       | Distinguish stall-triggered reconnects from network-induced ones in logs                                                                                       | `42927546` (#1357)                                 |
| **Angel**        | Subscribe batch-queue to coalesce per-symbol bursts + defensive `.get()` in place\_order response handling                                                     | `790cc64d` (#1352), `a4bdac18` (#846)              |
| **Zerodha**      | Remove \~4s sleep floor from subscribe path + add auth-fail short-circuit + interruptible sleeps + wire MCX\_INDEX through quote/history/depth/ws              | `659d53ab`, `f21f40cc` (#1371), `cd4095eb` (#1385) |
| **Fyers**        | Harden TBT client with batch queue, pong validation, exponential backoff, and health check                                                                     | `463a3004` (#1361)                                 |
| **Flattrade**    | Batch-queue subscriptions like Zerodha adapter                                                                                                                 | `ed37dbc2` (#1341)                                 |
| **Kotak**        | Align place/modify order payload with official Neo spec                                                                                                        | `b06ef4a8` (#1398)                                 |

**WebSocket-proxy + client layer:**

* `dd9cb64c` (#1378) — `fix(websocket_proxy): bind ZMQ publisher to ZMQ_HOST instead of all interfaces`
* `6ddff2bb` (#1375) — `fix(websocket_proxy): normalize subscribe/unsubscribe mode case-insensitively`
* `9a0f5e42` (#1376) — `fix(websocket_client): correlate subscribe/unsubscribe acks via request_id`
* `521ea129` (#1374) — `fix(cache_invalidation): route through SharedZmqPublisher to eliminate PUB->PUB topology`
* `25eed728` — `fix(ui/websocket-test): keep LTP card live when Depth is also subscribed`
* `f8a1ff4f` (#1386) — `chore(websocket): remove dead get_supported_brokers_list()`
* `06d4cb34` — `docs(audit): add WebSocket broker priority audit`

***

**New broker integrations + exchange expansion**

* **`0ad69cf3` / `15179371`** — IIFLCapital websockets integrated + broker hardening + option-chain perf
* **`440b78ef`** — Groww full option chain + websocket depth integration
* **`c0335582`** — Upstox GLOBAL\_INDEX world feeds (US30 / JAPAN225 / HANGSENG, plus IFSC-routed GIFTNIFTY) on indices and indicators
* **`cd4095eb`** — Zerodha MCX\_INDEX wired through quote/history/depth/ws
* **`ca15b333`** — Groww NSE\_INDEX/BSE\_INDEX in historical (#1338/#1342)
* **`11778af5`** — Symbol search surfaces FUT-only MCX underlyings (#1385)

***

**Security hardening — Fernet per-install salt**

The Fernet KDF in `database/auth_db.py` (which encrypts broker auth tokens) previously used a hardcoded static salt. This release lands a per-install random salt with a crash-safe online migration.

* `2f2e9bee` — `fix(security): rotate Fernet to per-install salt with crash-safe auto-migration`
* `e3c5285d` — place `FERNET_SALT` adjacent to `API_KEY_PEPPER` in `.env`, handle the 4 file-state cases cleanly (placeholder / valid / missing / mid-migration)
* `a1455ff1` — atomic `.env` rewrite falls back to in-place on Docker bind mounts
* `84922078` — degrade gracefully when `.env` is unwritable + pin Docker UID 1000 (#1394)
* `2981ff52` — post-FERNET\_SALT cleanup — security perm-check, dedupe, pool invalidate (#1394)
* `b9301b78` — never recommend rotating `API_KEY_PEPPER` on a populated DB (carried in from late v2.0.0.9 work, re-asserted here)

What this means operationally:

* New installs: `utils/env_check.py` generates a 32-byte hex `FERNET_SALT`, writes it adjacent to `API_KEY_PEPPER` in `.env`, and uses it directly. No migration runs.
* Existing installs upgrading to 2.0.1.1: on first boot, `env_check` detects the placeholder/missing state, generates the new salt, re-encrypts every broker-auth-token ciphertext on the fly with the new key, and atomically swaps. If the process dies mid-migration, the persisted `FERNET_SALT` lets the next boot resume cleanly.
* Same salt entropy feeds the new WhatsApp session blob via the `:whatsapp-session` domain separator.

***

**UI + frontend**

* `cd692653` — `feat(orderbook): make Quantity editable in Modify Order dialog`
* `f968b403` — `fix(ui): align table content with stats cards on Positions/Orderbook/Holdings/Tradebook`
* `d3aa8b6b` — `fix(frontend): auto-reload on stale-chunk import failure (#1393)` — fixes the "ChunkLoadError" trader sees after a deploy when the browser is still holding the old `index-*.js` reference
* `d63ec927` — drop hero gradient on the home page, use solid `text-primary`
* `3f4e2b2b` — home: "New in V2 — 12-Tool Options Analytics Suite" pill
* `624f8726` — home: Integrates With + Made for AI sections
* `61370758` / `54d83c07` — restyle the MCP OAuth consent page to match OpenAlgo dashboard + fix alignment

***

**Configuration changes**

`.sample.env`:

* `FERNET_SALT` — new placeholder line auto-rotated on first boot, placed adjacent to `API_KEY_PEPPER`
* No new keys for WhatsApp — `WHATSAPP_KEY_SALT` reuses the existing `FERNET_SALT` with a `:whatsapp-session` domain suffix (zero new env vars to manage)
* Optional: `WHATSAPP_ATTACHMENT_ROOTS` (comma-separated absolute dirs; defaults to `<openalgo>/db/attachments/`)
* Optional: `RUST_LOG` — defaults to a filter that silences three known-noisy wars/whatsapp-rust modules

`pyproject.toml`:

* `version = "2.0.1.1"`
* New: `wars==0.1.3` dependency (also added to `requirements.txt` + `requirements-nginx.txt`)
* SDK pin (`openalgo`) `1.0.49` → `1.0.50`

`utils/version.py`:

* `VERSION = "2.0.1.1"`

`requirements.txt` + `requirements-nginx.txt`:

* `wars==0.1.3` added after `python-telegram-bot==22.6`
* `openalgo==1.0.49` → `openalgo==1.0.50`

`frontend/src/stores/alertStore.ts`:

* New `whatsapp` toast category alongside `telegram`

***

**Database schema**

New tables created by `database/whatsapp_db.py` on first boot:

| Table                         | Purpose                                                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `whatsapp_config`             | Singleton row holding the Fernet-encrypted session blob + bot config + owner identity                        |
| `whatsapp_users`              | Optional linked recipients (unused in single-user mode, retained for future multi-recipient deployments)     |
| `whatsapp_command_logs`       | Slash-command audit log (sensitive args like `/link`'s api\_key are scrubbed before write)                   |
| `whatsapp_notification_queue` | Retry queue for failed alerts (currently unused — single-user model drops on not-paired instead of queueing) |
| `whatsapp_user_preferences`   | Per-user notification toggles + summary time + language + timezone                                           |

Idempotent `PRAGMA table_info` migration adds `owner_user_id` + `owner_username` columns to `whatsapp_config` on existing installs.

***

**Dependencies**

* `wars==0.1.3` added — PyO3 binding over the whatsapp-rust crate; provides the WhatsApp Web client. Wheels available for Python 3.12+ via abi3.
* `openalgo` SDK pin: `1.0.49` → `1.0.50` (PyPI: <https://pypi.org/project/openalgo/1.0.50/>)
* `urllib3` `2.6.3` → `2.7.0` (`4519f55f`) — clears 8 Dependabot high-severity alerts
* `axios` `1.15` → `1.16`, `python-multipart` `0.0.26` → `0.0.27`, pin `pip>=26.1` (`6d61e5c6`)

***

**Documentation**

* New: `docs/api/whatsapp-services/README.md` — architecture + security model + slash-command reference
* New: `docs/api/whatsapp-services/notify.md` — full endpoint reference for `POST /api/v1/whatsapp/notify`
* New: `collections/openalgo/IN_stock/whatsapp_notify.bru` — Bruno collection entry (auto-discovered by `/playground`)
* Updated: `docs/api/README.md` — adds the WhatsApp Services section under the existing service taxonomy
* Updated: `docs/prompt/openalgo python sdk.md` — full `client.whatsapp(...)` reference with all four recipient forms, image/document attachments, fire-and-forget vs synchronous delivery, and inbound slash-command reference
* `52eb8650` — `docs(mcp): rewrite Remote MCP userguide for traders, drop stale install paths`
* `3b3054be` — `docs(claude): update CLAUDE.md with new product surfaces, Ruff tooling, and architecture details (#1412)`
* `1a7d3a0a` — `docs(claude): clarify sandbox terminology and split /sandbox vs /analyzer surfaces`
* `c7e5f4a9` — `docs(services): align order field names with canonical code (pricetype, product)`
* `83499518` / `e2de15ec` — Ubuntu Server Installation guide refresh

***

**Install + infrastructure**

* `79557be5` — `feat(install): inline Remote MCP prompt in install-docker.sh and install-multi.sh`
* `5c8b64b9` — `feat(install): prompt to enable Remote MCP during install.sh`
* `04eac147` — `feat(install): simplify single-deploy paths + drop enable-remote-mcp.sh`
* `647183bd` — `feat(remote-mcp): UI controls for master switch + posture toggles`
* `9ec851ab` — `fix(mcp): use HOST_SERVER for SDK loopback so install.sh deploys work`
* `5fa17bd3` — `fix(diagnostics): correct dead secret keys + git info inside Docker (#1388)`
* `f786e21a` — `chore: add Caddyfile for local https://openalgo.local dev`
* `4e09da8b` — `fix(python-strategy): Stop button works under gunicorn-eventlet (#1404)`

***

**Bug fixes (non-WebSocket)**

* `a4bdac18` — `fix(angel/api): defensive .get() in place_order response handling (#846)`
* `b06ef4a8` — `fix(kotak): align place/modify order payload with official Neo spec (#1398)`
* `ca15b333` — `fix(groww/api): support NSE_INDEX/BSE_INDEX in historical (#1338) (#1342)`
* `11778af5` — `fix(search): surface FUT-only MCX underlyings in symbol search (#1385)`

***

**Upgrade procedure**

**For existing installs (Native Ubuntu):**

```bash
cd /var/python/openalgo-flask/<deploy-name>/openalgo
sudo ./install/update.sh
# update.sh runs migrate_all.py — the new whatsapp_config / whatsapp_users
# tables and the owner_user_id column are created automatically. The
# FERNET_SALT migration runs on first boot inside env_check; existing
# broker-auth ciphertext is re-encrypted on the fly.
```

**For existing installs (Docker):**

```bash
cd /opt/openalgo/<domain>
sudo docker compose pull
sudo docker compose up -d
# The container's start.sh runs migrate_all.py before gunicorn boots.
# FERNET_SALT migration runs on first start.
```

**For local developers (uv):**

```bash
git pull origin main
uv sync
cd frontend && npm install && npm run build
uv run app.py
```

**Enabling WhatsApp** (post-upgrade, optional):

1. Log in to OpenAlgo, open `/whatsapp`.
2. Click **Start pairing**. A QR code appears.
3. On your phone: WhatsApp → Settings → Linked devices → Link a device → scan.
4. Done. The bot auto-starts and reconnects on every server boot from the encrypted session in `openalgo.db`.

The session blob never leaves your server. There is no second-party service to register with — it's a direct Signal-Protocol connection to WhatsApp.

***

**Contributors**

* **@marketcalls (Rajandran)** — release management; WhatsApp architecture and full implementation (database schema with Fernet-encrypted session blob + domain-separated salt, dedicated `WhatsAppBotThread` to satisfy PyO3's unsendable contract, event-bus subscriber wired into all 13 order topics, send-only REST API + session-authed admin blueprint, React `/whatsapp` page with auto-rotating QR, RUST\_LOG suppression for the three known-noisy wars modules, attachment-path allowlist with traversal-token rejection, lazy own-JID capture from `is_from_me=True` messages, slash-command dispatcher with `is_from_me` gate, auto-reconnect on app boot); openalgo Python SDK 1.0.50 release with new `client.whatsapp(...)` API; WebSocket reliability sweep across 14 brokers (subscribe batching, reconnect hardening, fd-leak fixes); new IIFLCapital streaming adapter (#1416, #1430); Groww option chain + WS depth (#1392); Upstox GLOBAL\_INDEX world feeds; Zerodha MCX\_INDEX wiring (#1385); per-install Fernet salt rotation with crash-safe migration; websocket-proxy fixes (ZMQ bind #1378, mode normalization #1375, request\_id correlation #1376, SharedZmqPublisher topology #1374); UI alignment fixes and stale-chunk auto-reload; comprehensive WhatsApp documentation (endpoint reference, SDK prompt-doc, Bruno collection entry).

***

**Links**

* **Repository**: <https://github.com/marketcalls/openalgo>
* **Documentation**: <https://docs.openalgo.in>
* **Python SDK on PyPI**: <https://pypi.org/project/openalgo/1.0.50/>
* **WhatsApp service docs**: <https://docs.openalgo.in/api-documentation/v1/whatsapp-services>
* **Discord**: <https://www.openalgo.in/discord>
* **YouTube**: <https://www.youtube.com/@openalgo>
* **Issue tracker**: <https://github.com/marketcalls/openalgo/issues>

***

***
