A first rule
Every Hyperliquid BTC liquidation of $250,000 or more:filters (config is accepted as the same key) and has three parts:
- Scope keys (
venue,symbols, andaddresseson account events) choose where the event is watched. conditionscompare the event’s declared metrics with your values, herenotional_usdat least 250,000.paramsdefine what an occurrence is, such as a burst’s window. This rule sets none, somax_age_stakes its default.
conditions or params sent at the top level of the body, outside filters, are refused too, rather than creating a rule without them.
Scope
venue(string or list of strings): restrict to venues the event covers. Absent means every venue it covers.symbols(list of strings): restrict to these markets, in venue-native form. Absent means every market.addresses(list of strings,account.*events only): a subset of your watched addresses. Absent means all of them. Each one must already be on your watched list.
Symbol conventions
Symbols are venue-native. A symbol written in the wrong form matches nothing.- Hyperliquid perps: the bare coin,
BTC. - HIP-3: dex prefix and coin,
xyz:AAPL. A bareAAPLmatches nothing. - Hyperliquid Spot: the dashed pair,
HYPE-USDC. - HIP-4 outcome sides:
#and the asset id,#20481. - Lighter (
lighter): the bare market symbol,BTC. - Lighter on Robinhood Chain (
rh-lighter): the bare perp symbol,BTC, or the dashed spot pair with the USDG quote,AAPL-USDG. account.transferandmarket.pga_payment: the token, not a pair, such asUSDCorHYPE.
Conditions
Conditions compare a metric the event declares with a value. A rule takes up to 16 conditions, and all of them must hold. No conditions means every occurrence:account.fill with no conditions is every fill of a watched address, and market.liquidation with no conditions is every liquidation on the covered venues from the 100 USD scan floor up.
- Numbers:
greater_than,greater_than_or_equal,less_than,less_than_or_equal,equal,not_equal,between,not_between,in,not_in. - Text and enumerated values:
equal,not_equal,in,not_in,contains,not_contains,starts_with,ends_with. - True or false values:
equal,not_equal. - Timestamps:
before,after,equal, with RFC 3339 values. - Any type:
is_empty,is_not_empty.
>=, <, != and the like) are accepted and stored in word form. between and not_between take [low, high]; in and not_in take a non-empty list; is_empty and is_not_empty take no value. A custom-formula operator (formula) is reserved and refused for now; combine conditions instead.
min_notional_usd at the top level of filters is shorthand for a notional_usd greater_than_or_equal condition, or usdc_value on account.transfer, the one event whose notional metric has that name. It is refused on events that declare no notional metric.
Which metrics an event declares, with their types, units and enum values, is in the catalog: GET /v1/webhooks/event-types returns metrics, operators and params for each event.
Relative values
Four metrics let a threshold mean the same thing on a large market and a small one. They are conditionable like any other metric.notional_pct_volume_1handnotional_pct_volume_24h: the event’s notional as a percent of that market’s trailing volume. Onmarket.liquidation,account.liquidated,account.fillandmarket.liquidation_burst.notional_pct_oi: as a percent of that market’s open interest. On the same events, perps only.notional_pct_wallet_volume_30d: as a percent of that wallet’s own 30-day volume. Onaccount.fill.
null, so a condition on it does not fire, when its denominator is under 10,000 USD, which keeps a thin market from producing a huge percentage. notional_pct_oi is null on spot markets, and the volume percentages are null on Lighter on Robinhood Chain. A payload with a relative value carries reference_at, the time the denominator was measured.
Params
Some events are defined by a window or a level, so the value changes what an occurrence is rather than filtering one. This is the full list; defaults are in parentheses.market.liquidation_burst:window_sone of 60, 300, 900, 3600 (300);threshold_modeone ofusd,pct_oi,pct_volume_1h(usd);threshold_usdfrom 1,000, used inusdmode (1,000,000);threshold_pct0.01 to 100, used in the two percent modes (1).market.oi_delta:window_sone of 300, 900, 3600 (900);threshold_pct0.1 to 1000 (10).market.breadth_cross:threshold1 to 99 percent (30);hysteresis_pct0 to 50 points (5).oracle.jump:threshold_pct0.1 to 50 (2).oracle.stall:window_sone of 60, 120, 300, 900, 3600 (300).ingest.stallandingest.recovered:threshold_sone of 60, 120, 300, 600, 1800, 3600 (600). A market is judged against it only when the threshold is at least five times its usual update interval. Lighter books update about once a minute, so on the Lighter venues most markets are judged from 600 seconds and the sparsest only from 1800.chain.block_stall:threshold_sone of 10, 20, 30, 60, 120, 300, 600 (20).chain.block_time_degraded:degraded_pctone of 10, 20, 30, 50 (20);consecutive_minutesone of 1, 2, 3, 5 (2).billing.credit_low:levels_pct, a list of percent-remaining levels, each 0 to 100 ([25, 10, 0]).market.liquidation,market.pga_payment,hip4.settlementand everyaccount.*event:max_age_s60 to 86400 (3600, or 7200 forhip4.settlementandaccount.hip4_settled). See below.
market.liquidation_burst can be written in relative terms: {"params": {"window_s": 60, "threshold_mode": "pct_oi", "threshold_pct": 1}} is “liquidations inside a minute worth one percent of that market’s open interest”, a meaningful threshold on every perp without picking a dollar figure per market. A market without a reference does not fire the percent modes. The default mode is usd, so a rule written before modes existed keeps firing exactly as it did.
Omitted params take the declared default. A value outside the range or off the menu is refused with a 400 naming the allowed values. A declared param may also be written at the top level of filters ("threshold_s": 60) and is routed into params; on market.liquidation_burst, a top-level threshold means threshold_usd. Two rules with different params are two different triggers, and their deliveries carry different event ids.
max_age_s and late deliveries
max_age_s is the oldest occurrence you still want delivered, in seconds behind real time. In normal operation it never comes into play. After an outage on our side, the engine catches up as far back as your max_age_s and delivers those occurrences with late_ms set, and with late: true when they are more than 10 minutes behind, instead of dropping them. Anything older is skipped; fetch it from the REST API or an export. Set it low when a stale alert is worse than no alert, such as a trading trigger, and high when completeness matters more, such as an audit trail.
What the API stores
A fuller rule, on fills by a watched address:min_notional_usd mirrored from the loosest notional_usd lower bound among your conditions.
Edit or switch off a rule
PATCH /v1/webhooks/subscriptions/{id} with {"config": {...}} replaces the whole configuration in place, validated exactly like create (filters is accepted as the key too). {"enabled": false} switches delivery off without losing the configuration, and {"enabled": true} switches it back on, so tuning a threshold never means deleting and recreating the rule. The response is the updated rule in the same shape as create.
addresses the rule covers every watched address, without the side condition it covers both sides, and without params its max_age_s returns to 3600.
enabled is your switch, and it is separate from the engine’s own pause when a rule reaches the plan’s daily allowance. Resuming a paused rule never flips your switch, and switching a rule on never resumes it. See Paused rules. DELETE /v1/webhooks/subscriptions/{id} removes a rule for good.
Next step
See how often the rule would fire
Replay the configuration over recent history before you create it, and pick a threshold from the rate you want.