Skip to content

Enable Push Notifications

Browser push lets a lead alert reach an agent even when the admin tab is in the background or closed. It is off platform-wide until you give the API a VAPID key pair. Once the keys are in place, a bell appears in the admin sidebar footer and each person turns it on for the browsers they want alerted. Nothing is pushed to anyone who has not turned the bell on.


VAPID is the signing scheme push services use to know the platform, and not some third party, is the one sending. One pair serves every tenant on the platform. Either of these prints a public and a private key in the base64url form the API expects:

Terminal window
# From the idx-api directory, using the library the API already ships with
uv run python -c "from py_vapid import Vapid, b64urlencode; \
from cryptography.hazmat.primitives import serialization as s; \
v = Vapid(); v.generate_keys(); \
print('VAPID_PUBLIC_KEY=' + b64urlencode(v.public_key.public_bytes(s.Encoding.X962, s.PublicFormat.UncompressedPoint))); \
print('VAPID_PRIVATE_KEY=' + b64urlencode(v.private_key.private_numbers().private_value.to_bytes(32, 'big')))"
Terminal window
# Or with the reference Node tool
npx web-push generate-vapid-keys

The private key is a secret. Treat it like the SMTP password: it goes in .env on the host and nowhere else. Rotating it invalidates every existing subscription, so agents would have to turn the bell off and on again.


  1. Add the three variables to the API’s .env:

    Terminal window
    VAPID_PUBLIC_KEY=BNc... # the public key, base64url
    VAPID_PRIVATE_KEY=x3k... # the private key, base64url
    VAPID_SUBJECT=mailto:ops@example.com

    VAPID_SUBJECT is the contact push services can use if the platform misbehaves. A mailto: address or an https:// URL you actually watch.

  2. Recreate the API container so it reads the new values:

    Terminal window
    docker compose --profile prod up -d idx-api
  3. Confirm the API sees them. With any agent-or-above credential:

    Terminal window
    curl -s https://api.<DOMAIN>/api/v1/me/push/vapid-public-key \
    -H "Authorization: Bearer idx_..."
    # {"public_key":"BNc...","configured":true}

    configured is only true when all three variables are set. With any of them missing the bell stays hidden and the API sends nothing.


Every admin user does this once per browser.

  1. Open any admin page. The bell sits in the sidebar footer next to the theme switch (on the tablet rail it is the icon under the switch).
  2. Click it. The browser asks for permission to show notifications; allow it.
  3. A toast confirms the bell is on and offers Send a test. Take it. A notification titled Notifications are on should appear within a second or two. Clicking it focuses the admin tab.

Clicking the bell again turns it off for that browser and removes the subscription from the server. A crossed-out bell means the person blocked notifications for the site in their browser settings; only they can undo that, from the browser’s site permissions.

The browser, not the platform, remembers the on/off state. Signing in as a different person on the same browser hands the subscription to that person.


Push is a second channel for the response-window alerts the lifecycle sweep already emails. Once the brokerage’s alert channels include push, each rung of the ladder (breach, reminder, escalation) also lands as a notification on every browser where the recipient turned the bell on: the assigned agent, or the brokerage’s brokers when the lead is unassigned. The notification carries the lead’s name and opens the lead page when clicked. See SLA targets for the ladder itself.

Nothing else is pushed today. Drip sends, tour requests and contact-form intake stay email-only.


Subscriptions go stale: people clear site data, uninstall the browser, or the push service rotates the endpoint. The API prunes on delivery rather than on a schedule.

Push service responseWhat happens to the subscription
DeliveredFailure count reset, last_used_at updated
404 or 410Deleted immediately; the browser dropped it
Anything else (timeout, 5xx, bad key)Failure count incremented; deleted after five in a row

Turning the bell on again in that browser recreates the row. Each user’s current subscriptions are visible at GET /api/v1/me/push/subscriptions with their own credential.