> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ironflow.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Hyperliquid liquidation alerts to Discord, Slack, Telegram or a webhook

> Get Hyperliquid liquidations posted to a Discord channel, a Slack channel, a Telegram chat or your own webhook within seconds, filtered by market, side, size and wallet. No polling, no server to run.

Ironflow watches every Hyperliquid liquidation on its own node and posts the ones you ask for to your channel. You create the alert once; nothing runs on your side.

## From Telegram, no key

Message [@ironflow\_liquidations\_bot](https://t.me/ironflow_liquidations_bot) and say what you want:

| Command | This chat gets |
| - | - |
| `/alert BTC 100k` | BTC liquidations of \$100k or more |
| `/alert BTC,ETH,SOL long 1m` | Longs liquidated on those markets, \$1M or more |
| `/alert all 5m` | Every market, \$5M or more |
| `/alerts` | The chat's alerts |
| `/stop 1`, `/stop all` | Stops one or all of them |

The same bot watches wallets:

| Command | This chat gets |
| - | - |
| `/watch 0x...` | A message when one of the wallet's positions (native or HIP-3) gets within 10%, 5% and 2% of its liquidation price, and if it is liquidated |
| `/follow 0x... 50k` | A message when the wallet opens, closes or flips a position of \$50k or more |
| `/unwatch 0x...`, `/unfollow 0x...` | Stops one (or `all`) |

It works in a private chat, in a group (only the group's admins can set up or stop alerts) and in a channel (add the bot as an admin that can post). Without a size the floor is \$100k. A chat gets one alert (up to 20 markets), one watch and one follow for free; `/pro` gives 5 alerts, 10 watches and 20 follows for 1,000 Telegram Stars a month. For Discord, Slack and webhooks, use a key as below.

## Create one

Any API key works (a [free key](https://ironflow.sh/key) allows one alert). Point `url` at a Discord channel webhook, a Slack incoming webhook or your own HTTPS endpoint:

```bash theme={null}
curl -X POST https://api.ironflow.sh/v1/alerts \
  -H "Authorization: Bearer if_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "BTC and ETH longs",
    "url": "https://discord.com/api/webhooks/123/abc",
    "markets": ["BTC", "ETH"],
    "side": "long",
    "min_usd": 100000
  }'
```

Then check it reaches the channel:

```bash theme={null}
curl -X POST https://api.ironflow.sh/v1/alerts/ALERT_ID/test -H "Authorization: Bearer if_your_key"
```

| Field | Meaning |
| - | - |
| `url` | `https://discord.com/api/webhooks/...`, `https://hooks.slack.com/services/...`, or any public HTTPS URL on port 443 or 8443 |
| `markets` | Symbols or coin names (`BTC`, `ETH-PERP`, `xyz:NVDA`, `HYPE/USDC`); omit for every market |
| `side` | `long` (longs liquidated), `short`, or `any` |
| `min_usd` | Smallest liquidation to report, in USD |
| `address` | Only this wallet's liquidations |

To get a Discord webhook URL: channel settings, Integrations, Webhooks, New Webhook, Copy Webhook URL. For Slack: create an app with Incoming Webhooks and add one to the channel.

## Telegram

Telegram has no webhook URLs: our liquidation bot posts into your chat. Send `telegram_chat` instead of `url`:

```bash theme={null}
curl -X POST https://api.ironflow.sh/v1/alerts \
  -H "Authorization: Bearer if_your_key" \
  -H "Content-Type: application/json" \
  -d '{"telegram_chat": "@my_liquidations", "markets": "BTC,ETH", "min_usd": 250000}'
```

Add [@ironflow\_liquidations\_bot](https://t.me/ironflow_liquidations_bot) to the chat (the response's `setup` names it too): in a channel as an admin that can post messages, in a group as a member. A public channel or group is its `@name`; a private one is its numeric id (it starts with `-100`; forward a message from the chat to a bot such as @userinfobot to see it). Then send a test; if the bot is missing from the chat, the test result says so.

## What arrives

Partial fills of one liquidated position in one transaction count as one liquidation, and `min_usd` applies to their total. An alert sends at most one message every 5 seconds, listing everything it matched since the last one (up to 20, then a count and a total), so a cascade arrives as a handful of messages.

In Discord and Slack each line reads:

```text theme={null}
BTC-PERP long liquidated: $1.24M at 80355, 0x1234…abcd
```

A webhook receives JSON:

```json theme={null}
{
  "type": "liquidations",
  "alert_id": "6f1c...",
  "alert_name": "BTC and ETH longs",
  "sent_at": "2026-11-05T14:02:11Z",
  "liquidations": [
    {
      "id": "1793887329104-2214",
      "time_ms": 1793887329104,
      "time": "2026-11-05T14:02:09Z",
      "market": "BTC-PERP",
      "side": "long",
      "address": "0x1234...abcd",
      "size": 15.4,
      "price": 80355.2,
      "usd": 1237470,
      "fills": 3,
      "hash": "0x9a..."
    }
  ],
  "more": 0,
  "more_usd": 0
}
```

In Telegram the same lines arrive with the amount in bold and the wallet as a link.

A test message has `"type": "test"`. Delivery is at least once: after a restart a few seconds can be sent again, so use `id` to drop repeats.

## Verify a webhook

The create response has a `signing_secret` (shown once). Each request carries `X-Ironflow-Signature: t=<unix seconds>,v1=<hex>`, where `v1` is the HMAC-SHA256 of `<t>.<raw body>` with that secret.

```python theme={null}
import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    mac = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256)
    return hmac.compare_digest(mac.hexdigest(), parts["v1"])
```

```javascript theme={null}
import crypto from "node:crypto";

export function verify(secret, header, rawBody) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const mac = crypto.createHmac("sha256", secret).update(`${parts.t}.`).update(rawBody).digest("hex");
  return typeof parts.v1 === "string" && parts.v1.length === mac.length &&
    crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(parts.v1));
}
```

Answer with any 2xx status within 10 seconds.

## Limits and failures

| Tier | Alerts |
| - | - |
| Free | 1 (Discord, Slack and Telegram messages end with a one-line Ironflow link) |
| Explorer | 5 |
| Builder | 20 |
| Enterprise | 100 |

A failed delivery is tried once more 5 seconds later. After 20 failed deliveries in a row (a deleted webhook, an endpoint that is down) the alert is disabled; `GET /v1/alerts` shows `status` and `last_error`. Fix the destination and send a [test](https://docs.ironflow.sh/api-reference/alerts/test-alert.md): a delivered test switches the alert back on.

For the raw feed in your own code use the [liquidations stream](https://docs.ironflow.sh/api-reference/market-data/stream-liquidations.md) instead.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.