Understanding Pinnacle’s odds_changed_at
Sharp customers building +EV and arbitrage tooling against Pinnacle frequently ask the same question: “why does odds_changed_at on this Pinnacle row look 20 minutes old?” The short answer is that it is working as designed — it carries Pinnacle’s own trading-desk timestamp, not ours. This page explains what the field actually tracks, why it can sit unchanged for long stretches, and how to pair it with last_seen_at for a clean read on pipeline freshness.
What odds_changed_at Actually Means
On Pinnacle rows, odds_changed_at is Pinnacle’s own trading-desk timestamp — when Pinnacle last repriced this specific line.
It carries forward unchanged whenever Pinnacle signals that the price, line, and is_live flag on a market have not moved. Internally SharpAPI hashes those three fields for every odds row on every refresh; when the hash is identical to the previous snapshot, we keep the previous odds_changed_at rather than overwriting it with the observation time. This preserves the “when did this line last move” semantic across repeated polls of an unchanged market.
odds_changed_at is not the last time our pipeline refreshed or touched this row. For pipeline freshness, use last_seen_at.
Why It Can Look Stale
Pinnacle is a market-maker. Their trading desk publishes a new price only when actual flow forces a re-price — they do not shade lines around retail action to squeeze margin the way soft books do. That discipline is the reason Pinnacle is used as the sharp reference for +EV calculations, but it also means lines can sit unchanged for long stretches.
Observed over a 24-hour window of Pinnacle’s own CDN responses, the rate at which Pinnacle published new data (rather than a cached 304 Not Modified) varies enormously by sport:
| Sport | Pinnacle CDN “new data” rate |
|---|---|
| Soccer | ~94% |
| Tennis | ~66% |
| NHL | ~51% |
| MLB | ~18% |
| NBA | ~9% |
NBA and MLB player props commonly show long idle windows — 30+ minutes is not unusual — because Pinnacle’s trading desk is not moving the line. If you are seeing an old odds_changed_at on an NBA or MLB market, it is almost always Pinnacle’s own publish cadence, not a gap in our pipeline.
How to Read the Fields Together
Every odds row exposes two timestamps. They answer different questions:
| Field | What it tells you |
|---|---|
odds_changed_at | The last time Pinnacle’s trading desk moved this line |
last_seen_at | The last time our pipeline observed this row |
For pipeline freshness checks, use last_seen_at — this updates every time we ingest the row, regardless of whether the price moved.
For “when did Pinnacle last move this line,” use odds_changed_at.
A large gap between the two (fresh last_seen_at, old odds_changed_at) means Pinnacle is holding the line steady. This is normal and is the single most common source of confusion when reading Pinnacle data.
{
"sportsbook": "pinnacle",
"market_type": "player_total_bases",
"selection": "Edmundo Sosa Over",
"line": 0.5,
"odds_american": -129,
"last_seen_at": "2026-04-21T21:35:02Z",
"odds_changed_at": "2026-04-21T18:49:00Z"
}In this example the pipeline saw this row 4 seconds before the client fetched it (last_seen_at is fresh). The price itself last moved 2h 46m earlier (odds_changed_at), because Pinnacle’s trading desk has not repriced Sosa’s total-bases line since pre-market open. Both values are correct.
If last_seen_at is stale (more than a minute or two old for a major-league market), that is a pipeline signal worth investigating. If odds_changed_at is stale but last_seen_at is fresh, Pinnacle is holding the line — treat the displayed price as current.
Why Pinnacle Is Different
Pinnacle accepts sharp action and re-prices based on real flow rather than shading lines around retail bettors. That market-maker discipline is why we use them as the devig reference for +EV — their lines are the closest thing to a fair price available in the market. The tradeoff is that pre-match lines can sit unchanged for long stretches when nothing in the market has moved, which looks like staleness to anyone expecting the constant micro-adjustment that soft books do.
Related
- Odds Snapshot —
odds_changed_atandlast_seen_atfields on the REST odds response - Streaming —
odds_changed_atonodds:updatedeltas - Live vs. Pre-Match — publish cadence and book delivery mechanisms
- EV Calculation — why Pinnacle is the sharp reference