building-notification-streams

Building Notification Streams

A notification stream has two parts:

  1. a deployed notification algorithm that returns candidate rows,
  2. a delivery config that sends those candidates to a webhook.

Console separates those concerns into Ingestion and Delivery screens. Ingestion manages account-owned users or wallets. Delivery attaches algorithms to webhook settings.

Step 1: ingest users or wallets

Use Console's Notifications → Ingestion workflow when notification candidates must be matched to your users. For example, ingest wallet addresses for your app users, then use .inAppUsers("wallet_address") in the algorithm.

Step 2: build the algorithm

import { StudioV1 } from "algo-dsl";

export default async function notificationAlgo({ apiKey }) {
  const mbd = new StudioV1({ apiKey });

  return mbd
    .search()
    .index("hyperliquid-notifications")
    .include()
    .inAppUsers("wallet_address")
    .notNull("user_id")
    .sortBy("timestamp", "desc")
    .size(25)
    .execute();
}

Step 3: configure delivery

import { notification } from "algo-dsl";

export default notification("hyperliquid-wallet-alerts")
  .algos([125])
  .webhook("https://your-app.com/webhooks/embed-notifications", {
    authHeader: "x-embed-webhook-token",
    authBearer: process.env.EMBED_WEBHOOK_TOKEN
  })
  .cooldown({ hours: 6, key: "user_id" })
  .priorityFilter("P0,P1")
  .dailyBudget(10000);

Step 4: receive delivery

app.post("/webhooks/embed-notifications", express.json(), async (req, res) => {
  const token = req.header("x-embed-webhook-token");
  if (token !== process.env.EMBED_WEBHOOK_TOKEN) {
    return res.sendStatus(401);
  }

  await deliverNotification(req.body);
  res.sendStatus(200);
});

Operational notes

  • Keep webhook responses fast; enqueue slow push, email, or in-app work.
  • Use cooldown keys such as user_id to avoid repeating the same alert too frequently.
  • Use daily budgets while testing new algorithms.