> 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>

***

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.openalgo.in/change-log/release/version-2.0.1.1-released.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
