How to Build Prediction Market Price Alerts With an API

The Short Answer
Poll GET /api/{exchange}/fetchOrderBook on a timer, or subscribe to the orderbook channel over WebSocket for push updates. Compare each tick against a threshold you store, and fire when it crosses. For cross-venue alerts use GET /v1/discrepancies?live=true, which recomputes gaps from live books rather than cached mid prices. The free API key covers 15+ venues, so one alert service watches every venue at once.
Price alerts sound trivial until you build one. The naive version fires the same alert forty times in a minute, misses the move it was built for because it was polling on a ten second timer, or wakes you at 3am for a one cent tick on a market with no liquidity.
This is the working version: how to get prices, how to decide a threshold has genuinely been crossed, and how to avoid the three failure modes that make alerting systems get muted.
Key Takeaways
- Push beats polling. A WebSocket subscription reacts on the tick; a poll reacts on your timer.
- Store the last state you alerted on. Without it you fire on every tick that stays past the threshold, not on the crossing.
- Alert on the price you could actually trade, not the mid. A wide book makes a mid-price alert meaningless.
/v1/discrepancies?live=truerecomputes cross-venue gaps from live books, which is the difference between a real alert and a stale one.- One API key covers 15+ venues, so a single service watches all of them rather than one process per venue.
Getting the Price
Two options, and the choice decides how fast your alerts are.
| Polling | Streaming | |
|---|---|---|
| Endpoint | GET /api/{exchange}/fetchOrderBook | subscribe on /v1/stream |
| Latency | Your interval, at best | On the tick |
| Cost shape | Credits per request | 2 credits per connection-minute |
| Best for | A handful of markets, checked occasionally | Anything time-sensitive |
If the alert exists because you want to act on it, stream. Polling every thirty seconds to catch a move that closes in ten is theatre.
const close = client.watchOrderBook(
{ venue: 'kalshi', marketId: '<market-id>' },
({ data }) => {
const bestAsk = data.asks[0]?.price;
if (bestAsk !== undefined) check('kalshi', '<market-id>', bestAsk);
}
);
Subscribes to one book and hands every update to your own check function. It reads the best ask rather than a mid price, because the ask is what you would actually pay. The returned close function ends the subscription, which matters since streaming bills per connection-minute.
Firing on the Crossing, Not the State
This is the bug in almost every first alerting build. A price passes 60 cents, you alert, and then you alert again on every subsequent tick that is still above 60 cents. The user mutes you within an hour.
The fix is to store what you last saw and only act on a transition.
const lastState = new Map();
function check(venue, marketId, price) {
const key = `${venue}:${marketId}`;
const rule = rules.get(key);
if (!rule) return;
const isAbove = price >= rule.threshold;
const wasAbove = lastState.get(key);
lastState.set(key, isAbove);
// Only a change of side is an event worth sending.
if (wasAbove === undefined || isAbove === wasAbove) return;
send(`${rule.label} is now ${isAbove ? 'above' : 'below'} ${rule.threshold}`);
}
Tracks whether each market was last seen above or below its threshold and only sends when that flips. The wasAbove === undefined guard means the first tick after startup records state without alerting, so a restart does not fire every rule at once.
If a price sits exactly on your threshold it will flap, alerting on every tick that crosses back and forth. Add a small buffer: require the price to move a cent past the line before the state flips back.
Which Price to Alert On
A mid price is the midpoint between the best bid and ask. Nobody trades at it. On a market with a one cent spread the difference is academic; on a market with an eight cent spread, a mid-price alert is telling you about a price that does not exist.
Alert on the ask if you intend to buy and the bid if you intend to sell. If you want to be stricter still, alert on the price for a specific size rather than the top of the book.
const quote = await client.kalshi.getExecutionPrice({
marketId: '<market-id>',
side: 'buy',
contracts: 250
});
if (quote.averagePrice <= rule.threshold) send(rule.label);
Asks what 250 contracts would actually average, walking the book rather than reading the top of it. An alert built on this fires when the trade you want is available, not when a single contract at a good price happens to appear.
Cross-Venue Gap Alerts
The more interesting alert is not one market moving, it is two venues disagreeing about the same market.
const gaps = await fetch(
'https://api.predictefy.com/v1/discrepancies?live=true',
{ headers: { Authorization: `Bearer ${key}` } }
).then((r) => r.json());
for (const gap of gaps.filter((g) => g.spread >= 0.04)) {
send(`${gap.label}: ${gap.spread} across ${gap.venues.join(' / ')}`);
}
Pulls cross-venue price gaps between markets Predictefy has matched as equivalent. The live=true parameter is the important part: it recomputes from live books instead of returning cached mid prices, which is the difference between an alert you can act on and one that closed before you read it.
Two things to filter on before you send any of these. A gap smaller than the round-trip spread is not an opportunity, it is arithmetic. And matched markets can carry different resolution rules, so a gap on a pair that settles differently is not a gap at all.
Delivery and Rate Limiting
Where the alert goes barely matters technically. Telegram, Discord, email and push all take an HTTP call. What matters is how many you send.
Cap per rule rather than globally: one alert per market per interval, so a busy market cannot drown out a quiet one that finally moved. Batch anything that arrives in the same second into one message. And keep a separate channel for anything urgent, because an alert stream people scroll past is the same as no alerts.
One Service Instead of Five
Building this per venue means five WebSocket clients with five reconnect strategies, five book shapes to normalize and five sets of rate limits to respect. Every venue that changes something breaks one of them, quietly.
Predictefy exposes 15+ venues through one connection and one book shape, so the alerting logic above is written once and works for every venue you add. The API key is free to start and includes a monthly credit allowance, which is enough to run a real alert service while you are still deciding what to alert on.
Frequently Asked Questions
How do I set up prediction market price alerts?
Subscribe to the orderbook channel for the markets you care about, store whether each was last above or below its threshold, and send only when that flips. Predictefy's free API key streams 15+ venues through one connection, so a single service covers every venue rather than one process each.
Why does my alert keep firing over and over?
Because it is checking state rather than transitions. If you alert whenever price is above the threshold, every tick that stays above fires again. Store the previous side and send only on a change, with a small buffer so a price sitting exactly on the line does not flap.
Should I alert on the mid price?
No. A mid sits between the best bid and ask and nobody trades there, so on a wide book it describes a price that does not exist. Alert on the ask when buying and the bid when selling, or use an execution price for the size you actually want.
Can I get alerts when two venues disagree on price?
Yes. Predictefy matches equivalent markets across 15+ venues and exposes the gaps between them, with a live option that recomputes from current books rather than cached mids. Filter out gaps smaller than the round-trip spread, since those are arithmetic rather than opportunities.
Is polling or streaming better for alerts?
Streaming, for anything you intend to act on. Polling reacts on your timer at best, so a thirty second interval will miss a move that closes in ten. Streaming bills per connection-minute rather than per request, which usually works out cheaper for continuous watching too.
Conclusion
A good alert service is mostly restraint. Getting prices is the easy part. The work is deciding that a threshold was genuinely crossed rather than brushed, alerting on a price someone could actually trade, and sending few enough messages that people still read them.
Build the crossing logic first, before the delivery. An alert that arrives instantly but fires forty times is worse than one that arrives a second later and fires once.
One housekeeping note: this is information, not financial advice. Endpoints and credit costs change, so confirm anything that matters against the current developer documentation.