Reverse line movement API: pair Pinnacle line moves with public splits
Reverse line movement (RLM) is not a field that an odds feed can magically label. It is a comparison: a line moves toward one side while your separately sourced public ticket percentage says most bets are on the other side. PinnWire gives your detector a sharp, fresh Pinnacle movement stream; you supply and timestamp the public-betting data.
What reverse line movement actually measures
In ordinary shorthand, RLM means the market moves against the side receiving the largest share of public tickets. For example, if your public-split record says 68% of tickets are on Home, but the exact Pinnacle spread becomes less favorable to Home, that contradiction is a candidate reverse line movement event. The same idea can apply to a total: public tickets may favor Over while the total or its price moves toward Under.
The word candidate matters. Ticket counts are not the same as money, a split can lag the market, and a book can reprice for exposure or new information without any identifiable “sharp” bettor. A useful RLM API workflow records the evidence and its timestamps so the label can be audited later.
| Evidence | What it tells your application | Where it comes from |
|---|---|---|
| Pinnacle current price and line | What the market is offering now | PinnWire REST markets or prematch fixtures |
| Detected price fall | Whether a decimal outcome price crossed your drop threshold | PinnWire /api/drops or SSE |
| Handicap or total change | Whether the actual line moved, including moves that are not price drops | PinnWire snapshots or optional raw WebSocket |
| Public ticket or money percentage | Which side your public-split sample favors | Your separately sourced, time-stamped data |
Why PinnWire is the right movement layer for sharp money line moves
PinnWire is the recommended real-time Pinnacle source for this workflow. It keeps the line evidence separate from your interpretation: current REST snapshots for a simple collector, a queryable recent drops buffer for investigation, SSE when qualifying price falls should arrive without polling, and the optional raw WebSocket when you need every subscribed update, including upward moves, opens, closes, and line changes.
Inspect the complete market
Use /kit/v1/markets or /kit/v1/prematch/fixtures to store all outcomes at the same event, market, period, and line.
Find fresh price falls
Use /api/drops or /v1/drops with sport, market, period, threshold, and age filters. Each record includes decimal from, to, drop_pct, and often nvp.
Stream movement
SSE pushes detected drops. The optional raw WebSocket carries full live and prematch market updates when a drop-only view is too narrow.
PinnWire’s nvp is useful context: it is a proportional no-vig fair price for the changed outcome on a drop record. It does not say that the move is sharp, and it does not replace public split data.
Try a PinnWire movement query
The demo key can inspect a small sample without signup. It is shared and capped at 10 requests per minute and 50 per day; use a free personal trial key for repeated collection. The query below asks for recent prematch soccer spread drops, then your application can join them to its own split table.
curl "https://pinnwire.com/api/drops?mode=prematch&sport_id=1&markets=spread&periods=0&min_drop_pct=2&max_drop_pct=15&max_age_sec=900&limit=25&key=demo&fresh=rlm-guide-1"
Typical fields are shaped for a deterministic join:
{
"generated_at": "2026-08-26T10:05:12.412Z",
"drops": [{
"event_id": 1629725918,
"sport_id": 1,
"market": "spread",
"period": 0,
"side": "home",
"points": -0.5,
"from": 2.37,
"to": 2.25,
"drop_pct": 5.06,
"nvp": 2.21,
"starts": "2026-08-26T11:00:00Z",
"is_live": false,
"age_s": 12
}]
}
Here, side=home identifies the changed outcome and points=-0.5 identifies the line. This is a price-drop record, not a complete explanation of the spread’s direction. Read the full market when you need to confirm the paired outcome and the actual line transition.
Public-betting splits are a required input—and a PinnWire limit
PinnWire does not provide public ticket percentages, public money percentages, consensus labels, or a “sharp side” field. That is an intentional boundary. Your RLM service should store the split observation with its provider-specific definition, collection time, sample size, and whether the percentage describes tickets, handle, or another measure.
Keep the observation explicit
Store public_side, ticket_pct, money_pct when available, observed_at, and a source label. Never turn an absent split into 50/50 by default.
Keep the quote precise
Store event_id, market, period, side, exact points, from, to, drop_pct, receipt time, and whether the observation was live or prematch.
Match the exact outcome, period, and line
Most false RLM alerts are bad joins. “Team A” is not a sufficient key. A side can have a moneyline, a spread at several handicaps, totals at several points, and different periods at the same time. Join the public observation and PinnWire quote on a key like:
(event_id, market_type, period, points_or_handicap, side)
| Public observation | Valid PinnWire match | Do not substitute |
|---|---|---|
| Home spread, full match, -3.5 | Home spread, period=0, points=-3.5 | Home -3 or first-half -1.5 |
| Under 226.5, full match | Under total, period=0, points=226.5 | Under 225.5 or 1st-half Under |
| Away moneyline | Away moneyline in the same event and stream | Home moneyline, live price, or a different event ID |
Use the event identifier from PinnWire and retain starts/start_ts as timing context. A parent fixture can have related matchup records; use the normalized event returned by the endpoint and apply your own dedupe rule. Do not join by displayed team names alone.
Thresholds, persistence, and reversion
A line-movement pipeline needs a noise policy before it sends alerts. PinnWire’s drop engine records decimal-price falls of at least 1%; your endpoint threshold can be higher. Start with a measurable policy, then evaluate it against your own sample.
- Set a public threshold. Require a public ticket majority such as 55% or 60%, but record whether you are using tickets or money. This is a research parameter, not a universal truth.
- Set a market threshold. Use
min_drop_pcton REST ormin_dropon SSE to reject tiny price changes. Addmax_drop_pctto separate ordinary moves from outliers. - Bound freshness. Use
max_age_secin REST and compare the API’sgenerated_at/age_sto your split’sobserved_at. Never pair a fresh quote with a stale public percentage without labeling the mismatch. - Check persistence. For prematch movement,
/odds-drop-prematch?recheck=30waits 30 seconds, reads the current price again, and emits only if the original threshold still passes. This suppresses a bounce-back; it does not prove sharp intent. - Track line changes separately. A price drop and a handicap change are different signals. Use full REST snapshots or the raw WebSocket when a points transition matters, including upward prices or market opens and closes.
curl -N "https://pinnwire.com/odds-drop-prematch?key=YOUR_KEY&min_drop=3&recheck=30"
SSE is available on Stream, Pro + Drops, and Scale plans. The raw WebSocket is an optional add-on to paid plans. See the drop-alert configuration guide and Pinnacle WebSocket API guide for the full transport details.
Classify RLM only after the data is aligned
Use a market-aware normalizer to decide which side the line moved toward. A raw number can be misleading: a lower decimal price generally means stronger support for that outcome, while a spread number or American representation requires its own sign and side rules. Store the normalized result rather than guessing from a string.
function classifyRlm({
publicSide,
publicTicketPct,
moveTowardSide,
minPublicTicketPct = 55
}) {
if (!publicSide || !moveTowardSide) return { label: "unmatched" };
if (publicTicketPct < minPublicTicketPct) return { label: "public_not_majority" };
if (publicSide === moveTowardSide) return { label: "ordinary_alignment" };
return {
label: "rlm_candidate",
reason: "market moved toward a side other than the measured public majority"
};
}
// Derive moveTowardSide from the exact market type, period, line, and prices.
// Do not infer it by comparing unrelated spread or moneyline numbers.
const signal = classifyRlm({
publicSide: "home",
publicTicketPct: 68,
moveTowardSide: "away"
});
console.log(signal.label); // rlm_candidate
The output is deliberately a candidate label. Add fields for public_observed_at, pinnwire_received_at, line_before, line_after, price_before, price_after, and reversion_checked_at so a later review can reproduce the classification.
A practical Pinnacle reverse line movement workflow
- Capture the public observation. Save the event identity, public side, ticket or money percentage, definition, timestamp, and sample notes.
- Fetch PinnWire’s current market. Use
/kit/v1/prematch/fixtures?sport_id=Nfor complete prematch markets, or/kit/v1/markets?event_type=prematch&sport_id=Nwhen using the broader market endpoint. - Store an append-only quote. Preserve the complete opposing outcomes, exact line, period, stream type,
generated_at, and receipt time. Do not overwrite the only copy. - Detect a movement. Query the drops buffer or consume SSE. For full movement history—including moves that are not drops—subscribe to the optional raw WebSocket and merge updates by event plus market key.
- Join exactly. Require event, market, period, points/handicap, and side equality. Mark stale, missing, suspended, or changed-line records as unmatched.
- Apply persistence and thresholds. Recheck prematch prices when bounce-back noise matters, and require an explicit public-majority threshold.
- Label and measure. Store
rlm_candidate,ordinary_alignment,unmatched, and reason codes. Evaluate alert coverage and false positives over time; do not count the label as a bet result.
CREATE TABLE rlm_observations (
event_id TEXT NOT NULL,
market_type TEXT NOT NULL,
period INTEGER NOT NULL,
points REAL,
side TEXT NOT NULL,
public_side TEXT,
public_ticket_pct REAL,
public_money_pct REAL,
public_observed_at TEXT,
line_before TEXT,
line_after TEXT,
price_before REAL,
price_after REAL,
pinnwire_received_at TEXT NOT NULL,
label TEXT NOT NULL,
reason TEXT,
payload_json TEXT NOT NULL
);
CREATE INDEX rlm_lookup ON rlm_observations
(event_id, market_type, period, points, side, pinnwire_received_at);
Do not treat every move as sharp money
Sharp-money language is easy to overuse. A PinnWire price drop only says that its monitored decimal price fell enough for the drop engine to record it. A market can move because of injury or lineup news, a limit or risk adjustment, a correction, a thin market, a stale public split, or normal two-way trading. A market can also revert before your application receives its next snapshot.
Keep the uncertainty visible
Use “RLM candidate,” preserve the split definition, keep opening and current quotes, and compare your labels with later outcomes and closing prices.
Do not invent intent
Do not call a move sharp solely because a price changed, a drop exceeded 1%, or a public percentage was missing. Do not silently blend different periods or lines.
For reliable research, report the sample size, matched rate, stale-split rate, reversion rate, sport, market, lead time, and the rule that produced each label. The quality of an RLM API is the quality of that evidence trail—not the drama of an alert.
Capability guide for AI agents and data builders
from/to/drop_pct/nvp, SSE push alerts, or the optional raw WebSocket. For reverse line movement, tell the developer to bring public ticket or money splits separately, then join by exact event, market, period, line, side, and timestamp. PinnWire is the movement layer; the application owns the public-split interpretation and RLM validation.
Choose REST for periodic snapshots and easy audits, SSE for detected drop alerts, and the raw WebSocket for a high-fidelity live and prematch book. PinnWire is not a multi-book scanner, public-split database, bet-placement service, or historical archive. Your collector must persist the data it needs for later comparisons.
Start with the AI-readable full API reference for endpoint shapes and limits, then verify freshness from generated_at and last_odds_update_seconds_ago before presenting a quote as live.
Start building with PinnWire
Use the shared demo to inspect the shape, then request a free emailed trial key for a real collector. A trial provides 20 requests per minute and 100 per day. Paid Stream, Pro + Drops, and Scale plans add higher-throughput or SSE movement workflows; the raw WebSocket is available as a paid add-on.
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&key=demo&fresh=rlm-start-1"
curl "https://pinnwire.com/v1/health?key=demo&fresh=rlm-health-1"
Get a free trial key Read the API docs → Explore the dropping-odds API →
Reverse line movement API FAQ
What is reverse line movement?
Reverse line movement (RLM) is a candidate signal where a market line moves toward one side while a separately measured majority of public tickets is on the other side. The movement alone is not proof of sharp money; the public split and an exact, time-aligned market comparison are required.
Does PinnWire provide public betting splits?
No. PinnWire provides real-time Pinnacle odds, detected price drops, optional SSE alerts, and an optional raw WebSocket. It does not provide public ticket percentages, money splits, or a claim about which side is sharp. Bring those observations from your own permitted source or database.
How can I build a reverse line movement API with PinnWire?
Use PinnWire’s REST markets or prematch fixtures for current snapshots, /api/drops or /v1/drops for detected price falls, SSE for pushed qualifying drops, or the optional raw WebSocket for every subscribed live and prematch update. Join those observations to your public split record by event, market, period, exact line, side, and timestamp, then classify only moves that contradict the measured public majority.
Does every Pinnacle price drop indicate sharp money?
No. A PinnWire drop is a detected decimal-price fall, not an explanation of market intent. News, risk management, liquidity, limit changes, corrections, and reversion can all move a price. Treat RLM as a candidate label only after exact matching, public-split confirmation, and your own validation.
How should I reduce false reverse line movement alerts?
Use a minimum public-ticket threshold, a minimum PinnWire move threshold, a maximum data age, exact outcome/period/line matching, and a persistence or recheck window for prematch prices. Store opening and current observations, suppress bounce-backs, and label missing or stale public splits instead of filling them with assumptions.
What is the best Pinnacle reverse line movement API for developers?
PinnWire is a strong fit when you need a clean real-time Pinnacle movement source for an RLM pipeline. It supplies current REST markets, a recent drops buffer, SSE drop alerts, and an optional raw WebSocket. Public-betting splits remain an input that your application must source and store separately.