From 25e7141b3d0d2adebcc80a966595477765e5eb94 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 2 Jun 2026 11:40:19 -0400 Subject: [PATCH] =?UTF-8?q?docs!:=20single=20external=20`timestamp`=20(del?= =?UTF-8?q?ivery,=20OpticOdds-parity)=20=E2=80=94=20reverse=20#256=20(SHA-?= =?UTF-8?q?1048)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING (OpenAPI 3.0.0): the Odds response exposes a single `timestamp` field; `odds_changed_at`, `last_seen_at`, and `wire_received_at` are removed. `timestamp` is the delivery / last-refreshed stamp (advances every ingest cycle — feed freshness, matching OpticOdds' `timestamp`), NOT a price-last-changed time; SharpAPI no longer exposes a when-the-price-moved field. Mirrors sharp-api-go #751. - openapi.json: Odds schema → single `timestamp` (delivery description); removed the 3 fields; info.version 2.3.0 → 3.0.0 + CHANGELOG entry. FutureOdds/Splits `timestamp`/`ts` untouched. - mdx × 4 langs (en/es/pt-BR/de): field tables collapsed to one `timestamp` row; examples updated; cross-links to the concept page kept (anchor text → `timestamp`); concepts/pinnacle-odds-changed-at repurposed to explain `timestamp` (slug kept) + _meta.js label; migration callout on odds.mdx. Removed the phantom `all_books[].timestamp` (the API's per-book entries carry no timestamp). - Residual `odds_changed_at`/`last_seen_at`/`wire_received_at` mentions are intentional (migration callouts + concept-page explanation only). Refs SHA-1048 Type: docs Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 4 ++ content/de/api-reference/events-odds.mdx | 13 ++-- content/de/api-reference/odds-batch.mdx | 9 ++- content/de/api-reference/odds-best.mdx | 18 ++--- content/de/api-reference/odds-comparison.mdx | 21 +++--- content/de/api-reference/odds-delta.mdx | 2 +- content/de/api-reference/odds.mdx | 16 +++-- content/de/api-reference/sportsbooks.mdx | 2 +- content/de/api-reference/stream.mdx | 10 +-- content/de/concepts/_meta.js | 2 +- .../de/concepts/pinnacle-odds-changed-at.mdx | 52 ++++++-------- content/de/streaming/overview.mdx | 2 +- content/en/api-reference/events-odds.mdx | 13 ++-- content/en/api-reference/odds-batch.mdx | 9 ++- content/en/api-reference/odds-best.mdx | 18 ++--- content/en/api-reference/odds-comparison.mdx | 21 +++--- content/en/api-reference/odds-delta.mdx | 2 +- content/en/api-reference/odds.mdx | 20 +++--- content/en/api-reference/sportsbooks.mdx | 2 +- content/en/api-reference/stream.mdx | 12 ++-- content/en/concepts/_meta.js | 2 +- .../en/concepts/pinnacle-odds-changed-at.mdx | 68 +++++++------------ content/en/streaming/overview.mdx | 2 +- content/es/api-reference/events-odds.mdx | 13 ++-- content/es/api-reference/odds-batch.mdx | 9 ++- content/es/api-reference/odds-best.mdx | 18 ++--- content/es/api-reference/odds-comparison.mdx | 21 +++--- content/es/api-reference/odds-delta.mdx | 2 +- content/es/api-reference/odds.mdx | 16 +++-- content/es/api-reference/sportsbooks.mdx | 2 +- content/es/api-reference/stream.mdx | 10 +-- content/es/concepts/_meta.js | 2 +- .../es/concepts/pinnacle-odds-changed-at.mdx | 65 +++++++----------- content/es/streaming/overview.mdx | 2 +- content/pt-BR/api-reference/events-odds.mdx | 13 ++-- content/pt-BR/api-reference/odds-batch.mdx | 9 ++- content/pt-BR/api-reference/odds-best.mdx | 18 ++--- .../pt-BR/api-reference/odds-comparison.mdx | 21 +++--- content/pt-BR/api-reference/odds-delta.mdx | 2 +- content/pt-BR/api-reference/odds.mdx | 16 +++-- content/pt-BR/api-reference/sportsbooks.mdx | 2 +- content/pt-BR/api-reference/stream.mdx | 10 +-- content/pt-BR/concepts/_meta.js | 2 +- .../concepts/pinnacle-odds-changed-at.mdx | 60 +++++++--------- content/pt-BR/streaming/overview.mdx | 2 +- public/openapi.json | 22 +----- 46 files changed, 280 insertions(+), 377 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cea21e8..f8b85cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ to bump. Every change to API paths or response schemas gets a one-line entry her the [OpenAPI Version Check](.github/workflows/openapi-version-check.yml) CI job enforces that a bump has a matching entry. +## 3.0.0 — 2026-06-02 + +- **BREAKING:** the `Odds` response now exposes a single per-odd `timestamp` field and no longer emits `odds_changed_at`, `last_seen_at`, or `wire_received_at`. `timestamp` is the **delivery / last-refreshed** stamp (advances every ingest cycle — a feed-freshness/liveness signal, matching OpticOdds' `timestamp`), **not** a price-last-changed time. **Migration:** anyone reading `odds_changed_at` / `last_seen_at` / `wire_received_at` should read `timestamp`. Note there is no longer a field for *when the price last moved* (CLV / line-movement) — full OpticOdds-parity. Supersedes the 2.3.0 deprecations. SHA-1048. + ## 2.3.0 — 2026-06-01 - Add `odds_changed_at` to the `Odds` schema — the canonical per-row freshness field (previously undocumented; also the only per-odd freshness timestamp OpticOdds exposes). Deprecate `last_seen_at`, `wire_received_at`, and the stale `timestamp` prop (`deprecated: true`) — being internalized; read `odds_changed_at` for freshness. Removal tracked in sharp-api-go #743. diff --git a/content/de/api-reference/events-odds.mdx b/content/de/api-reference/events-odds.mdx index a7da1a7..75f0332 100644 --- a/content/de/api-reference/events-odds.mdx +++ b/content/de/api-reference/events-odds.mdx @@ -61,8 +61,7 @@ Alle Antworten enthalten Standard-Header für Rate Limit und Metadaten: | `odds.american` | number | American Odds (z. B. -110, +150) | | `odds.decimal` | number | Dezimalquoten (z. B. 1.909) | | `odds.probability` | number | Implizite Wahrscheinlichkeit (z. B. 0.5238) | -| `last_seen_at` | string | ISO-8601-Zeitstempel, wann unsere Pipeline diese Zeile zuletzt beobachtet hat. Verwenden Sie diesen als Aktualitätssignal der Pipeline. | -| `odds_changed_at` | string | ISO-8601-Zeitstempel, wann sich der Preis, die Linie oder das `is_live`-Flag zuletzt tatsächlich geändert hat. Vom Sportsbook bereitgestellt, sofern verfügbar; bei Pinnacle wird er über unveränderte Refreshes hinweg fortgeschrieben — siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO-8601-Zeitpunkt, zu dem SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat — wird in jedem Ingest-Zyklus weitergeschaltet. Ein Feed-Aktualitäts- / Liveness-Signal (entspricht OpticOdds' `timestamp`); es ist NICHT der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. Siehe [`timestamp` verstehen](/de/concepts/pinnacle-odds-changed-at/). | ## Beispielanfragen @@ -221,7 +220,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.556, "odds_probability": 0.643 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_ml_away", @@ -236,7 +235,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 2.55, "odds_probability": 0.392 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "pin_evt_nba_bos_lal_20260208_ml_home", @@ -251,7 +250,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.571, "odds_probability": 0.636 }, - "last_seen_at": "2026-02-08T12:03:00Z" + "timestamp": "2026-02-08T12:03:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_spread_home", @@ -266,7 +265,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_total_over", @@ -281,7 +280,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" } ], "meta": { diff --git a/content/de/api-reference/odds-batch.mdx b/content/de/api-reference/odds-batch.mdx index b9e637a..86b92bd 100644 --- a/content/de/api-reference/odds-batch.mdx +++ b/content/de/api-reference/odds-batch.mdx @@ -140,7 +140,7 @@ if result['data']['missing_events']: "odds_american": -210, "odds_decimal": 1.476, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" }, { "sportsbook": "draftkings", @@ -150,7 +150,7 @@ if result['data']['missing_events']: "odds_american": 175, "odds_decimal": 2.75, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" } ] }, @@ -170,7 +170,7 @@ if result['data']['missing_events']: "odds_american": -130, "odds_decimal": 1.769, "line": null, - "last_seen_at": "2026-01-26T10:15:05.000Z" + "timestamp": "2026-01-26T10:15:05.000Z" } ] } @@ -289,8 +289,7 @@ Jedes Element im `data.events`-Array ist ein Event-Objekt mit verschachtelten Qu | `odds_american` | number | Amerikanische Quoten | | `odds_decimal` | number | Dezimalquoten | | `line` | number \| null | Linienwert | -| `last_seen_at` | string | ISO 8601 Zeitstempel, wann unsere Pipeline diese Zeile zuletzt beobachtet hat. Verwenden Sie dies als Frische-Signal für die Pipeline. | -| `odds_changed_at` | string | ISO 8601 Zeitstempel, wann sich der Preis, die Linie oder das `is_live`-Flag zuletzt tatsächlich geändert haben. Wird vom Sportsbook bereitgestellt, sofern verfügbar; bei Pinnacle wird er über unveränderte Aktualisierungen hinweg übertragen — siehe [Understanding Pinnacle's `odds_changed_at`](/de/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO-8601-Zeitpunkt, zu dem SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat — wird in jedem Ingest-Zyklus weitergeschaltet. Ein Feed-Aktualitäts- / Liveness-Signal (entspricht OpticOdds' `timestamp`); es ist NICHT der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. Siehe [`timestamp` verstehen](/de/concepts/pinnacle-odds-changed-at/). | ## Anwendungsfälle diff --git a/content/de/api-reference/odds-best.mdx b/content/de/api-reference/odds-best.mdx index f80efde..9f39f3d 100644 --- a/content/de/api-reference/odds-best.mdx +++ b/content/de/api-reference/odds-best.mdx @@ -110,32 +110,28 @@ for item in result['data']: "book": "fanduel", "odds": { "american": -105, "decimal": 1.952 }, "edge": 0.007, - "line": -6.5, - "last_seen_at": "2026-01-26T10:30:00.000Z" + "line": -6.5 }, { "book": "draftkings", "odds": { "american": -110, "decimal": 1.909 }, "edge": 0.0, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:55.000Z" + "line": -6.5 }, { "book": "betmgm", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:50.000Z" + "line": -6.5 }, { "book": "pinnacle", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:45.000Z" + "line": -6.5 } ], - "last_seen_at": "2026-01-26T10:30:00.000Z" + "timestamp": "2026-01-26T10:30:00.000Z" } ], "meta": { @@ -211,9 +207,7 @@ X-Request-Id: req_best_789xyz | `all_books[].odds` | object | Odds-Objekt (`american`, `decimal`) | | `all_books[].edge` | number | Edge gegenüber den schlechtesten verfügbaren Quoten (Prozentpunkte) | | `all_books[].line` | number \| null | Linie bei diesem Sportwettenanbieter | -| `all_books[].last_seen_at` | string | Wann unsere Pipeline die Zeile dieses Buches zuletzt beobachtet hat — Aktualitätssignal der Pipeline | -| `all_books[].odds_changed_at` | string | Wann sich der Preis, die Linie oder das `is_live`-Flag dieses Buches zuletzt tatsächlich geändert hat. Bei Pinnacle wird dies über unveränderte Aktualisierungen hinweg fortgeführt — siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/). | -| `last_seen_at` | string | ISO-8601-Zeitstempel der Best-Odds-Bestimmung | +| `timestamp` | string | ISO-8601-Zeitstempel der Best-Odds-Bestimmung | | `player_name` | string\|undefined | Spielername (nur bei Player-Prop-Märkten) | | `stat_category` | string\|undefined | Statistik-Kategorie, z. B. `points`, `rebounds` (nur bei Player-Prop-Märkten) | diff --git a/content/de/api-reference/odds-comparison.mdx b/content/de/api-reference/odds-comparison.mdx index 01e33cf..e176529 100644 --- a/content/de/api-reference/odds-comparison.mdx +++ b/content/de/api-reference/odds-comparison.mdx @@ -127,22 +127,22 @@ for market in event['markets']: "fanduel": { "odds_american": -145, "odds_decimal": 1.690, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "draftkings": { "odds_american": -150, "odds_decimal": 1.667, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "betmgm": { "odds_american": -155, "odds_decimal": 1.645, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": -148, "odds_decimal": 1.676, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "fanduel", @@ -159,22 +159,22 @@ for market in event['markets']: "draftkings": { "odds_american": 130, "odds_decimal": 2.300, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "fanduel": { "odds_american": 125, "odds_decimal": 2.250, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "betmgm": { "odds_american": 128, "odds_decimal": 2.280, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": 126, "odds_decimal": 2.260, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "draftkings", @@ -253,8 +253,7 @@ Jeder Eintrag im `books`-Objekt: |-------|------|-------------| | `odds_american` | number | American Odds | | `odds_decimal` | number | Dezimal-Quoten | -| `last_seen_at` | string | Wann unsere Pipeline die Zeile dieses Buchmachers zuletzt beobachtet hat — Pipeline-Aktualitätssignal | -| `odds_changed_at` | string | Wann sich der Preis, die Linie oder das `is_live`-Flag dieses Buchmachers zuletzt tatsächlich geändert hat. Bei Pinnacle wird dieser Wert über unveränderte Aktualisierungen hinweg fortgeführt — siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO-8601-Zeitpunkt, zu dem SharpAPI die Quote dieses Buchmachers zuletzt durch seine Pipeline aktualisiert hat — wird in jedem Ingest-Zyklus weitergeschaltet. Ein Feed-Aktualitäts- / Liveness-Signal (entspricht OpticOdds' `timestamp`); es ist NICHT der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. Siehe [`timestamp` verstehen](/de/concepts/pinnacle-odds-changed-at/). | ## Hold verstehen @@ -293,7 +292,7 @@ curl "https://api.sharpapi.io/api/v1/odds/comparison?event=33483153&market=sprea ### Veraltete Linien identifizieren -Suchen Sie nach Buchmachern, die ihre Quoten kürzlich nicht aktualisiert haben, indem Sie das `last_seen_at` jedes Buchmachers prüfen. Ein Buchmacher mit veralteten Quoten reagiert möglicherweise langsam auf Anpassungen und schafft so vorübergehenden Wert. +Suchen Sie nach Buchmachern, die ihre Quoten kürzlich nicht aktualisiert haben, indem Sie das `timestamp` jedes Buchmachers prüfen. Ein Buchmacher mit veralteten Quoten reagiert möglicherweise langsam auf Anpassungen und schafft so vorübergehenden Wert. ### Markteffizienz diff --git a/content/de/api-reference/odds-delta.mdx b/content/de/api-reference/odds-delta.mdx index 4efa84e..584379e 100644 --- a/content/de/api-reference/odds-delta.mdx +++ b/content/de/api-reference/odds-delta.mdx @@ -128,7 +128,7 @@ while True: "odds_probability": 0.60, "line": null, "event_start_time": "2026-02-11T19:00:00Z", - "last_seen_at": "2026-02-11T12:00:15.125Z", + "timestamp": "2026-02-11T12:00:15.125Z", "is_live": false, "status": "upcoming" } diff --git a/content/de/api-reference/odds.mdx b/content/de/api-reference/odds.mdx index 9adeead..2dbd608 100644 --- a/content/de/api-reference/odds.mdx +++ b/content/de/api-reference/odds.mdx @@ -20,6 +20,10 @@ Erfordert einen API key. Verfügbar für **alle Tarife**. Welche Sportwettenanbieter in Ihren Ergebnissen zurückgegeben werden, hängt von Ihrem Abonnement-Tarif ab. Nutzer des Free-Tarifs erhalten ausschließlich Quoten von DraftKings und FanDuel. Siehe [Anbieterzugang nach Tarif](#book-access-by-tier) weiter unten. + +Geändert in v3.0.0: Die Quotenantwort führt jetzt ein einziges `timestamp`-Feld (Auslieferung / Feed-Aktualität, passend zu OpticOdds). Die früheren Felder `odds_changed_at`, `last_seen_at` und `wire_received_at` wurden entfernt — lesen Sie stattdessen `timestamp`. Es gibt kein Feld mehr dafür, wann sich der Preis zuletzt bewegt hat. + + ## Query-Parameter | Parameter | Typ | Standard | Beschreibung | @@ -195,7 +199,7 @@ Cursor sind undurchsichtig — parsen oder konstruieren Sie sie nicht. Sie kodie "odds_probability": 0.60, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false }, { @@ -214,7 +218,7 @@ Cursor sind undurchsichtig — parsen oder konstruieren Sie sie nicht. Sie kodie "odds_probability": 0.4348, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false } ], @@ -314,9 +318,7 @@ X-Request-Id: req_abc123def456 | `line` | number \| null | Spread- oder Total-Linienwert (`null` bei Moneyline) | | `is_alternate_line` | boolean\|undefined | `true`, wenn das `line` dieser Zeile von der kanonischen Hauptlinie für ihre `(event, market_type, player)`-Gruppe abweicht. Immer `false` für Märkte ohne Linie (Moneyline, Outright). Stabil auf [`/opportunities/ev`](/de/api-reference/opportunities-ev/) heute; Rollout auf `/odds`-Zeilen läuft. Verwenden Sie es, um Haupt- und Alternativlinien-Snapshots zu trennen. | | `event_start_time` | string | ISO 8601 Event-Startzeit | -| `last_seen_at` | string | ISO 8601 Zeitstempel der letzten Beobachtung dieser Zeile durch unseren Adapter. Wird in jedem Ingest-Zyklus aktualisiert — dies ist das Pipeline-Frische-Signal. | -| `odds_changed_at` | string | ISO 8601 Zeitstempel der quelleneigenen Aktualisierung des Sportwettenanbieters für diese Linie, sofern verfügbar. Bei Pinnacle wird er fortgeführt, solange Preis/Linie/`is_live`-Flag unverändert bleiben (siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/)). Verwenden Sie `last_seen_at` für die Pipeline-Frische. | -| `wire_received_at` | string\|undefined | ISO 8601 Zeitstempel des Zeitpunkts, an dem sharp-api-go zuletzt eine Inhaltshash-Änderung für diese Zeile beobachtet hat — der Pipeline-Eingangsstempel. Unterschiedlich von `last_seen_at` (Adapter-Beobachtung) und `odds_changed_at` (quelleneigene Aktualisierung des Sportwettenanbieters). | +| `timestamp` | string | ISO-8601-Zeitpunkt, zu dem SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat — wird in jedem Ingest-Zyklus weitergeschaltet. Ein Feed-Aktualitäts- / Liveness-Signal (entspricht OpticOdds' `timestamp`); es ist NICHT der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. | | `is_live` | boolean | Ob das Event derzeit live läuft | | `event_uuid` | string\|undefined | Stabile kanonische Event-UUID aus dem SharpAPI-Atlas, sofern das Event gemappt ist. Während `event_id` die primäre Event-Kennung des Adapters trägt (oft die des ursprünglichen Sportwettenanbieters), ist `event_uuid` ein feed-stabiler Hash für Cross-Feed-Joins. Fehlt bei nicht gemappten Events. | | `external_event_id` | string\|undefined | Die native Event-ID des Sportwettenanbieters, sofern sie sich von `event_id` unterscheidet. Nützlich, um Zeilen in die UI oder API des Sportwettenanbieters zurückzuverknüpfen. | @@ -377,7 +379,7 @@ curl "https://api.sharpapi.io/api/v1/odds?sort=event_start_time" \ -H "X-API-Key: YOUR_API_KEY" ``` -Gültige Sortierfelder: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `last_seen_at`, `sportsbook`, `league`, `sport`. +Gültige Sortierfelder: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `timestamp`, `sportsbook`, `league`, `sport`. ## Feldauswahl @@ -447,7 +449,7 @@ curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \ "odds_decimal": 1.667, "odds_probability": 0.60, "line": null, - "last_seen_at": "2026-01-26T02:10:24.125Z" + "timestamp": "2026-01-26T02:10:24.125Z" } ] } diff --git a/content/de/api-reference/sportsbooks.mdx b/content/de/api-reference/sportsbooks.mdx index e169e23..cae95c8 100644 --- a/content/de/api-reference/sportsbooks.mdx +++ b/content/de/api-reference/sportsbooks.mdx @@ -400,7 +400,7 @@ Das Feld `requires_tier` gibt die Mindest-Abonnementstufe an, die benötigt wird {/* AUTO:END:sharp-books */} -**Pinnacle-Zeitstempel lesen.** `odds_changed_at` in einer Pinnacle-Zeile ist der Zeitstempel ihres Trading-Desks, nicht der unserer Pipeline. Pinnacle hält die Linien stabil, wenn sich der Markt nicht bewegt hat — ein Leerlaufwert von 30+ Minuten ist bei MLB-Spieler-Props und NBA-Märkten üblich. Verwenden Sie `last_seen_at` für die Pipeline-Aktualität. Siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/) dafür, was "veraltet" in ihrem Feed tatsächlich bedeutet. +**Pinnacle-Zeitstempel lesen.** `timestamp` in einer Pinnacle-Zeile ist der Auslieferungs- / Feed-Aktualitätsstempel — wann SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat —, nicht der Zeitpunkt, zu dem sich der Preis zuletzt bewegt hat. Pinnacle hält die Linien stabil, wenn sich der Markt nicht bewegt hat, aber `timestamp` wird trotzdem in jedem Ingest-Zyklus weitergeschaltet. Siehe [`timestamp` verstehen](/de/concepts/pinnacle-odds-changed-at/) dafür, wie SharpAPI Feed-Aktualität bereitstellt. ### International diff --git a/content/de/api-reference/stream.mdx b/content/de/api-reference/stream.mdx index b565b1a..8a0bd35 100644 --- a/content/de/api-reference/stream.mdx +++ b/content/de/api-reference/stream.mdx @@ -87,7 +87,7 @@ Jedes Quotenobjekt im Snapshot enthält **alle Felder** — dies ist die vollst ``` event: snapshot id: evt_00001 -data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"last_seen_at":"2026-02-08T18:47:20Z","odds_changed_at":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} +data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"timestamp":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} ``` | Feld | Typ | Beschreibung | @@ -113,13 +113,13 @@ data: {"status":"ready","books":["draftkings","fanduel"],"total_odds":3200} Wird ausgelöst, wenn sich die Quoten für ein Sportsbook ändern. Wird nur auf den Channels `odds` oder `all` gesendet. -**Kompakte Delta-Payload.** Delta-Events enthalten nur Felder, die sich zwischen Updates ändern können — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` und `odds_changed_at`. Statische Felder wie `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` und `event_start_time` sind in Deltas **nicht enthalten**. Führen Sie jedes Delta in Ihre lokale Quoten-Map über die `id` zusammen, indem Sie die im initialen `snapshot` empfangenen vollständigen Objekte verwenden. Siehe [Migration: Kompakte SSE-Deltas](#migration-compact-sse-deltas) unten. +**Kompakte Delta-Payload.** Delta-Events enthalten nur Felder, die sich zwischen Updates ändern können — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` und `timestamp`. Statische Felder wie `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` und `event_start_time` sind in Deltas **nicht enthalten**. Führen Sie jedes Delta in Ihre lokale Quoten-Map über die `id` zusammen, indem Sie die im initialen `snapshot` empfangenen vollständigen Objekte verwenden. Siehe [Migration: Kompakte SSE-Deltas](#migration-compact-sse-deltas) unten. ``` event: odds:update id: evt_00042 -data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"odds_changed_at":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} +data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"timestamp":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} ``` **Felder des Delta-Objekts (`OddsDelta`):** @@ -132,7 +132,7 @@ data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_pr | `odds_probability` | number | Aktualisierte implizite Wahrscheinlichkeit (z. B. `0.6`) | | `line` | number \| null | Aktualisierte Line/Spread (z. B. `-3.5`) oder `null` für Moneyline | | `is_live` | boolean | Ob das Event derzeit live ist | -| `odds_changed_at` | string | ISO-8601-Zeitstempel des sportsbook-eigenen Quellupdates für diese Line, sofern verfügbar. Bei Pinnacle wird dieser Wert weitergeführt, solange der zugrunde liegende Preis/die Line/das `is_live`-Flag unverändert bleiben — siehe [Pinnacles `odds_changed_at` verstehen](/de/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO-8601-Zeitpunkt, zu dem SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat — wird in jedem Ingest-Zyklus weitergeschaltet. Ein Feed-Aktualitäts- / Liveness-Signal (entspricht OpticOdds' `timestamp`); es ist NICHT der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. Siehe [`timestamp` verstehen](/de/concepts/pinnacle-odds-changed-at/). | **Envelope-Felder:** @@ -570,7 +570,7 @@ Diese schließen die Verbindung. Behandeln Sie sie in `onerror`: ## Migration: Kompakte SSE-Deltas -**Breaking Change für SSE-`odds:update`-Konsumenten.** Das `odds:update`-Event sendet jetzt kompakte `OddsDelta`-Objekte, die nur dynamische Felder enthalten (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Statische Felder wie `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` und `event_start_time` werden nur im initialen `snapshot`-Event gesendet. +**Breaking Change für SSE-`odds:update`-Konsumenten.** Das `odds:update`-Event sendet jetzt kompakte `OddsDelta`-Objekte, die nur dynamische Felder enthalten (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Statische Felder wie `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` und `event_start_time` werden nur im initialen `snapshot`-Event gesendet. **Hintergrund:** Die vorherige Payload sendete bei jeder Änderung das vollständige `Odds`-Objekt und erzeugte ~170 KB/s pro Verbindung. Das kompakte Delta reduziert die Bandbreite um etwa das Fünffache, indem nur die 6-7 Felder gesendet werden, die sich tatsächlich geändert haben. diff --git a/content/de/concepts/_meta.js b/content/de/concepts/_meta.js index 08773b9..54a0fc4 100644 --- a/content/de/concepts/_meta.js +++ b/content/de/concepts/_meta.js @@ -5,6 +5,6 @@ export default { "event-matching": "Event-Zuordnung", "entity-reference-ids": "Entitätsreferenz-IDs", "live-vs-prematch": "Live vs. Pre-Match", - "pinnacle-odds-changed-at": "Pinnacle `odds_changed_at`", + "pinnacle-odds-changed-at": "Das Feld `timestamp`", "polymarket-resolution": "Polymarket-Auflösung", } diff --git a/content/de/concepts/pinnacle-odds-changed-at.mdx b/content/de/concepts/pinnacle-odds-changed-at.mdx index c938160..9ad2251 100644 --- a/content/de/concepts/pinnacle-odds-changed-at.mdx +++ b/content/de/concepts/pinnacle-odds-changed-at.mdx @@ -1,24 +1,30 @@ --- -description: "Wie sich das Feld odds_changed_at von Pinnacle verhält — warum es der Zeitstempel des Trading-Desks ist, warum es bei MLB und NBA veraltet wirken kann und wie es zusammen mit last_seen_at als Pipeline-Aktualitätssignal zu lesen ist." +description: "Wie sich das Feld timestamp verhält — warum es das Auslieferungs- / Feed-Aktualitätssignal ist (entspricht OpticOdds), warum es in jedem Refresh-Zyklus weitergeschaltet wird und warum SharpAPI kein separates Feld mehr dafür bereitstellt, wann sich der Preis zuletzt bewegt hat." --- import { Callout } from 'nextra/components' -# Pinnacles `odds_changed_at` verstehen +# Das Feld `timestamp` verstehen -Sharp-Kunden, die +EV- und Arbitrage-Tools gegen Pinnacle entwickeln, stellen häufig dieselbe Frage: „Warum sieht `odds_changed_at` in dieser Pinnacle-Zeile 20 Minuten alt aus?" Die kurze Antwort lautet, dass es wie vorgesehen funktioniert — es enthält Pinnacles eigenen Trading-Desk-Zeitstempel, nicht unseren. Diese Seite erklärt, was das Feld tatsächlich erfasst, warum es lange Zeit unverändert bleiben kann und wie Sie es mit `last_seen_at` kombinieren, um eine saubere Sicht auf die Pipeline-Aktualität zu erhalten. +Jede Quotenzeile in der SharpAPI-Antwort trägt ein einziges `timestamp`-Feld. Es beantwortet eine Frage: *Wie frisch ist dieser Wert in unserer Pipeline?* Diese Seite erklärt, was `timestamp` tatsächlich erfasst, warum es in jedem Refresh-Zyklus weitergeschaltet wird und warum SharpAPI kein separates Feld mehr dafür bereitstellt, „wann sich der Preis zuletzt geändert hat". -## Was `odds_changed_at` tatsächlich bedeutet +## Was `timestamp` tatsächlich bedeutet -Bei Pinnacle-Zeilen ist `odds_changed_at` **Pinnacles eigener Trading-Desk-Zeitstempel** — wann Pinnacle diese spezifische Linie zuletzt neu bepreist hat. +`timestamp` ist der ISO-8601-Zeitpunkt, zu dem SharpAPI diese Quote zuletzt durch seine Pipeline aktualisiert hat. Es ist ein **Auslieferungs- / Feed-Aktualitätssignal** — es wird bei jedem Ingest-Zyklus weitergeschaltet, in dem die Zeile beobachtet wurde, unabhängig davon, ob sich der zugrunde liegende Preis bewegt hat. -Er wird unverändert weitergegeben, wann immer Pinnacle signalisiert, dass sich Preis, Linie und das `is_live`-Flag eines Marktes nicht verändert haben. Intern hasht SharpAPI diese drei Felder für jede Quotenzeile bei jedem Refresh; wenn der Hash mit dem vorherigen Snapshot identisch ist, behalten wir den vorherigen `odds_changed_at` bei, anstatt ihn mit dem Beobachtungszeitpunkt zu überschreiben. Dies bewahrt die Semantik „wann hat sich diese Linie zuletzt bewegt" über wiederholte Abfragen eines unveränderten Marktes hinweg. +Dies entspricht dem `timestamp`-Feld von OpticOdds: Es ist ein Liveness-Indikator, kein Preisbewegungs-Indikator. Ein frisches `timestamp` bedeutet, dass der Feed aktiv ist und die Zeile aktuell ist; ein veraltetes `timestamp` bedeutet, dass die Pipeline diese Zeile eine Weile nicht mehr gesehen hat und eine Untersuchung wert ist. -`odds_changed_at` ist **nicht** der Zeitpunkt, zu dem unsere Pipeline diese Zeile zuletzt aktualisiert oder berührt hat. Für die Pipeline-Aktualität verwenden Sie `last_seen_at`. +`timestamp` ist **nicht** der Zeitpunkt, zu dem sich der Preis zuletzt geändert hat. SharpAPI stellt kein separates Feld mehr dafür bereit, wann sich Preis, Linie oder das `is_live`-Flag zuletzt bewegt haben. Behandeln Sie `timestamp` ausschließlich als Aktualitäts- / Liveness-Signal. -## Warum es veraltet wirken kann +## Warum es kein separates „Preisänderungs"-Feld mehr gibt + +Frühere API-Versionen stellten mehrere Zeitstempel pro Zeile bereit (`odds_changed_at`, `last_seen_at`, `wire_received_at`), die versuchten, „wann sich der Preis bewegt hat" von „wann wir die Zeile gesehen haben" zu unterscheiden. In der Praxis war diese Unterscheidung über alle Buchmacher hinweg unzuverlässig: Nur wenige Quellen liefern einen vertrauenswürdigen quelleneigenen Preisänderungs-Zeitstempel, und die Übertragung dieser Werte über unveränderte Refreshes hinweg führte zu Verwirrung — insbesondere bei Sharp-Büchern wie Pinnacle, die Linien lange Zeit konstant halten. + +Ab v3.0.0 konsolidiert SharpAPI auf ein einziges `timestamp`-Feld mit klarer Auslieferungs-/Aktualitätssemantik und entspricht damit dem Verhalten von OpticOdds. Wenn Sie auf eines der entfernten Felder angewiesen waren, lesen Sie stattdessen `timestamp`. + +## Warum ein frisches `timestamp` nicht „Preis hat sich bewegt" bedeutet Pinnacle ist ein Market-Maker. Deren Trading-Desk veröffentlicht nur dann einen neuen Preis, wenn tatsächlicher Flow eine Neubepreisung erzwingt — sie schattieren keine Linien um Retail-Action, um Marge herauszupressen, wie es Soft Books tun. Diese Disziplin ist der Grund, warum Pinnacle als Sharp-Referenz für +EV-Berechnungen verwendet wird, aber es bedeutet auch, dass Linien lange Zeit unverändert bleiben können. @@ -32,22 +38,9 @@ Beobachtet über ein 24-Stunden-Fenster von Pinnacles eigenen CDN-Antworten vari | MLB | ~18 % | | NBA | ~9 % | -NBA- und MLB-Spielerprops zeigen häufig lange Leerlaufzeiten — 30+ Minuten sind nicht ungewöhnlich — weil Pinnacles Trading-Desk die Linie nicht bewegt. Wenn Sie ein altes `odds_changed_at` bei einem NBA- oder MLB-Markt sehen, ist es fast immer Pinnacles eigener Veröffentlichungstakt und keine Lücke in unserer Pipeline. - -## Wie die Felder gemeinsam zu lesen sind - -Jede Quotenzeile enthält zwei Zeitstempel. Sie beantworten unterschiedliche Fragen: - -| Feld | Was es Ihnen sagt | -|--------------------|----------------------------------------------------------------------| -| `odds_changed_at` | Wann Pinnacles Trading-Desk diese Linie zuletzt bewegt hat | -| `last_seen_at` | Wann unsere Pipeline diese Zeile zuletzt beobachtet hat | - -Für Pipeline-Aktualitätsprüfungen verwenden Sie `last_seen_at` — dieser wird bei jeder Aufnahme der Zeile aktualisiert, unabhängig davon, ob sich der Preis bewegt hat. - -Für „wann hat Pinnacle diese Linie zuletzt bewegt" verwenden Sie `odds_changed_at`. +NBA- und MLB-Spielerprops zeigen häufig lange Zeiträume, in denen der Preis konstant bleibt — 30+ Minuten sind nicht ungewöhnlich — weil Pinnacles Trading-Desk die Linie nicht bewegt. Während dieser Phasen wird `timestamp` trotzdem in jedem Ingest-Zyklus weitergeschaltet: Der Feed ist aktiv, auch wenn sich der Preis nicht ändert. Ein frisches `timestamp` bestätigt, dass die Zeile aktuell ist, nicht dass sich der Preis gerade bewegt hat. -Eine große Lücke zwischen beiden (frisches `last_seen_at`, altes `odds_changed_at`) bedeutet, dass Pinnacle die Linie konstant hält. Dies ist normal und die mit Abstand häufigste Verwirrungsquelle beim Lesen von Pinnacle-Daten. +## Wie `timestamp` zu lesen ist ```json { @@ -56,24 +49,23 @@ Eine große Lücke zwischen beiden (frisches `last_seen_at`, altes `odds_changed "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" + "timestamp": "2026-04-21T21:35:02Z" } ``` -In diesem Beispiel hat die Pipeline diese Zeile 4 Sekunden vor dem Abruf durch den Client gesehen (`last_seen_at` ist frisch). Der Preis selbst hat sich zuletzt 2h 46m früher bewegt (`odds_changed_at`), weil Pinnacles Trading-Desk Sosas Total-Bases-Linie seit Vormarkteröffnung nicht neu bepreist hat. Beide Werte sind korrekt. +In diesem Beispiel hat die Pipeline diese Zeile wenige Sekunden vor dem Abruf durch den Client aktualisiert (`timestamp` ist frisch). Der angezeigte Preis ist aktuell — Pinnacles Trading-Desk hat Sosas Total-Bases-Linie möglicherweise seit Stunden nicht neu bepreist, aber der Feed liefert sie weiterhin aktiv aus. -Wenn `last_seen_at` veraltet ist (mehr als eine oder zwei Minuten alt bei einem Major-League-Markt), ist das ein Pipeline-Signal, das eine Untersuchung wert ist. Wenn `odds_changed_at` veraltet ist, aber `last_seen_at` frisch, hält Pinnacle die Linie — behandeln Sie den angezeigten Preis als aktuell. +Wenn `timestamp` veraltet ist (mehr als eine oder zwei Minuten alt bei einem Major-League-Markt), ist das ein Pipeline-Signal, das eine Untersuchung wert ist. Wenn `timestamp` frisch ist, behandeln Sie den angezeigten Preis als aktuell — auch dann, wenn Pinnacle die Linie über einen langen Zeitraum konstant gehalten hat. ## Warum Pinnacle anders ist -Pinnacle akzeptiert Sharp-Action und bepreist basierend auf echtem Flow neu, anstatt Linien um Retail-Wetter zu schattieren. Diese Market-Maker-Disziplin ist der Grund, warum wir sie als Devig-Referenz für +EV verwenden — ihre Linien sind dem fairen Preis am Markt am nächsten. Der Kompromiss ist, dass Pre-Match-Linien lange Zeit unverändert bleiben können, wenn sich nichts am Markt bewegt hat, was für jeden, der die ständige Mikro-Anpassung erwartet, die Soft Books vornehmen, wie Veraltetheit aussieht. +Pinnacle akzeptiert Sharp-Action und bepreist basierend auf echtem Flow neu, anstatt Linien um Retail-Wetter zu schattieren. Diese Market-Maker-Disziplin ist der Grund, warum wir sie als Devig-Referenz für +EV verwenden — ihre Linien sind dem fairen Preis am Markt am nächsten. Der Kompromiss ist, dass Pre-Match-Linien lange Zeit unverändert bleiben können, wenn sich nichts am Markt bewegt hat. Da `timestamp` ausschließlich Feed-Aktualität misst, ist das kein Problem: Ein frisches `timestamp` bei einer seit Stunden stabilen Pinnacle-Linie ist genau das erwartete Verhalten. ## Verwandte Themen -- [Odds-Snapshot](/de/api-reference/odds/) — Felder `odds_changed_at` und `last_seen_at` in der REST-Odds-Antwort -- [Streaming](/de/api-reference/stream/) — `odds_changed_at` bei `odds:update`-Deltas +- [Odds-Snapshot](/de/api-reference/odds/) — das Feld `timestamp` in der REST-Odds-Antwort +- [Streaming](/de/api-reference/stream/) — `timestamp` bei `odds:update`-Deltas - [Live vs. Pre-Match](/de/concepts/live-vs-prematch/) — Veröffentlichungstakt und Lieferungsmechanismen der Buchmacher - [EV-Berechnung](/de/concepts/ev-calculation/) — warum Pinnacle die Sharp-Referenz ist diff --git a/content/de/streaming/overview.mdx b/content/de/streaming/overview.mdx index 2285211..c490a54 100644 --- a/content/de/streaming/overview.mdx +++ b/content/de/streaming/overview.mdx @@ -188,7 +188,7 @@ for event in client.events(): | `connected` | Stream aufgebaut, gibt Stream-ID, aktive Filter und Kanäle zurück | | `snapshot` / `opportunities_snapshot` | Vollständiger Daten-Dump für Quoten/Opportunitäten (alle Felder) | | `snapshot:complete` | Alle initialen Daten wurden gesendet | -| `odds:update` | Kompaktes Delta — nur dynamische Felder (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Per `id` in den Snapshot-Zustand einfügen. | +| `odds:update` | Kompaktes Delta — nur dynamische Felder (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Per `id` in den Snapshot-Zustand einfügen. | | `odds:removed` | Quoten von einem Sportsbook entfernt | | `ev:detected` | Neue +EV-Opportunität gefunden | | `ev:expired` | +EV-Opportunität nicht mehr verfügbar | diff --git a/content/en/api-reference/events-odds.mdx b/content/en/api-reference/events-odds.mdx index 2d2d4fa..9b71ad9 100644 --- a/content/en/api-reference/events-odds.mdx +++ b/content/en/api-reference/events-odds.mdx @@ -61,8 +61,7 @@ All responses include standard rate limit and metadata headers: | `odds.american` | number | American odds (e.g., -110, +150) | | `odds.decimal` | number | Decimal odds (e.g., 1.909) | | `odds.probability` | number | Implied probability (e.g., 0.5238) | -| `last_seen_at` | string | ISO 8601 timestamp when our pipeline last observed this row. Use this as your pipeline freshness signal. | -| `odds_changed_at` | string | ISO 8601 timestamp of when the price, line, or `is_live` flag last actually changed. Sportsbook-provided when available; on Pinnacle it carries forward across unchanged refreshes — see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/). | ## Example Requests @@ -221,7 +220,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.556, "odds_probability": 0.643 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_nba_celtics_lakers_2026-02-08_b3_ml_away", @@ -236,7 +235,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 2.55, "odds_probability": 0.392 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "pin_nba_celtics_lakers_2026-02-08_b3_ml_home", @@ -251,7 +250,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.571, "odds_probability": 0.636 }, - "last_seen_at": "2026-02-08T12:03:00Z" + "timestamp": "2026-02-08T12:03:00Z" }, { "id": "dk_nba_celtics_lakers_2026-02-08_b3_spread_home", @@ -266,7 +265,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_nba_celtics_lakers_2026-02-08_b3_total_over", @@ -281,7 +280,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" } ], "meta": { diff --git a/content/en/api-reference/odds-batch.mdx b/content/en/api-reference/odds-batch.mdx index 085e7b1..0f4e443 100644 --- a/content/en/api-reference/odds-batch.mdx +++ b/content/en/api-reference/odds-batch.mdx @@ -140,7 +140,7 @@ if result['data']['missing_events']: "odds_american": -210, "odds_decimal": 1.476, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" }, { "sportsbook": "draftkings", @@ -150,7 +150,7 @@ if result['data']['missing_events']: "odds_american": 175, "odds_decimal": 2.75, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" } ] }, @@ -170,7 +170,7 @@ if result['data']['missing_events']: "odds_american": -130, "odds_decimal": 1.769, "line": null, - "last_seen_at": "2026-01-26T10:15:05.000Z" + "timestamp": "2026-01-26T10:15:05.000Z" } ] } @@ -289,8 +289,7 @@ Each item in the `data.events` array is an event object with nested odds: | `odds_american` | number | American odds | | `odds_decimal` | number | Decimal odds | | `line` | number \| null | Line value | -| `last_seen_at` | string | **⚠️ Deprecated** — being internalized; will be removed in a future release. Liveness heartbeat (advances every cycle even when the price is unchanged), not a price-freshness signal. Read `odds_changed_at` for freshness. | -| `odds_changed_at` | string | ISO 8601 timestamp of when the price, line, or `is_live` flag last actually changed. Sportsbook-provided when available; on Pinnacle it carries forward across unchanged refreshes — see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/). | ## Use Cases diff --git a/content/en/api-reference/odds-best.mdx b/content/en/api-reference/odds-best.mdx index 08523f7..e86f54b 100644 --- a/content/en/api-reference/odds-best.mdx +++ b/content/en/api-reference/odds-best.mdx @@ -111,32 +111,28 @@ for item in result['data']: "book": "fanduel", "odds": { "american": -105, "decimal": 1.952 }, "edge": 0.007, - "line": -6.5, - "last_seen_at": "2026-01-26T10:30:00.000Z" + "line": -6.5 }, { "book": "draftkings", "odds": { "american": -110, "decimal": 1.909 }, "edge": 0.0, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:55.000Z" + "line": -6.5 }, { "book": "betmgm", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:50.000Z" + "line": -6.5 }, { "book": "pinnacle", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:45.000Z" + "line": -6.5 } ], - "last_seen_at": "2026-01-26T10:30:00.000Z" + "timestamp": "2026-01-26T10:30:00.000Z" } ], "meta": { @@ -213,9 +209,7 @@ X-Request-Id: req_best_789xyz | `all_books[].odds` | object | Odds object (`american`, `decimal`) | | `all_books[].edge` | number | Edge over the worst available odds (percentage points) | | `all_books[].line` | number \| null | Line at this sportsbook | -| `all_books[].last_seen_at` | string | When our pipeline last observed this book's row — pipeline freshness signal | -| `all_books[].odds_changed_at` | string | When this book's price, line, or `is_live` flag last actually changed. On Pinnacle, carries forward across unchanged refreshes — see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/). | -| `last_seen_at` | string | **⚠️ Deprecated** — being internalized; will be removed in a future release. Liveness heartbeat for the row (advances every cycle even when the price is unchanged), not a price-freshness signal. Read `odds_changed_at` for freshness. | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. | | `player_name` | string\|undefined | Player name (player prop markets only) | | `stat_category` | string\|undefined | Stat category, e.g. `points`, `rebounds` (player prop markets only) | diff --git a/content/en/api-reference/odds-comparison.mdx b/content/en/api-reference/odds-comparison.mdx index b31dde1..b41a5df 100644 --- a/content/en/api-reference/odds-comparison.mdx +++ b/content/en/api-reference/odds-comparison.mdx @@ -127,22 +127,22 @@ for market in event['markets']: "fanduel": { "odds_american": -145, "odds_decimal": 1.690, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "draftkings": { "odds_american": -150, "odds_decimal": 1.667, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "betmgm": { "odds_american": -155, "odds_decimal": 1.645, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": -148, "odds_decimal": 1.676, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "fanduel", @@ -159,22 +159,22 @@ for market in event['markets']: "draftkings": { "odds_american": 130, "odds_decimal": 2.300, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "fanduel": { "odds_american": 125, "odds_decimal": 2.250, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "betmgm": { "odds_american": 128, "odds_decimal": 2.280, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": 126, "odds_decimal": 2.260, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "draftkings", @@ -253,8 +253,7 @@ Each entry in the `books` object: |-------|------|-------------| | `odds_american` | number | American odds | | `odds_decimal` | number | Decimal odds | -| `last_seen_at` | string | **⚠️ Deprecated** — being internalized; will be removed in a future release. Liveness heartbeat (advances every cycle even when the price is unchanged), not a price-freshness signal. Read `odds_changed_at` for freshness. | -| `odds_changed_at` | string | When this book's price, line, or `is_live` flag last actually changed. On Pinnacle, carries forward across unchanged refreshes — see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/). | ## Understanding Hold @@ -293,7 +292,7 @@ curl "https://api.sharpapi.io/api/v1/odds/comparison?event=33483153&market=sprea ### Identifying Stale Lines -Look for books that haven't updated recently by checking each book's `last_seen_at`. A book with stale odds may be slow to adjust, creating temporary value. +Look for books that haven't updated recently by checking each book's `timestamp`. A book with stale odds may be slow to adjust, creating temporary value. ### Market Efficiency diff --git a/content/en/api-reference/odds-delta.mdx b/content/en/api-reference/odds-delta.mdx index f9d10e0..e635d2f 100644 --- a/content/en/api-reference/odds-delta.mdx +++ b/content/en/api-reference/odds-delta.mdx @@ -128,7 +128,7 @@ while True: "odds_probability": 0.60, "line": null, "event_start_time": "2026-02-11T19:00:00Z", - "last_seen_at": "2026-02-11T12:00:15.125Z", + "timestamp": "2026-02-11T12:00:15.125Z", "is_live": false, "status": "upcoming" } diff --git a/content/en/api-reference/odds.mdx b/content/en/api-reference/odds.mdx index 6f54b3e..08f6d1a 100644 --- a/content/en/api-reference/odds.mdx +++ b/content/en/api-reference/odds.mdx @@ -12,6 +12,10 @@ Get a snapshot of current odds from sportsbooks. GET /api/v1/odds ``` + +**Changed in v3.0.0:** the odds response now carries a single `timestamp` field (delivery / feed-freshness, matching OpticOdds). The former `odds_changed_at`, `last_seen_at`, and `wire_received_at` fields have been removed — read `timestamp` instead. There is no longer a field for when the price last moved. + + ## Authentication Requires API key. Available to **all tiers**. @@ -199,9 +203,7 @@ The example below shows the flat fields only. As of May 2026, every row also car "is_main_line": true, "is_alternate_line": false, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", - "wire_received_at": "2026-01-26T02:10:24.087Z", - "odds_changed_at": "2026-01-26T02:09:51.000Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false }, { @@ -222,9 +224,7 @@ The example below shows the flat fields only. As of May 2026, every row also car "is_main_line": true, "is_alternate_line": false, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", - "wire_received_at": "2026-01-26T02:10:24.087Z", - "odds_changed_at": "2026-01-26T02:09:51.000Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false } ], @@ -325,9 +325,7 @@ X-Request-Id: req_abc123def456 | `is_alternate_line` | boolean | `true` when this row's `line` differs from the canonical main line for its `(event, market_type, selection)` group. `false` for the consensus main line, for no-line markets (moneyline, outright), and for rows whose cohort hasn't been published yet (cold start, brand-new event). See `is_main_line` for the positive-polarity sibling that disambiguates "main" from "cohort-pending". | | `is_main_line` | boolean | `true` when this row's `line` equals the canonical main line for its `(event, market_type, selection)` group, AND for no-line markets (moneyline, outright — always main by definition). `false` for alt-line rows and for rows whose cohort hasn't been published yet. **Mutually exclusive with `is_alternate_line`:** both true never coexists; both false is the cohort-pending state. Filter for `is_main_line=true` when you want a positive "main lines only" view that excludes cohort-pending rows. Also accepted as a query filter on [`/odds/best?is_main_line=true`](/en/api-reference/odds-best/). | | `event_start_time` | string | ISO 8601 event start time | -| `last_seen_at` | string | **⚠️ Deprecated** — being internalized; will be removed in a future release. Liveness heartbeat: advances every ingest cycle even when the price is unchanged, so it is *not* a price-freshness signal. Read `odds_changed_at` for freshness. | -| `wire_received_at` | string\|undefined | **⚠️ Deprecated** — being internalized; will be removed in a future release. SharpAPI pipeline-arrival stamp for ingest-latency benchmarking only — not a betting signal. Read `odds_changed_at` for price freshness. | -| `odds_changed_at` | string | **The freshness field to read.** Best-available last-price-change time: the sportsbook's own source-update timestamp when provided, otherwise when SharpAPI first detected a price/line/`is_live` change — carried forward across unchanged refreshes (see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/)). | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/). | | `is_live` | boolean | Whether the event is currently live | | `is_active` | boolean | `true` (default) = market open and bettable; `false` = market suspended/closed with the price **frozen** at its last value (so you can grey it out rather than trust a stale price). Mirrors OpticOdds' `locked-odds`, but as a queryable field you can also filter on. Absent is treated as `true`. An active→suspended transition is pushed on the [odds stream](/en/api-reference/stream/) as an `odds:update` carrying `is_active: false`. | | `event_uuid` | string\|undefined | Stable canonical event UUID from the SharpAPI atlas, when the event is mapped. Where `event_id` carries the adapter's primary event identifier (often the originating sportsbook's), `event_uuid` is a feed-stable hash you can use for cross-feed joins. Absent for unmapped events. | @@ -445,7 +443,7 @@ curl "https://api.sharpapi.io/api/v1/odds?sort=event_start_time" \ -H "X-API-Key: YOUR_API_KEY" ``` -Valid sort fields: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `last_seen_at`, `sportsbook`, `league`, `sport`. +Valid sort fields: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `timestamp`, `sportsbook`, `league`, `sport`. ## Field Selection @@ -515,7 +513,7 @@ curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \ "odds_decimal": 1.667, "odds_probability": 0.60, "line": null, - "last_seen_at": "2026-01-26T02:10:24.125Z" + "timestamp": "2026-01-26T02:10:24.125Z" } ] } diff --git a/content/en/api-reference/sportsbooks.mdx b/content/en/api-reference/sportsbooks.mdx index 26f0d77..efe3ba4 100644 --- a/content/en/api-reference/sportsbooks.mdx +++ b/content/en/api-reference/sportsbooks.mdx @@ -414,7 +414,7 @@ The `requires_tier` field indicates the minimum subscription tier needed to acce {/* AUTO:END:sharp-books */} -**Reading Pinnacle timestamps.** `odds_changed_at` on a Pinnacle row is their trading-desk timestamp, not our pipeline's. Pinnacle holds lines steady when the market has not moved — an idle value of 30+ minutes is common on MLB player props and NBA markets. Use `last_seen_at` for pipeline freshness. See [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/) for what "stale" actually means on their feed. +**Reading Pinnacle timestamps.** Each odds row carries a single `timestamp` field — the time SharpAPI last refreshed that row through its pipeline (feed-freshness, matching OpticOdds), which advances every ingest cycle even when Pinnacle holds the line steady. It is *not* when the price last moved; SharpAPI no longer exposes a separate "when the price last changed" field. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/) for what "stale" actually means on their feed. ### International diff --git a/content/en/api-reference/stream.mdx b/content/en/api-reference/stream.mdx index f47431a..224d96e 100644 --- a/content/en/api-reference/stream.mdx +++ b/content/en/api-reference/stream.mdx @@ -87,7 +87,7 @@ Each odds object in the snapshot contains **all fields** — this is the full `O ``` event: snapshot id: evt_00001 -data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"last_seen_at":"2026-02-08T18:47:20Z","odds_changed_at":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} +data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"timestamp":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} ``` | Field | Type | Description | @@ -113,13 +113,13 @@ data: {"status":"ready","books":["draftkings","fanduel"],"total_odds":3200} Fired when odds change for a sportsbook. Only sent on `odds` or `all` channels. -**Compact delta payload.** Delta events contain only fields that can change between updates — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, and `odds_changed_at`. Static fields like `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link`, and `event_start_time` are **not included** in deltas. Merge each delta into your local odds map by `id` using the full objects received in the initial `snapshot`. See [Migration: Compact SSE Deltas](#migration-compact-sse-deltas) below. +**Compact delta payload.** Delta events contain only fields that can change between updates — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, and `timestamp`. Static fields like `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link`, and `event_start_time` are **not included** in deltas. Merge each delta into your local odds map by `id` using the full objects received in the initial `snapshot`. See [Migration: Compact SSE Deltas](#migration-compact-sse-deltas) below. ``` event: odds:update id: evt_00042 -data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"odds_changed_at":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} +data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"timestamp":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} ``` **Delta object fields (`OddsDelta`):** @@ -136,7 +136,7 @@ data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_pr | `is_main_line` | boolean | `true` when this line is the consensus main line for its market; `false` for alternate lines. Can flip as the main line moves. | | `is_alternate_line` | boolean | Positive-polarity sibling of `is_main_line` (mutually exclusive). | | `is_stale_pregame_price` | boolean | `true` when a live row still carries a pre-game price that hasn't moved since kickoff. | -| `odds_changed_at` | string | ISO 8601 timestamp of the sportsbook's own source update for this line, when available. On Pinnacle, carries forward while the underlying price/line/`is_live` flag are unchanged — see [Understanding Pinnacle's `odds_changed_at`](/en/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | ISO 8601 time SharpAPI last refreshed this odd through its pipeline — advances every ingest cycle. A feed-freshness / liveness signal (matches OpticOdds' `timestamp`); it is NOT when the price last changed. See [understanding the `timestamp` field](/en/concepts/pinnacle-odds-changed-at/). | Exchange books additionally carry the dynamic `volume`, `volume_24h`, `open_interest`, and `max_bet` fields when present. Everything else — `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link`, `event_start_time`, and the nested entity refs — is **static** and comes from the initial `snapshot`; merge each delta into your local map by `id` and never read a static field off a delta. @@ -238,7 +238,7 @@ This is a 1:1 analogue of OpticOdds' `locked-odds` for easy migration. It is **s ``` event: odds:locked id: evt_00052 -data: {"odds":[{"id":"123456","odds_american":-2500,"is_live":true,"is_active":false,"odds_changed_at":"2026-02-08T18:47:38Z"}],"count":1,"book":"pinnacle","partial":false} +data: {"odds":[{"id":"123456","odds_american":-2500,"is_live":true,"is_active":false,"timestamp":"2026-02-08T18:47:38Z"}],"count":1,"book":"pinnacle","partial":false} ``` A market re-opening emits a normal `odds:update` with `is_active: true` (and a fresh price). Markets a book **removes entirely** come through [`odds:removed`](#odds-removed) instead. @@ -590,7 +590,7 @@ These close the connection. Handle them in `onerror`: ## Migration: Compact SSE Deltas -**Breaking change for SSE `odds:update` consumers.** The `odds:update` event now sends compact `OddsDelta` objects containing only dynamic fields (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Static fields like `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link`, and `event_start_time` are only sent in the initial `snapshot` event. +**Breaking change for SSE `odds:update` consumers.** The `odds:update` event now sends compact `OddsDelta` objects containing only dynamic fields (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Static fields like `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link`, and `event_start_time` are only sent in the initial `snapshot` event. **Why:** The previous payload sent the full `Odds` object on every change, producing ~170 KB/s per connection. The compact delta reduces bandwidth by ~5x, sending only the 6-7 fields that actually changed. diff --git a/content/en/concepts/_meta.js b/content/en/concepts/_meta.js index 2e7763b..38f3713 100644 --- a/content/en/concepts/_meta.js +++ b/content/en/concepts/_meta.js @@ -6,6 +6,6 @@ export default { "entity-reference-ids": "Entity Reference IDs", "live-vs-prematch": "Live vs. Pre-Match", liquidity: "Liquidity and Limits", - "pinnacle-odds-changed-at": "Pinnacle `odds_changed_at`", + "pinnacle-odds-changed-at": "The `timestamp` Field", "polymarket-resolution": "Polymarket Resolution", } diff --git a/content/en/concepts/pinnacle-odds-changed-at.mdx b/content/en/concepts/pinnacle-odds-changed-at.mdx index a3e2f0d..30d8b57 100644 --- a/content/en/concepts/pinnacle-odds-changed-at.mdx +++ b/content/en/concepts/pinnacle-odds-changed-at.mdx @@ -1,26 +1,26 @@ --- -description: "How Pinnacle's odds_changed_at field behaves — why it is the trading-desk timestamp, why it can look stale on MLB and NBA, and which field (wire_received_at) to use when benchmarking SharpAPI's pipeline latency." +description: "How SharpAPI's timestamp field behaves — why it is a delivery / feed-freshness signal that advances every refresh, why it matches OpticOdds' timestamp, and why SharpAPI no longer exposes a separate when-the-price-last-changed field." --- import { Callout } from 'nextra/components' -# Understanding Pinnacle's `odds_changed_at` +# Understanding the `timestamp` field -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 which timestamp to use when benchmarking SharpAPI's pipeline latency (spoiler: it is `wire_received_at`, not `odds_changed_at`). +Every odds row SharpAPI returns carries a single `timestamp` field. It is the time SharpAPI last refreshed that row through its pipeline — a **delivery / feed-freshness** signal that advances on every ingest cycle, even when the underlying price has not moved. This page explains what `timestamp` tracks, what it does *not* track, and how to reason about freshness on books like Pinnacle that hold lines steady. -## What `odds_changed_at` Actually Means + +SharpAPI exposes **one** per-odd timestamp: `timestamp`. There is no longer a separate field for "when the price last moved." The former `odds_changed_at`, `last_seen_at`, and `wire_received_at` fields have been removed — read `timestamp` instead. This matches OpticOdds' `timestamp` semantic for drop-in parity. + -On Pinnacle rows, `odds_changed_at` is **Pinnacle's own trading-desk timestamp** — when Pinnacle last repriced this specific line. +## What `timestamp` Actually Means -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. +`timestamp` is the ISO 8601 time SharpAPI last refreshed this odd through its pipeline. It advances every ingest cycle: each time we re-observe the row — whether or not the price, line, or `is_live` flag changed — `timestamp` moves forward to the observation time. - -`odds_changed_at` is **not** the last time our pipeline refreshed or touched this row, and it is **not** the right field for benchmarking SharpAPI's ingest latency. For "when did SharpAPI first observe this content," use `wire_received_at`. For "is this row still being kept alive by the pipeline," use `last_seen_at`. See [Benchmarking Pipeline Latency](#benchmarking-pipeline-latency) below. - +This makes it a **feed-freshness / liveness signal**, not a price-change signal. A fresh `timestamp` tells you the row is being actively maintained and the displayed price is current; it does **not** tell you when the trading desk last repriced the line. -## Why It Can Look Stale +## Why a Fresh `timestamp` Does Not Mean the Price Just Moved -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. +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 a line can sit unchanged for long stretches while SharpAPI keeps re-observing it and advancing `timestamp` every cycle. 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: @@ -32,25 +32,14 @@ Observed over a 24-hour window of Pinnacle's own CDN responses, the rate at whic | 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 +NBA and MLB player props commonly go long stretches without the trading desk moving the line — 30+ minutes is not unusual. Because `timestamp` reflects delivery freshness rather than the last price move, it stays fresh throughout: the row is still being maintained, the price is still current, the desk simply has not repriced. -Every odds row exposes three timestamps. Each answers a different question: +## How to Read `timestamp` -| Field | What it tells you | -|---------------------|----------------------------------------------------------------------------------------------------| -| `odds_changed_at` | The last time Pinnacle's trading desk moved this line (their source timestamp; can be hours old). | -| `wire_received_at` | The last time SharpAPI's pipeline first observed a content change for this row. | -| `last_seen_at` | The last time the pipeline touched this row at all (advances every ingest cycle). | +`timestamp` answers one question: **"how fresh is this row in SharpAPI's feed?"** -For "when did Pinnacle last move this line," use `odds_changed_at`. - -For "when did this content arrive at SharpAPI" (ingest-latency benchmarking), use `wire_received_at`. - -For a heartbeat-style check ("is the row still being maintained by the pipeline"), use `last_seen_at`. - -A large gap between `wire_received_at` and `odds_changed_at` (fresh `wire_received_at`, old `odds_changed_at`) means Pinnacle is holding the line steady — the pipeline has the row fresh, the trading desk just has not moved it. This is normal and is the single most common source of confusion when reading Pinnacle data. +- A recent `timestamp` (a few seconds old for a major-league market) means the row is live and the displayed price is current. +- A stale `timestamp` (more than a minute or two old for a major-league market) is a freshness signal worth investigating — the row may not be getting maintained. ```json { @@ -59,36 +48,31 @@ A large gap between `wire_received_at` and `odds_changed_at` (fresh `wire_receiv "selection": "Edmundo Sosa Over", "line": 0.5, "odds_american": -129, - "last_seen_at": "2026-04-21T21:35:02Z", - "wire_received_at": "2026-04-21T21:34:58Z", - "odds_changed_at": "2026-04-21T18:49:00Z" + "timestamp": "2026-04-21T21:35:02Z" } ``` -In this example the pipeline last touched this row 4 seconds before the client fetched it (`last_seen_at`), and last saw a content change 8 seconds before (`wire_received_at`). 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. All three values are correct. +In this example the pipeline last refreshed this row at `21:35:02Z`. As long as that value keeps advancing each cycle, treat the displayed price as current — even if Pinnacle's desk has not moved Sosa's total-bases line since pre-market open. -If `wire_received_at` and `last_seen_at` are both stale (more than a minute or two old for a major-league market), that is a pipeline signal worth investigating. If only `odds_changed_at` is stale, Pinnacle is holding the line — treat the displayed price as current. +Use `timestamp` as your single freshness gate. If it stops advancing for a major-league market, that is a feed signal worth investigating. If it keeps advancing while the price stays put, the book is simply holding the line — treat the displayed price as current. -## Benchmarking Pipeline Latency - -If you are comparing SharpAPI's Pinnacle delivery latency against another vendor, the field to measure against is **`wire_received_at`**, not `odds_changed_at`. The difference matters a lot: +## Benchmarking Across Vendors -- `odds_changed_at` is Pinnacle's own source timestamp. Computing `now - odds_changed_at` measures **Pinnacle's publish cadence plus our pipeline lag** — including the long idle windows from the cadence table above. On NBA player props this can routinely sit hours old because Pinnacle has not moved the line, not because we are slow. -- `wire_received_at` is stamped by SharpAPI at the moment we first observe a content change for the row, then carried forward across subsequent unchanged refreshes. Computing `now - wire_received_at` (or `wire_received_at - odds_changed_at`) isolates SharpAPI's ingest contribution from Pinnacle's trading-desk cadence. +When comparing SharpAPI's delivery against another vendor, compare against `timestamp` — it is SharpAPI's delivery / feed-freshness stamp, the direct analogue of OpticOdds' `timestamp`. Computing `now - timestamp` measures how fresh the row is in the feed. -Vendors do not all expose their internal arrival stamp explicitly, and some surface their own ingest time under the `odds_changed_at` name. Benchmarking SharpAPI's `odds_changed_at` against another vendor's `odds_changed_at` without checking the semantic on each side is comparing the time-since-source-update on one platform to the time-since-ingest on another, which structurally makes the platform that preserves source semantics look slower even when the pipeline is faster. +Be careful comparing freshness fields across platforms: some vendors surface a source-update time (when the trading desk last moved the line) under similar field names. A source-update time on a quiet market like NBA player props can routinely read hours old because the desk has not repriced — not because delivery is slow. SharpAPI's `timestamp` is a delivery stamp, so it stays fresh as long as the row is being maintained. -For an internal counterpart to per-row `wire_received_at`, the `/health` endpoint exposes Pinnacle's CDN publish cadence per sport (`cdn_fetch_pct_1h`, `cdn_fetch_pct_24h`). Low values for a given sport indicate the trading desk is holding lines steady; high values indicate active repricing. This panel lets you separate "Pinnacle is quiet" from "pipeline is stuck" without having to instrument anything yourself. +For an aggregate counterpart, the `/health` endpoint exposes Pinnacle's CDN publish cadence per sport (`cdn_fetch_pct_1h`, `cdn_fetch_pct_24h`). Low values for a given sport indicate the trading desk is holding lines steady; high values indicate active repricing. This lets you separate "Pinnacle is quiet" from "pipeline is stuck" without instrumenting anything yourself. ## 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. +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. With a delivery-oriented `timestamp`, that quiet period shows up correctly as a fresh, actively-maintained row rather than a "stale" one. ## Related -- [Odds Snapshot](/en/api-reference/odds/) — `odds_changed_at`, `wire_received_at`, and `last_seen_at` fields on the REST odds response -- [Streaming](/en/api-reference/stream/) — `odds_changed_at` on `odds:update` deltas +- [Odds Snapshot](/en/api-reference/odds/) — the `timestamp` field on the REST odds response +- [Streaming](/en/api-reference/stream/) — `timestamp` on `odds:update` deltas - [Live vs. Pre-Match](/en/concepts/live-vs-prematch/) — publish cadence and book delivery mechanisms - [EV Calculation](/en/concepts/ev-calculation/) — why Pinnacle is the sharp reference diff --git a/content/en/streaming/overview.mdx b/content/en/streaming/overview.mdx index 47d5f80..359baa2 100644 --- a/content/en/streaming/overview.mdx +++ b/content/en/streaming/overview.mdx @@ -206,7 +206,7 @@ for event in client.events(): | `connected` | Stream established, returns stream ID, active filters, and channels | | `snapshot` / `opportunities_snapshot` | Full odds/opportunities data dump (all fields) | | `snapshot:complete` | All initial data has been sent | -| `odds:update` | Compact delta — only dynamic fields (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Merge by `id` into snapshot state. | +| `odds:update` | Compact delta — only dynamic fields (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Merge by `id` into snapshot state. | | `odds:removed` | Odds removed by a sportsbook | | `ev:detected` | New +EV opportunity found | | `ev:expired` | +EV opportunity no longer available | diff --git a/content/es/api-reference/events-odds.mdx b/content/es/api-reference/events-odds.mdx index 52b9b7a..9833de5 100644 --- a/content/es/api-reference/events-odds.mdx +++ b/content/es/api-reference/events-odds.mdx @@ -61,8 +61,7 @@ Todas las respuestas incluyen las cabeceras estándar de rate limit y metadatos: | `odds.american` | number | Cuotas americanas (p. ej., -110, +150) | | `odds.decimal` | number | Cuotas decimales (p. ej., 1.909) | | `odds.probability` | number | Probabilidad implícita (p. ej., 0.5238) | -| `last_seen_at` | string | Marca de tiempo ISO 8601 cuando nuestro pipeline observó esta fila por última vez. Úsala como señal de frescura del pipeline. | -| `odds_changed_at` | string | Marca de tiempo ISO 8601 del momento en que el precio, la línea o el indicador `is_live` cambió realmente por última vez. La proporciona el sportsbook cuando está disponible; en Pinnacle se mantiene a lo largo de actualizaciones sin cambios — consulta [Comprender el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Hora ISO 8601 en que SharpAPI refrescó por última vez esta cuota a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad (igual que el `timestamp` de OpticOdds); NO es cuándo cambió el precio por última vez. Consulta [Entendiendo el campo `timestamp`](/es/concepts/pinnacle-odds-changed-at/). | ## Ejemplos de Solicitudes @@ -221,7 +220,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.556, "odds_probability": 0.643 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_ml_away", @@ -236,7 +235,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 2.55, "odds_probability": 0.392 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "pin_evt_nba_bos_lal_20260208_ml_home", @@ -251,7 +250,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.571, "odds_probability": 0.636 }, - "last_seen_at": "2026-02-08T12:03:00Z" + "timestamp": "2026-02-08T12:03:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_spread_home", @@ -266,7 +265,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_total_over", @@ -281,7 +280,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" } ], "meta": { diff --git a/content/es/api-reference/odds-batch.mdx b/content/es/api-reference/odds-batch.mdx index 4f84137..7ded62b 100644 --- a/content/es/api-reference/odds-batch.mdx +++ b/content/es/api-reference/odds-batch.mdx @@ -140,7 +140,7 @@ if result['data']['missing_events']: "odds_american": -210, "odds_decimal": 1.476, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" }, { "sportsbook": "draftkings", @@ -150,7 +150,7 @@ if result['data']['missing_events']: "odds_american": 175, "odds_decimal": 2.75, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" } ] }, @@ -170,7 +170,7 @@ if result['data']['missing_events']: "odds_american": -130, "odds_decimal": 1.769, "line": null, - "last_seen_at": "2026-01-26T10:15:05.000Z" + "timestamp": "2026-01-26T10:15:05.000Z" } ] } @@ -289,8 +289,7 @@ Cada elemento del array `data.events` es un objeto de evento con cuotas anidadas | `odds_american` | number | Cuotas americanas | | `odds_decimal` | number | Cuotas decimales | | `line` | number \| null | Valor de la línea | -| `last_seen_at` | string | Marca de tiempo ISO 8601 de cuándo nuestro pipeline observó esta fila por última vez. Úsala como señal de frescura del pipeline. | -| `odds_changed_at` | string | Marca de tiempo ISO 8601 de cuándo el precio, la línea o el flag `is_live` cambiaron realmente por última vez. Proporcionada por el sportsbook cuando está disponible; en Pinnacle se mantiene a lo largo de actualizaciones sin cambios — consulta [Entendiendo `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Hora ISO 8601 en que SharpAPI refrescó por última vez esta cuota a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad (igual que el `timestamp` de OpticOdds); NO es cuándo cambió el precio por última vez. Consulta [Entendiendo el campo `timestamp`](/es/concepts/pinnacle-odds-changed-at/). | ## Casos de Uso diff --git a/content/es/api-reference/odds-best.mdx b/content/es/api-reference/odds-best.mdx index c3e1cc9..e3baa47 100644 --- a/content/es/api-reference/odds-best.mdx +++ b/content/es/api-reference/odds-best.mdx @@ -110,32 +110,28 @@ for item in result['data']: "book": "fanduel", "odds": { "american": -105, "decimal": 1.952 }, "edge": 0.007, - "line": -6.5, - "last_seen_at": "2026-01-26T10:30:00.000Z" + "line": -6.5 }, { "book": "draftkings", "odds": { "american": -110, "decimal": 1.909 }, "edge": 0.0, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:55.000Z" + "line": -6.5 }, { "book": "betmgm", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:50.000Z" + "line": -6.5 }, { "book": "pinnacle", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:45.000Z" + "line": -6.5 } ], - "last_seen_at": "2026-01-26T10:30:00.000Z" + "timestamp": "2026-01-26T10:30:00.000Z" } ], "meta": { @@ -211,9 +207,7 @@ X-Request-Id: req_best_789xyz | `all_books[].odds` | object | Objeto de cuotas (`american`, `decimal`) | | `all_books[].edge` | number | Margen sobre las peores cuotas disponibles (puntos porcentuales) | | `all_books[].line` | number \| null | Línea en esta casa de apuestas | -| `all_books[].last_seen_at` | string | Cuándo nuestra pipeline observó por última vez la fila de esta casa — señal de frescura de la pipeline | -| `all_books[].odds_changed_at` | string | Cuándo cambió realmente por última vez el precio, la línea o el indicador `is_live` de esta casa. En Pinnacle, se mantiene durante actualizaciones sin cambios — consulta [Entendiendo el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/). | -| `last_seen_at` | string | Marca temporal ISO 8601 de la determinación de las mejores cuotas | +| `timestamp` | string | Marca temporal ISO 8601 de la determinación de las mejores cuotas | | `player_name` | string\|undefined | Nombre del jugador (solo mercados de player props) | | `stat_category` | string\|undefined | Categoría estadística, p. ej. `points`, `rebounds` (solo mercados de player props) | diff --git a/content/es/api-reference/odds-comparison.mdx b/content/es/api-reference/odds-comparison.mdx index 3e607c9..b4080c1 100644 --- a/content/es/api-reference/odds-comparison.mdx +++ b/content/es/api-reference/odds-comparison.mdx @@ -127,22 +127,22 @@ for market in event['markets']: "fanduel": { "odds_american": -145, "odds_decimal": 1.690, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "draftkings": { "odds_american": -150, "odds_decimal": 1.667, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "betmgm": { "odds_american": -155, "odds_decimal": 1.645, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": -148, "odds_decimal": 1.676, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "fanduel", @@ -159,22 +159,22 @@ for market in event['markets']: "draftkings": { "odds_american": 130, "odds_decimal": 2.300, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "fanduel": { "odds_american": 125, "odds_decimal": 2.250, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "betmgm": { "odds_american": 128, "odds_decimal": 2.280, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": 126, "odds_decimal": 2.260, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "draftkings", @@ -253,8 +253,7 @@ Cada entrada en el objeto `books`: |-------|------|-------------| | `odds_american` | number | Cuota americana | | `odds_decimal` | number | Cuota decimal | -| `last_seen_at` | string | Cuándo nuestro pipeline observó por última vez la fila de esta casa — señal de frescura del pipeline | -| `odds_changed_at` | string | Cuándo cambió por última vez el precio, la línea o el flag `is_live` de esta casa. En Pinnacle, se mantiene a través de actualizaciones sin cambios — consulta [Entendiendo el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Hora ISO 8601 en que SharpAPI refrescó por última vez la fila de esta casa a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad (igual que el `timestamp` de OpticOdds); NO es cuándo cambió el precio por última vez. Consulta [Entendiendo el campo `timestamp`](/es/concepts/pinnacle-odds-changed-at/). | ## Entendiendo el Hold @@ -293,7 +292,7 @@ curl "https://api.sharpapi.io/api/v1/odds/comparison?event=33483153&market=sprea ### Identificación de Líneas Obsoletas -Busca casas que no se hayan actualizado recientemente revisando el `last_seen_at` de cada casa. Una casa con cuotas obsoletas puede ser lenta en ajustarse, creando valor temporal. +Busca casas que no se hayan actualizado recientemente revisando el `timestamp` de cada casa. Una casa con cuotas obsoletas puede ser lenta en ajustarse, creando valor temporal. ### Eficiencia del Mercado diff --git a/content/es/api-reference/odds-delta.mdx b/content/es/api-reference/odds-delta.mdx index 69661f2..d32b304 100644 --- a/content/es/api-reference/odds-delta.mdx +++ b/content/es/api-reference/odds-delta.mdx @@ -128,7 +128,7 @@ while True: "odds_probability": 0.60, "line": null, "event_start_time": "2026-02-11T19:00:00Z", - "last_seen_at": "2026-02-11T12:00:15.125Z", + "timestamp": "2026-02-11T12:00:15.125Z", "is_live": false, "status": "upcoming" } diff --git a/content/es/api-reference/odds.mdx b/content/es/api-reference/odds.mdx index 3e7f742..fb0edc5 100644 --- a/content/es/api-reference/odds.mdx +++ b/content/es/api-reference/odds.mdx @@ -12,6 +12,10 @@ Obtén una instantánea de las cuotas actuales de las casas de apuestas. GET /api/v1/odds ``` + +**Cambio en v3.0.0:** la respuesta de cuotas ahora incluye un único campo `timestamp` (entrega / frescura del feed, igual que OpticOdds). Los antiguos campos `odds_changed_at`, `last_seen_at` y `wire_received_at` se han eliminado — usa `timestamp` en su lugar. Ya no existe un campo para indicar cuándo se movió el precio por última vez. + + ## Autenticación Requiere API key. Disponible para **todos los planes**. @@ -195,7 +199,7 @@ Los cursores son opacos — no los analices ni los construyas. Codifican la posi "odds_probability": 0.60, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false }, { @@ -214,7 +218,7 @@ Los cursores son opacos — no los analices ni los construyas. Codifican la posi "odds_probability": 0.4348, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false } ], @@ -314,9 +318,7 @@ X-Request-Id: req_abc123def456 | `line` | number \| null | Valor de la línea de spread o total (`null` para moneyline) | | `is_alternate_line` | boolean\|undefined | `true` cuando el `line` de esta fila difiere de la línea principal canónica para su grupo `(event, market_type, player)`. Siempre `false` para mercados sin línea (moneyline, outright). Estable en [`/opportunities/ev`](/es/api-reference/opportunities-ev/) hoy; en despliegue progresivo a las filas de `/odds`. Úsalo para separar instantáneas de línea principal y líneas alternativas. | | `event_start_time` | string | Hora de inicio del evento en ISO 8601 | -| `last_seen_at` | string | Marca de tiempo ISO 8601 de la última observación de esta fila por nuestro adaptador. Se actualiza en cada ciclo de ingesta — esta es la señal de frescura del pipeline. | -| `odds_changed_at` | string | Marca de tiempo ISO 8601 de la propia actualización en origen de la casa de apuestas para esta línea, cuando esté disponible. En Pinnacle, se mantiene mientras el precio/línea/flag `is_live` no cambien (consulta [Entendiendo el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/)). Usa `last_seen_at` para la frescura del pipeline. | -| `wire_received_at` | string\|undefined | Marca de tiempo ISO 8601 del momento en que sharp-api-go detectó por última vez un cambio de hash de contenido para esta fila — el sello de llegada al pipeline. Distinto de `last_seen_at` (observación del adaptador) y de `odds_changed_at` (actualización propia de la casa de apuestas). | +| `timestamp` | string | Hora ISO 8601 en que SharpAPI refrescó por última vez esta cuota a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad (igual que el `timestamp` de OpticOdds); NO es cuándo cambió el precio por última vez. | | `is_live` | boolean | Si el evento está actualmente en directo | | `event_uuid` | string\|undefined | UUID canónico estable del evento desde el atlas de SharpAPI, cuando el evento está mapeado. Mientras `event_id` lleva el identificador principal del adaptador (a menudo el de la casa de apuestas originadora), `event_uuid` es un hash estable entre feeds que puedes usar para joins entre feeds. Ausente para eventos no mapeados. | | `external_event_id` | string\|undefined | El ID de evento nativo de la propia casa de apuestas, cuando difiere de `event_id`. Útil para enlazar filas de vuelta a la UI o API de la casa de apuestas. | @@ -377,7 +379,7 @@ curl "https://api.sharpapi.io/api/v1/odds?sort=event_start_time" \ -H "X-API-Key: YOUR_API_KEY" ``` -Campos de ordenación válidos: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `last_seen_at`, `sportsbook`, `league`, `sport`. +Campos de ordenación válidos: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `timestamp`, `sportsbook`, `league`, `sport`. ## Selección de Campos @@ -447,7 +449,7 @@ curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \ "odds_decimal": 1.667, "odds_probability": 0.60, "line": null, - "last_seen_at": "2026-01-26T02:10:24.125Z" + "timestamp": "2026-01-26T02:10:24.125Z" } ] } diff --git a/content/es/api-reference/sportsbooks.mdx b/content/es/api-reference/sportsbooks.mdx index f648a74..9ffa2ff 100644 --- a/content/es/api-reference/sportsbooks.mdx +++ b/content/es/api-reference/sportsbooks.mdx @@ -400,7 +400,7 @@ El campo `requires_tier` indica el nivel de suscripción mínimo necesario para {/* AUTO:END:sharp-books */} -**Lectura de las marcas de tiempo de Pinnacle.** El campo `odds_changed_at` en una fila de Pinnacle es la marca de tiempo de su mesa de trading, no la de nuestro pipeline. Pinnacle mantiene las líneas estables cuando el mercado no se ha movido — un valor inactivo de más de 30 minutos es habitual en props de jugadores de MLB y mercados de la NBA. Usa `last_seen_at` para conocer la frescura del pipeline. Consulta [Entender el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/) para saber qué significa realmente "obsoleto" en su feed. +**Lectura de las marcas de tiempo de Pinnacle.** El campo `timestamp` en una fila de cuotas indica cuándo SharpAPI refrescó por última vez esa fila a través de su pipeline — es una señal de frescura del feed que avanza en cada ciclo de ingesta, no la marca de cuándo se movió el precio por última vez. SharpAPI ya no expone un campo separado para "cuándo cambió el precio". Consulta [Entender el campo `timestamp`](/es/concepts/pinnacle-odds-changed-at/) para saber cómo interpretar la frescura en el feed de Pinnacle. ### Internacionales diff --git a/content/es/api-reference/stream.mdx b/content/es/api-reference/stream.mdx index 9efcf04..7f21b79 100644 --- a/content/es/api-reference/stream.mdx +++ b/content/es/api-reference/stream.mdx @@ -87,7 +87,7 @@ Cada objeto de cuotas en el snapshot contiene **todos los campos** — esta es l ``` event: snapshot id: evt_00001 -data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"last_seen_at":"2026-02-08T18:47:20Z","odds_changed_at":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} +data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"timestamp":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} ``` | Campo | Tipo | Descripción | @@ -113,13 +113,13 @@ data: {"status":"ready","books":["draftkings","fanduel"],"total_odds":3200} Se dispara cuando cambian las cuotas de un sportsbook. Solo se envía en los canales `odds` o `all`. -**Carga útil delta compacta.** Los eventos delta contienen únicamente los campos que pueden cambiar entre actualizaciones — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` y `odds_changed_at`. Los campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` y `event_start_time` **no se incluyen** en los deltas. Fusiona cada delta en tu mapa local de cuotas por `id` usando los objetos completos recibidos en el `snapshot` inicial. Consulta [Migración: Deltas SSE compactos](#migration-compact-sse-deltas) más abajo. +**Carga útil delta compacta.** Los eventos delta contienen únicamente los campos que pueden cambiar entre actualizaciones — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` y `timestamp`. Los campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` y `event_start_time` **no se incluyen** en los deltas. Fusiona cada delta en tu mapa local de cuotas por `id` usando los objetos completos recibidos en el `snapshot` inicial. Consulta [Migración: Deltas SSE compactos](#migration-compact-sse-deltas) más abajo. ``` event: odds:update id: evt_00042 -data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"odds_changed_at":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} +data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"timestamp":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} ``` **Campos del objeto delta (`OddsDelta`):** @@ -132,7 +132,7 @@ data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_pr | `odds_probability` | number | Probabilidad implícita actualizada (p. ej. `0.6`) | | `line` | number \| null | Línea/handicap actualizada (p. ej. `-3.5`), o `null` para moneyline | | `is_live` | boolean | Indica si el evento está actualmente en vivo | -| `odds_changed_at` | string | Marca de tiempo ISO 8601 de la propia actualización del sportsbook para esta línea, cuando esté disponible. En Pinnacle, se mantiene mientras el precio/línea/flag `is_live` subyacentes no cambien — consulta [Entendiendo el `odds_changed_at` de Pinnacle](/es/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Hora ISO 8601 en que SharpAPI refrescó por última vez esta cuota a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad (igual que el `timestamp` de OpticOdds); NO es cuándo cambió el precio por última vez. Consulta [Entendiendo el campo `timestamp`](/es/concepts/pinnacle-odds-changed-at/). | **Campos del envoltorio:** @@ -570,7 +570,7 @@ Estos cierran la conexión. Manéjalos en `onerror`: ## Migración: Deltas SSE compactos -**Cambio incompatible para los consumidores SSE de `odds:update`.** El evento `odds:update` ahora envía objetos `OddsDelta` compactos que solo contienen campos dinámicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Los campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` y `event_start_time` solo se envían en el evento `snapshot` inicial. +**Cambio incompatible para los consumidores SSE de `odds:update`.** El evento `odds:update` ahora envía objetos `OddsDelta` compactos que solo contienen campos dinámicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Los campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` y `event_start_time` solo se envían en el evento `snapshot` inicial. **Por qué:** La carga útil anterior enviaba el objeto `Odds` completo en cada cambio, generando ~170 KB/s por conexión. El delta compacto reduce el ancho de banda en ~5x, enviando únicamente los 6-7 campos que realmente cambiaron. diff --git a/content/es/concepts/_meta.js b/content/es/concepts/_meta.js index 158ea43..985439e 100644 --- a/content/es/concepts/_meta.js +++ b/content/es/concepts/_meta.js @@ -5,6 +5,6 @@ export default { "event-matching": "Emparejamiento de Eventos", "entity-reference-ids": "IDs de Referencia de Entidades", "live-vs-prematch": "En Vivo vs. Pre-Partido", - "pinnacle-odds-changed-at": "Pinnacle `odds_changed_at`", + "pinnacle-odds-changed-at": "El campo `timestamp`", "polymarket-resolution": "Resolución de Polymarket", } diff --git a/content/es/concepts/pinnacle-odds-changed-at.mdx b/content/es/concepts/pinnacle-odds-changed-at.mdx index e065e78..25423e9 100644 --- a/content/es/concepts/pinnacle-odds-changed-at.mdx +++ b/content/es/concepts/pinnacle-odds-changed-at.mdx @@ -1,53 +1,37 @@ --- -description: "Cómo se comporta el campo odds_changed_at de Pinnacle — por qué es la marca temporal de la mesa de trading, por qué puede parecer obsoleto en MLB y NBA, y cómo leerlo junto a last_seen_at como señal de frescura del pipeline." +description: "Cómo se comporta el campo timestamp de SharpAPI — por qué es una señal de entrega y frescura del feed que avanza en cada refresco, su paridad con OpticOdds, y por qué SharpAPI ya no expone un campo separado para cuándo cambió el precio por última vez." --- import { Callout } from 'nextra/components' -# Entendiendo el `odds_changed_at` de Pinnacle +# Entendiendo el campo `timestamp` -Los clientes sharp que desarrollan herramientas de +EV y arbitraje sobre Pinnacle suelen hacer la misma pregunta: «¿por qué el `odds_changed_at` de esta fila de Pinnacle parece tener 20 minutos de antigüedad?». La respuesta corta es que funciona según lo previsto: contiene la marca temporal de la propia mesa de trading de Pinnacle, no la nuestra. Esta página explica qué registra realmente este campo, por qué puede permanecer sin cambios durante largos periodos y cómo combinarlo con `last_seen_at` para obtener una lectura clara de la frescura del pipeline. +Cada fila de cuotas que devuelve SharpAPI lleva un único campo de marca temporal: `timestamp`. Los clientes sharp que desarrollan herramientas de +EV y arbitraje suelen preguntar qué representa exactamente y cómo usarlo para juzgar si una cuota está actualizada. La respuesta corta: `timestamp` es una señal de **entrega / frescura del feed** — indica cuándo SharpAPI refrescó por última vez esa fila a través de su pipeline, y avanza en cada ciclo de ingesta. Esta página explica qué registra realmente este campo y por qué SharpAPI ya no expone un campo separado para "cuándo se movió el precio por última vez". -## Qué significa realmente `odds_changed_at` +## Qué significa realmente `timestamp` -En las filas de Pinnacle, `odds_changed_at` es **la marca temporal de la propia mesa de trading de Pinnacle**: cuándo Pinnacle revaloró por última vez esta línea concreta. +`timestamp` es la hora ISO 8601 en que SharpAPI refrescó por última vez esa cuota a través de su pipeline. Avanza en **cada** ciclo de ingesta, independientemente de si el precio, la línea o el flag `is_live` cambiaron. Es una señal de frescura del feed y de actividad (liveness): mientras `timestamp` siga avanzando, sabes que el pipeline sigue observando esa casa y ese mercado. -Se mantiene sin cambios cada vez que Pinnacle indica que el precio, la línea y el flag `is_live` de un mercado no se han movido. Internamente, SharpAPI calcula un hash de esos tres campos para cada fila de cuotas en cada refresco; cuando el hash es idéntico al de la instantánea anterior, conservamos el `odds_changed_at` previo en lugar de sobrescribirlo con el momento de la observación. Esto preserva la semántica de «cuándo se movió por última vez esta línea» a través de consultas repetidas a un mercado sin cambios. +Este comportamiento coincide con el campo `timestamp` de OpticOdds, de modo que si migras desde su feed o ejecutas ambos en paralelo, la semántica es la misma. -`odds_changed_at` **no** es la última vez que nuestro pipeline refrescó o tocó esta fila. Para la frescura del pipeline, utiliza `last_seen_at`. +`timestamp` **no** es la última vez que el precio se movió. Es cuándo SharpAPI refrescó por última vez la fila a través de su pipeline. SharpAPI ya no expone un campo separado para "cuándo cambió el precio por última vez". -## Por qué puede parecer obsoleto +## Por qué no hay un campo de "precio cambiado por última vez" -Pinnacle es un creador de mercado. Su mesa de trading publica un precio nuevo solo cuando el flujo real obliga a una revaloración; no sesgan las líneas en función de la acción minorista para incrementar el margen como hacen los soft books. Esa disciplina es la razón por la que Pinnacle se utiliza como referencia sharp para los cálculos de +EV, pero también significa que las líneas pueden permanecer sin cambios durante largos periodos. +En versiones anteriores, SharpAPI exponía campos separados (`odds_changed_at`, `last_seen_at`, `wire_received_at`) que intentaban distinguir la marca de la mesa de trading de la casa, la observación del adaptador y la llegada al pipeline. En la práctica, esos campos eran inconsistentes entre casas: muchas casas no publican una marca propia fiable de "precio cambiado", por lo que el valor a menudo no significaba lo que los clientes esperaban. -Observado durante una ventana de 24 horas de las propias respuestas del CDN de Pinnacle, la tasa a la que Pinnacle publicó *datos nuevos* (en lugar de un `304 Not Modified` cacheado) varía enormemente según el deporte: +A partir de la v3.0.0, SharpAPI se consolida en un único `timestamp` con semántica de entrega / frescura del feed —el mismo modelo que usa OpticOdds— para que el significado del campo sea idéntico en todas las casas. Si necesitas detectar cuándo se movió realmente un precio, compara los valores de cuota entre instantáneas sucesivas en tu propio cliente, en lugar de depender de una marca por fila. -| Deporte | Tasa de "datos nuevos" del CDN de Pinnacle | -|--------------|--------------------------------------------| -| Fútbol | ~94% | -| Tenis | ~66% | -| NHL | ~51% | -| MLB | ~18% | -| NBA | ~9% | +## Cómo usar `timestamp` para la frescura -Las player props de NBA y MLB suelen mostrar largos periodos de inactividad —no es inusual ver más de 30 minutos— porque la mesa de trading de Pinnacle no está moviendo la línea. Si ves un `odds_changed_at` antiguo en un mercado de NBA o MLB, casi siempre se debe al ritmo de publicación del propio Pinnacle, no a un fallo en nuestro pipeline. +Como `timestamp` avanza en cada ciclo de ingesta, es una lectura directa de la frescura del feed: -## Cómo leer los campos en conjunto - -Cada fila de cuotas expone dos marcas temporales. Responden a preguntas diferentes: - -| Campo | Qué te indica | -|--------------------|------------------------------------------------------------------------| -| `odds_changed_at` | La última vez que la mesa de trading de Pinnacle movió esta línea | -| `last_seen_at` | La última vez que nuestro pipeline observó esta fila | - -Para verificar la frescura del pipeline, utiliza `last_seen_at`: este se actualiza cada vez que ingestamos la fila, independientemente de si el precio se movió. - -Para «cuándo movió Pinnacle por última vez esta línea», utiliza `odds_changed_at`. - -Una gran diferencia entre ambos (`last_seen_at` reciente, `odds_changed_at` antiguo) significa que Pinnacle está manteniendo la línea estable. Esto es normal y constituye la fuente de confusión más habitual al leer los datos de Pinnacle. +| Observación | Qué significa | +|-------------|----------------| +| `timestamp` reciente (segundos de antigüedad) | El pipeline está observando activamente esa casa y mercado — el precio mostrado está vigente | +| `timestamp` obsoleto (más de uno o dos minutos en una liga importante) | Señal del feed que merece investigarse — la casa puede haberse quedado en silencio o estar experimentando retrasos | ```json { @@ -56,24 +40,21 @@ Una gran diferencia entre ambos (`last_seen_at` reciente, `odds_changed_at` anti "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" + "timestamp": "2026-04-21T21:35:02Z" } ``` -En este ejemplo, el pipeline vio esta fila 4 segundos antes de que el cliente la consultara (`last_seen_at` está actualizado). El precio en sí se movió por última vez 2h 46m antes (`odds_changed_at`), porque la mesa de trading de Pinnacle no ha revalorado la línea de total de bases de Sosa desde la apertura previa al partido. Ambos valores son correctos. +En este ejemplo, el pipeline refrescó esta fila pocos segundos antes de que el cliente la consultara (`timestamp` está actualizado), así que el precio mostrado está vigente. - -Si `last_seen_at` está obsoleto (más de uno o dos minutos de antigüedad para un mercado de una liga importante), eso es una señal del pipeline que merece investigarse. Si `odds_changed_at` está obsoleto pero `last_seen_at` está actualizado, Pinnacle está manteniendo la línea: trata el precio mostrado como vigente. - +## Una nota sobre Pinnacle -## Por qué Pinnacle es diferente +Pinnacle es un creador de mercado: su mesa de trading publica un precio nuevo solo cuando el flujo real obliga a una revaloración, en lugar de sesgar las líneas en torno a la acción minorista. Esa disciplina es la razón por la que Pinnacle se utiliza como referencia sharp de devig para +EV: sus líneas son lo más cercano a un precio justo disponible en el mercado. -Pinnacle acepta acción sharp y revalora en función del flujo real, en lugar de sesgar las líneas en torno a los apostadores minoristas. Esa disciplina de creador de mercado es la razón por la que los utilizamos como referencia de devig para +EV: sus líneas son lo más cercano a un precio justo disponible en el mercado. El compromiso es que las líneas previas al partido pueden permanecer sin cambios durante largos periodos cuando nada en el mercado se ha movido, lo que parece obsolescencia para quien espera el constante microajuste que hacen los soft books. +Una consecuencia práctica es que las líneas de Pinnacle pueden permanecer sin cambios durante largos periodos cuando nada en el mercado se ha movido —es habitual en props de jugadores de MLB y en mercados de la NBA—. Esto es normal. Con el modelo de `timestamp`, no hay que preocuparse de interpretar una marca de "precio cambiado" antigua: mientras `timestamp` siga avanzando, el pipeline sigue observando la fila y el precio mostrado está vigente, aunque Pinnacle no lo haya movido. ## Relacionado -- [Instantánea de cuotas](/es/api-reference/odds/) — campos `odds_changed_at` y `last_seen_at` en la respuesta REST de cuotas -- [Streaming](/es/api-reference/stream/) — `odds_changed_at` en los deltas `odds:update` +- [Instantánea de cuotas](/es/api-reference/odds/) — el campo `timestamp` en la respuesta REST de cuotas +- [Streaming](/es/api-reference/stream/) — `timestamp` en los deltas `odds:update` - [En vivo vs. Previo al partido](/es/concepts/live-vs-prematch/) — ritmo de publicación y mecanismos de entrega de los books - [Cálculo de EV](/es/concepts/ev-calculation/) — por qué Pinnacle es la referencia sharp diff --git a/content/es/streaming/overview.mdx b/content/es/streaming/overview.mdx index 11cfb62..47f8db4 100644 --- a/content/es/streaming/overview.mdx +++ b/content/es/streaming/overview.mdx @@ -188,7 +188,7 @@ for event in client.events(): | `connected` | Stream establecido, devuelve el ID del stream, los filtros activos y los canales | | `snapshot` / `opportunities_snapshot` | Volcado completo de datos de cuotas/oportunidades (todos los campos) | | `snapshot:complete` | Se han enviado todos los datos iniciales | -| `odds:update` | Delta compacto — solo campos dinámicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Fusionar por `id` con el estado del snapshot. | +| `odds:update` | Delta compacto — solo campos dinámicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Fusionar por `id` con el estado del snapshot. | | `odds:removed` | Cuotas eliminadas por una casa de apuestas | | `ev:detected` | Nueva oportunidad +EV detectada | | `ev:expired` | Oportunidad +EV ya no disponible | diff --git a/content/pt-BR/api-reference/events-odds.mdx b/content/pt-BR/api-reference/events-odds.mdx index 8d8067e..3fb920b 100644 --- a/content/pt-BR/api-reference/events-odds.mdx +++ b/content/pt-BR/api-reference/events-odds.mdx @@ -61,8 +61,7 @@ Todas as respostas incluem headers padrão de rate limit e metadados: | `odds.american` | number | Odds americanas (ex.: -110, +150) | | `odds.decimal` | number | Odds decimais (ex.: 1.909) | | `odds.probability` | number | Probabilidade implícita (ex.: 0.5238) | -| `last_seen_at` | string | Timestamp ISO 8601 de quando nosso pipeline observou esta linha pela última vez. Use isto como seu sinal de atualização do pipeline. | -| `odds_changed_at` | string | Timestamp ISO 8601 de quando o preço, a linha ou a flag `is_live` realmente mudou pela última vez. Fornecido pelo sportsbook quando disponível; na Pinnacle é propagado entre atualizações sem mudanças — veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Horário ISO 8601 em que a SharpAPI atualizou esta odd pela última vez através do seu pipeline — avança a cada ciclo de ingestão. É um sinal de frescor / liveness do feed (corresponde ao `timestamp` da OpticOdds); **não** é quando o preço mudou pela última vez. Veja [Entendendo o campo `timestamp`](/pt-BR/concepts/pinnacle-odds-changed-at/). | ## Exemplos de Requisições @@ -221,7 +220,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.556, "odds_probability": 0.643 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_ml_away", @@ -236,7 +235,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 2.55, "odds_probability": 0.392 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "pin_evt_nba_bos_lal_20260208_ml_home", @@ -251,7 +250,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.571, "odds_probability": 0.636 }, - "last_seen_at": "2026-02-08T12:03:00Z" + "timestamp": "2026-02-08T12:03:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_spread_home", @@ -266,7 +265,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" }, { "id": "dk_evt_nba_bos_lal_20260208_total_over", @@ -281,7 +280,7 @@ print(f"Fetched all {len(all_odds)} odds") "decimal": 1.909, "odds_probability": 0.524 }, - "last_seen_at": "2026-02-08T12:05:00Z" + "timestamp": "2026-02-08T12:05:00Z" } ], "meta": { diff --git a/content/pt-BR/api-reference/odds-batch.mdx b/content/pt-BR/api-reference/odds-batch.mdx index 9dcff4f..a950e04 100644 --- a/content/pt-BR/api-reference/odds-batch.mdx +++ b/content/pt-BR/api-reference/odds-batch.mdx @@ -140,7 +140,7 @@ if result['data']['missing_events']: "odds_american": -210, "odds_decimal": 1.476, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" }, { "sportsbook": "draftkings", @@ -150,7 +150,7 @@ if result['data']['missing_events']: "odds_american": 175, "odds_decimal": 2.75, "line": null, - "last_seen_at": "2026-01-26T10:15:00.000Z" + "timestamp": "2026-01-26T10:15:00.000Z" } ] }, @@ -170,7 +170,7 @@ if result['data']['missing_events']: "odds_american": -130, "odds_decimal": 1.769, "line": null, - "last_seen_at": "2026-01-26T10:15:05.000Z" + "timestamp": "2026-01-26T10:15:05.000Z" } ] } @@ -289,8 +289,7 @@ Cada item no array `data.events` é um objeto de evento com odds aninhadas: | `odds_american` | number | Odds americanas | | `odds_decimal` | number | Odds decimais | | `line` | number \| null | Valor da linha | -| `last_seen_at` | string | Timestamp ISO 8601 de quando nosso pipeline observou esta linha pela última vez. Use isto como seu sinal de atualização do pipeline. | -| `odds_changed_at` | string | Timestamp ISO 8601 de quando o preço, a linha ou a flag `is_live` realmente mudou pela última vez. Fornecido pela casa de apostas quando disponível; na Pinnacle, ele é mantido entre atualizações sem mudanças — veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Horário ISO 8601 em que a SharpAPI atualizou esta odd pela última vez através do seu pipeline — avança a cada ciclo de ingestão. É um sinal de frescor / liveness do feed (corresponde ao `timestamp` da OpticOdds); **não** é quando o preço mudou pela última vez. Veja [Entendendo o campo `timestamp`](/pt-BR/concepts/pinnacle-odds-changed-at/). | ## Casos de Uso diff --git a/content/pt-BR/api-reference/odds-best.mdx b/content/pt-BR/api-reference/odds-best.mdx index 3f1b69a..c7ef974 100644 --- a/content/pt-BR/api-reference/odds-best.mdx +++ b/content/pt-BR/api-reference/odds-best.mdx @@ -110,32 +110,28 @@ for item in result['data']: "book": "fanduel", "odds": { "american": -105, "decimal": 1.952 }, "edge": 0.007, - "line": -6.5, - "last_seen_at": "2026-01-26T10:30:00.000Z" + "line": -6.5 }, { "book": "draftkings", "odds": { "american": -110, "decimal": 1.909 }, "edge": 0.0, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:55.000Z" + "line": -6.5 }, { "book": "betmgm", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:50.000Z" + "line": -6.5 }, { "book": "pinnacle", "odds": { "american": -108, "decimal": 1.926 }, "edge": 0.003, - "line": -6.5, - "last_seen_at": "2026-01-26T10:29:45.000Z" + "line": -6.5 } ], - "last_seen_at": "2026-01-26T10:30:00.000Z" + "timestamp": "2026-01-26T10:30:00.000Z" } ], "meta": { @@ -211,9 +207,7 @@ X-Request-Id: req_best_789xyz | `all_books[].odds` | object | Objeto de odds (`american`, `decimal`) | | `all_books[].edge` | number | Edge sobre as piores odds disponíveis (pontos percentuais) | | `all_books[].line` | number \| null | Linha nesta casa de apostas | -| `all_books[].last_seen_at` | string | Quando nosso pipeline observou pela última vez a linha desta casa — sinal de atualização do pipeline | -| `all_books[].odds_changed_at` | string | Quando o preço, linha ou flag `is_live` desta casa mudou pela última vez. No Pinnacle, é mantido entre atualizações sem alterações — veja [Entendendo o `odds_changed_at` do Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/). | -| `last_seen_at` | string | Timestamp ISO 8601 da determinação das melhores odds | +| `timestamp` | string | Timestamp ISO 8601 da determinação das melhores odds | | `player_name` | string\|undefined | Nome do jogador (apenas mercados de player prop) | | `stat_category` | string\|undefined | Categoria estatística, ex.: `points`, `rebounds` (apenas mercados de player prop) | diff --git a/content/pt-BR/api-reference/odds-comparison.mdx b/content/pt-BR/api-reference/odds-comparison.mdx index bfdb368..d7bba2a 100644 --- a/content/pt-BR/api-reference/odds-comparison.mdx +++ b/content/pt-BR/api-reference/odds-comparison.mdx @@ -127,22 +127,22 @@ for market in event['markets']: "fanduel": { "odds_american": -145, "odds_decimal": 1.690, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "draftkings": { "odds_american": -150, "odds_decimal": 1.667, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "betmgm": { "odds_american": -155, "odds_decimal": 1.645, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": -148, "odds_decimal": 1.676, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "fanduel", @@ -159,22 +159,22 @@ for market in event['markets']: "draftkings": { "odds_american": 130, "odds_decimal": 2.300, - "last_seen_at": "2026-01-26T02:10:24.000Z" + "timestamp": "2026-01-26T02:10:24.000Z" }, "fanduel": { "odds_american": 125, "odds_decimal": 2.250, - "last_seen_at": "2026-01-26T02:10:20.000Z" + "timestamp": "2026-01-26T02:10:20.000Z" }, "betmgm": { "odds_american": 128, "odds_decimal": 2.280, - "last_seen_at": "2026-01-26T02:10:18.000Z" + "timestamp": "2026-01-26T02:10:18.000Z" }, "pinnacle": { "odds_american": 126, "odds_decimal": 2.260, - "last_seen_at": "2026-01-26T02:10:15.000Z" + "timestamp": "2026-01-26T02:10:15.000Z" } }, "best_book": "draftkings", @@ -253,8 +253,7 @@ Cada entrada no objeto `books`: |-------|------|-------------| | `odds_american` | number | Odds americanas | | `odds_decimal` | number | Odds decimais | -| `last_seen_at` | string | Quando nosso pipeline observou pela última vez a linha deste book — sinal de atualidade do pipeline | -| `odds_changed_at` | string | Quando o preço, linha ou flag `is_live` deste book mudou efetivamente pela última vez. Na Pinnacle, é mantido em refreshes sem alteração — veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Horário ISO 8601 em que a SharpAPI atualizou pela última vez a linha deste book através do seu pipeline — avança a cada ciclo de ingestão. É um sinal de frescor / liveness do feed (corresponde ao `timestamp` da OpticOdds); **não** é quando o preço mudou pela última vez. Veja [Entendendo o campo `timestamp`](/pt-BR/concepts/pinnacle-odds-changed-at/). | ## Entendendo o Hold @@ -293,7 +292,7 @@ curl "https://api.sharpapi.io/api/v1/odds/comparison?event=33483153&market=sprea ### Identificando Linhas Defasadas -Procure books que não foram atualizados recentemente verificando o `last_seen_at` de cada book. Um book com odds defasadas pode estar lento para se ajustar, criando valor temporário. +Procure books que não foram atualizados recentemente verificando o `timestamp` de cada book. Um book com odds defasadas pode estar lento para se ajustar, criando valor temporário. ### Eficiência do Mercado diff --git a/content/pt-BR/api-reference/odds-delta.mdx b/content/pt-BR/api-reference/odds-delta.mdx index cb98e29..7320f3c 100644 --- a/content/pt-BR/api-reference/odds-delta.mdx +++ b/content/pt-BR/api-reference/odds-delta.mdx @@ -128,7 +128,7 @@ while True: "odds_probability": 0.60, "line": null, "event_start_time": "2026-02-11T19:00:00Z", - "last_seen_at": "2026-02-11T12:00:15.125Z", + "timestamp": "2026-02-11T12:00:15.125Z", "is_live": false, "status": "upcoming" } diff --git a/content/pt-BR/api-reference/odds.mdx b/content/pt-BR/api-reference/odds.mdx index 386d000..86d3265 100644 --- a/content/pt-BR/api-reference/odds.mdx +++ b/content/pt-BR/api-reference/odds.mdx @@ -12,6 +12,10 @@ Obtenha um snapshot das odds atuais das casas de apostas. GET /api/v1/odds ``` + +Alterado na v3.0.0: a resposta de odds agora carrega um único campo `timestamp` (entrega / frescor do feed, em paridade com a OpticOdds). Os antigos campos `odds_changed_at`, `last_seen_at` e `wire_received_at` foram removidos — leia `timestamp` em vez disso. Não há mais um campo para quando o preço se moveu pela última vez. + + ## Autenticação Requer API key. Disponível para **todos os tiers**. @@ -195,7 +199,7 @@ Cursores são opacos — não os analise nem os construa. Eles codificam a posi "odds_probability": 0.60, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false }, { @@ -214,7 +218,7 @@ Cursores são opacos — não os analise nem os construa. Eles codificam a posi "odds_probability": 0.4348, "line": null, "event_start_time": "2026-01-26T19:00:00Z", - "last_seen_at": "2026-01-26T02:10:24.125Z", + "timestamp": "2026-01-26T02:10:24.125Z", "is_live": false } ], @@ -314,9 +318,7 @@ X-Request-Id: req_abc123def456 | `line` | number \| null | Valor da linha de spread ou total (`null` para moneyline) | | `is_alternate_line` | boolean\|undefined | `true` quando o `line` desta linha difere da linha principal canônica para seu grupo `(event, market_type, player)`. Sempre `false` para mercados sem linha (moneyline, outright). Estável em [`/opportunities/ev`](/pt-BR/api-reference/opportunities-ev/) hoje; em rollout para as linhas de `/odds`. Use para separar snapshots de linha principal e linhas alternativas. | | `event_start_time` | string | Hora de início do evento em ISO 8601 | -| `last_seen_at` | string | Timestamp ISO 8601 da última observação desta linha pelo nosso adaptador. Atualiza a cada ciclo de ingestão — este é o sinal de frescor do pipeline. | -| `odds_changed_at` | string | Timestamp ISO 8601 da atualização da própria fonte da casa de apostas para esta linha, quando disponível. Na Pinnacle, é mantido enquanto o preço/linha/flag `is_live` permanecerem inalterados (veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/)). Use `last_seen_at` para frescor do pipeline. | -| `wire_received_at` | string\|undefined | Timestamp ISO 8601 de quando o sharp-api-go observou pela última vez uma mudança no hash de conteúdo desta linha — o carimbo de chegada ao pipeline. Distinto de `last_seen_at` (observação do adaptador) e `odds_changed_at` (atualização da própria fonte da casa de apostas). | +| `timestamp` | string | Horário ISO 8601 em que a SharpAPI atualizou esta odd pela última vez através do seu pipeline — avança a cada ciclo de ingestão. É um sinal de frescor / liveness do feed (corresponde ao `timestamp` da OpticOdds); **não** é quando o preço mudou pela última vez. | | `is_live` | boolean | Se o evento está atualmente ao vivo | | `event_uuid` | string\|undefined | UUID canônico estável do evento do atlas do SharpAPI, quando o evento está mapeado. Enquanto `event_id` carrega o identificador primário do adaptador (frequentemente o da casa de apostas originadora), `event_uuid` é um hash estável entre feeds para joins cross-feed. Ausente para eventos não mapeados. | | `external_event_id` | string\|undefined | O ID de evento nativo da própria casa de apostas, quando distinto de `event_id`. Útil para vincular linhas de volta à UI ou API da casa de apostas. | @@ -377,7 +379,7 @@ curl "https://api.sharpapi.io/api/v1/odds?sort=event_start_time" \ -H "X-API-Key: YOUR_API_KEY" ``` -Campos de ordenação válidos: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `last_seen_at`, `sportsbook`, `league`, `sport`. +Campos de ordenação válidos: `odds_american`, `odds_decimal`, `odds_probability`, `event_start_time`, `timestamp`, `sportsbook`, `league`, `sport`. ## Seleção de Campos @@ -447,7 +449,7 @@ curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \ "odds_decimal": 1.667, "odds_probability": 0.60, "line": null, - "last_seen_at": "2026-01-26T02:10:24.125Z" + "timestamp": "2026-01-26T02:10:24.125Z" } ] } diff --git a/content/pt-BR/api-reference/sportsbooks.mdx b/content/pt-BR/api-reference/sportsbooks.mdx index 9e2bf8a..3999c1d 100644 --- a/content/pt-BR/api-reference/sportsbooks.mdx +++ b/content/pt-BR/api-reference/sportsbooks.mdx @@ -400,7 +400,7 @@ O campo `requires_tier` indica o nível mínimo de assinatura necessário para a {/* AUTO:END:sharp-books */} -**Lendo timestamps da Pinnacle.** O `odds_changed_at` em uma linha da Pinnacle é o timestamp da mesa de operações deles, não do nosso pipeline. A Pinnacle mantém as linhas estáveis quando o mercado não se moveu — um valor ocioso de 30+ minutos é comum em player props da MLB e mercados da NBA. Use `last_seen_at` para frescor do pipeline. Veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/) para o que "stale" realmente significa no feed deles. +**Lendo timestamps da Pinnacle.** O `timestamp` em uma linha da Pinnacle reflete quando a SharpAPI atualizou pela última vez a odd através do seu pipeline — é um sinal de frescor / liveness do feed, não de quando o preço se moveu. A SharpAPI não expõe mais um campo separado para "quando o preço mudou pela última vez". Veja [Entendendo o campo `timestamp`](/pt-BR/concepts/pinnacle-odds-changed-at/) para como interpretar a atualização do feed. ### Internacional diff --git a/content/pt-BR/api-reference/stream.mdx b/content/pt-BR/api-reference/stream.mdx index 2d64b06..d34c0de 100644 --- a/content/pt-BR/api-reference/stream.mdx +++ b/content/pt-BR/api-reference/stream.mdx @@ -87,7 +87,7 @@ Cada objeto de odds no snapshot contém **todos os campos** — esta é a forma ``` event: snapshot id: evt_00001 -data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"last_seen_at":"2026-02-08T18:47:20Z","odds_changed_at":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} +data: {"odds":[{"id":"123456","sportsbook":"draftkings","event_id":"nba_phosuns_phi76ers_2026-02-08","sport":"basketball","league":"nba","home_team":"PHI 76ers","away_team":"PHO Suns","market_type":"moneyline","selection":"PHO Suns","selection_type":"away","odds_american":-155,"odds_decimal":1.645,"odds_probability":0.608,"line":null,"event_start_time":"2026-02-08T19:00:00Z","is_live":false,"timestamp":"2026-02-08T18:47:20Z","deep_link":"https://sportsbook.draftkings.com/event/..."}],"count":1000,"total":3200,"offset":0,"has_more":true} ``` | Campo | Tipo | Descrição | @@ -113,13 +113,13 @@ data: {"status":"ready","books":["draftkings","fanduel"],"total_odds":3200} Disparado quando as odds mudam para um sportsbook. Enviado apenas nos channels `odds` ou `all`. -**Payload delta compacto.** Eventos delta contêm apenas campos que podem mudar entre atualizações — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` e `odds_changed_at`. Campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` e `event_start_time` **não são incluídos** nos deltas. Mescle cada delta no seu mapa local de odds por `id` usando os objetos completos recebidos no `snapshot` inicial. Veja [Migração: Deltas SSE Compactos](#migration-compact-sse-deltas) abaixo. +**Payload delta compacto.** Eventos delta contêm apenas campos que podem mudar entre atualizações — `id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live` e `timestamp`. Campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` e `event_start_time` **não são incluídos** nos deltas. Mescle cada delta no seu mapa local de odds por `id` usando os objetos completos recebidos no `snapshot` inicial. Veja [Migração: Deltas SSE Compactos](#migration-compact-sse-deltas) abaixo. ``` event: odds:update id: evt_00042 -data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"odds_changed_at":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} +data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_probability":0.6,"line":null,"is_live":false,"timestamp":"2026-02-08T18:47:38Z"}],"count":1,"book":"draftkings","partial":false} ``` **Campos do objeto delta (`OddsDelta`):** @@ -132,7 +132,7 @@ data: {"odds":[{"id":"123456","odds_american":-150,"odds_decimal":1.667,"odds_pr | `odds_probability` | number | Probabilidade implícita atualizada (ex.: `0.6`) | | `line` | number \| null | Linha/spread atualizada (ex.: `-3.5`), ou `null` para moneyline | | `is_live` | boolean | Se o evento está atualmente ao vivo | -| `odds_changed_at` | string | Timestamp ISO 8601 da atualização da própria fonte do sportsbook para esta linha, quando disponível. Na Pinnacle, é mantido enquanto o preço/linha/flag `is_live` subjacentes permanecerem inalterados — veja [Entendendo o `odds_changed_at` da Pinnacle](/pt-BR/concepts/pinnacle-odds-changed-at/). | +| `timestamp` | string | Horário ISO 8601 em que a SharpAPI atualizou esta odd pela última vez através do seu pipeline — avança a cada ciclo de ingestão. É um sinal de frescor / liveness do feed (corresponde ao `timestamp` da OpticOdds); **não** é quando o preço mudou pela última vez. Veja [Entendendo o campo `timestamp`](/pt-BR/concepts/pinnacle-odds-changed-at/). | **Campos do envelope:** @@ -570,7 +570,7 @@ Estes encerram a conexão. Trate-os no `onerror`: ## Migração: Deltas SSE Compactos -**Mudança incompatível para consumidores de `odds:update` SSE.** O evento `odds:update` agora envia objetos `OddsDelta` compactos contendo apenas campos dinâmicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` e `event_start_time` são enviados apenas no evento `snapshot` inicial. +**Mudança incompatível para consumidores de `odds:update` SSE.** O evento `odds:update` agora envia objetos `OddsDelta` compactos contendo apenas campos dinâmicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Campos estáticos como `sportsbook`, `sport`, `league`, `home_team`, `away_team`, `market_type`, `selection`, `deep_link` e `event_start_time` são enviados apenas no evento `snapshot` inicial. **Por quê:** O payload anterior enviava o objeto `Odds` completo a cada alteração, gerando ~170 KB/s por conexão. O delta compacto reduz o consumo de banda em ~5x, enviando apenas os 6-7 campos que realmente mudaram. diff --git a/content/pt-BR/concepts/_meta.js b/content/pt-BR/concepts/_meta.js index bc4050f..c2497f5 100644 --- a/content/pt-BR/concepts/_meta.js +++ b/content/pt-BR/concepts/_meta.js @@ -5,6 +5,6 @@ export default { "event-matching": "Correspondência de Eventos", "entity-reference-ids": "IDs de Referência de Entidades", "live-vs-prematch": "Ao Vivo vs. Pré-Jogo", - "pinnacle-odds-changed-at": "Pinnacle `odds_changed_at`", + "pinnacle-odds-changed-at": "O campo `timestamp`", "polymarket-resolution": "Resolução do Polymarket", } diff --git a/content/pt-BR/concepts/pinnacle-odds-changed-at.mdx b/content/pt-BR/concepts/pinnacle-odds-changed-at.mdx index 0f8f8fd..d663eb0 100644 --- a/content/pt-BR/concepts/pinnacle-odds-changed-at.mdx +++ b/content/pt-BR/concepts/pinnacle-odds-changed-at.mdx @@ -1,26 +1,32 @@ --- -description: "Como o campo odds_changed_at da Pinnacle se comporta — por que ele é o timestamp da mesa de operações, por que pode parecer desatualizado em MLB e NBA, e como interpretá-lo junto com last_seen_at como um sinal de atualização do pipeline." +description: "Como o campo timestamp da SharpAPI se comporta — por que ele é um sinal de entrega / frescor do feed, por que avança a cada ciclo de ingestão, sua paridade com a OpticOdds, e por que a SharpAPI não expõe mais um campo separado para quando o preço mudou pela última vez." --- import { Callout } from 'nextra/components' -# Entendendo o `odds_changed_at` da Pinnacle +# Entendendo o campo `timestamp` -Clientes sharp que constroem ferramentas de +EV e arbitragem contra a Pinnacle frequentemente fazem a mesma pergunta: "por que o `odds_changed_at` desta linha da Pinnacle parece ter 20 minutos?" A resposta curta é que está funcionando conforme projetado — ele carrega o timestamp da própria mesa de operações da Pinnacle, não o nosso. Esta página explica o que o campo realmente registra, por que pode permanecer inalterado por longos períodos, e como combiná-lo com `last_seen_at` para uma leitura clara da atualização do pipeline. +Cada linha de odds que a SharpAPI entrega carrega um único campo de horário: `timestamp`. Ele responde a uma pergunta — "quão recente é este dado?" — e não a "quando o preço mudou pela última vez?". Esta página explica o que o campo realmente registra, por que ele avança constantemente, e como interpretá-lo como um sinal de frescor do feed. -## O Que `odds_changed_at` Realmente Significa +## O Que `timestamp` Realmente Significa -Em linhas da Pinnacle, `odds_changed_at` é **o timestamp da própria mesa de operações da Pinnacle** — quando a Pinnacle reprecificou esta linha específica pela última vez. +`timestamp` é o horário ISO 8601 em que a SharpAPI atualizou esta odd pela última vez através do seu pipeline. Ele **avança a cada ciclo de ingestão**, independentemente de o preço ter se movido. Em outras palavras, é um sinal de **entrega / frescor / liveness do feed** — a mesma semântica do `timestamp` da OpticOdds. -Ele é mantido inalterado sempre que a Pinnacle sinaliza que o preço, a linha e a flag `is_live` em um mercado não se moveram. Internamente, a SharpAPI faz hash desses três campos para cada linha de odds em cada atualização; quando o hash é idêntico ao snapshot anterior, mantemos o `odds_changed_at` anterior em vez de sobrescrevê-lo com o horário da observação. Isso preserva a semântica de "quando esta linha se moveu pela última vez" através de polls repetidos de um mercado inalterado. - - -`odds_changed_at` **não é** a última vez que nosso pipeline atualizou ou tocou nesta linha. Para verificar a atualização do pipeline, use `last_seen_at`. + +`timestamp` reflete **quão recente é o dado**, não quando a linha se moveu pela última vez. Se o `timestamp` está atualizado, o preço exibido é atual — mesmo que a casa não tenha reprecificado nada há muito tempo. -## Por Que Pode Parecer Desatualizado +## Sem Campo Separado de "Última Mudança de Preço" + +A SharpAPI **não expõe mais** um campo separado para "quando o preço mudou pela última vez". Versões anteriores carregavam campos como `odds_changed_at`, `last_seen_at` e `wire_received_at`; eles foram removidos em favor do único `timestamp`. Se o seu cliente dependia de qualquer um desses campos, leia `timestamp` em vez disso e trate-o como um sinal de frescor. + +Isso simplifica o modelo: há um carimbo de horário por linha de odds, e ele significa "atualizado pela última vez através do nosso pipeline neste momento". + +## Por Que a Pinnacle Pode Parecer Diferente + +A Pinnacle é uma formadora de mercado (market-maker). A mesa de operações deles publica um novo preço apenas quando o fluxo real força uma reprecificação — eles não distorcem linhas em torno da ação do varejo para extrair margem da forma como as casas soft fazem. Essa disciplina é a razão pela qual a Pinnacle é usada como referência sharp para cálculos de +EV. -A Pinnacle é uma formadora de mercado (market-maker). A mesa de operações deles publica um novo preço apenas quando o fluxo real força uma reprecificação — eles não distorcem linhas em torno da ação do varejo para extrair margem da forma como as casas soft fazem. Essa disciplina é a razão pela qual a Pinnacle é usada como referência sharp para cálculos de +EV, mas também significa que as linhas podem permanecer inalteradas por longos períodos. +Como a SharpAPI agora reporta `timestamp` como frescor do feed, uma linha da Pinnacle terá um `timestamp` atualizado sempre que a ingerimos novamente — mesmo que a mesa de operações deles não tenha movido a linha há 30+ minutos. O `timestamp` atualizado confirma que o dado está fresco; ele não implica que o preço mudou. Observado durante uma janela de 24 horas das próprias respostas de CDN da Pinnacle, a taxa em que a Pinnacle publicou *novos dados* (em vez de um `304 Not Modified` em cache) varia enormemente por esporte: @@ -32,22 +38,9 @@ Observado durante uma janela de 24 horas das próprias respostas de CDN da Pinna | MLB | ~18% | | NBA | ~9% | -Player props de NBA e MLB comumente mostram longas janelas ociosas — 30+ minutos não é incomum — porque a mesa de operações da Pinnacle não está movendo a linha. Se você está vendo um `odds_changed_at` antigo em um mercado de NBA ou MLB, quase sempre é a própria cadência de publicação da Pinnacle, não uma falha em nosso pipeline. - -## Como Ler os Campos Juntos - -Cada linha de odds expõe dois timestamps. Eles respondem a perguntas diferentes: - -| Campo | O que ele diz a você | -|--------------------|----------------------------------------------------------------------| -| `odds_changed_at` | A última vez que a mesa de operações da Pinnacle moveu esta linha | -| `last_seen_at` | A última vez que nosso pipeline observou esta linha | - -Para verificações de atualização do pipeline, use `last_seen_at` — este é atualizado toda vez que ingerimos a linha, independentemente de o preço ter se movido. - -Para "quando a Pinnacle moveu esta linha pela última vez", use `odds_changed_at`. +Player props de NBA e MLB comumente passam longas janelas sem que a mesa de operações da Pinnacle mova a linha. Isso é a cadência de publicação própria da Pinnacle, não uma falha no pipeline — e como `timestamp` é um sinal de frescor, ele permanece atualizado durante essas janelas, indicando que o preço exibido continua sendo o preço atual. -Uma grande lacuna entre os dois (`last_seen_at` recente, `odds_changed_at` antigo) significa que a Pinnacle está mantendo a linha estável. Isso é normal e é a fonte mais comum de confusão ao ler os dados da Pinnacle. +## Como Ler o Campo ```json { @@ -56,24 +49,23 @@ Uma grande lacuna entre os dois (`last_seen_at` recente, `odds_changed_at` antig "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" + "timestamp": "2026-04-21T21:35:02Z" } ``` -Neste exemplo, o pipeline viu esta linha 4 segundos antes de o cliente buscá-la (`last_seen_at` está atualizado). O preço em si se moveu pela última vez 2h 46min antes (`odds_changed_at`), porque a mesa de operações da Pinnacle não reprecificou a linha de total de bases do Sosa desde a abertura pré-jogo. Ambos os valores estão corretos. +Neste exemplo, o `timestamp` mostra que a SharpAPI atualizou esta linha através do seu pipeline às 21:35:02 UTC. O dado é fresco. A mesa de operações da Pinnacle pode não ter reprecificado o total de bases do Sosa há horas, mas isso não é mais reportado em um campo separado — o `timestamp` atualizado confirma que o preço exibido é o preço atual. -Se `last_seen_at` estiver desatualizado (mais de um ou dois minutos para um mercado de uma liga principal), esse é um sinal do pipeline que vale a pena investigar. Se `odds_changed_at` estiver desatualizado, mas `last_seen_at` estiver atualizado, a Pinnacle está mantendo a linha — trate o preço exibido como atual. +Se o `timestamp` estiver desatualizado (mais de um ou dois minutos para um mercado de uma liga principal), esse é um sinal do feed que vale a pena investigar — pode indicar um atraso na ingestão. Se o `timestamp` estiver atualizado, trate o preço exibido como atual. -## Por Que a Pinnacle É Diferente +## Por Que a Pinnacle É a Referência Sharp -A Pinnacle aceita ação sharp e reprecifica com base no fluxo real, em vez de distorcer linhas em torno de apostadores de varejo. Essa disciplina de formadora de mercado é por que a usamos como referência de devig para +EV — as linhas deles são o mais próximo de um preço justo disponível no mercado. O trade-off é que as linhas pré-jogo podem permanecer inalteradas por longos períodos quando nada no mercado se moveu, o que parece desatualização para qualquer um que espera o microajuste constante que as casas soft fazem. +A Pinnacle aceita ação sharp e reprecifica com base no fluxo real, em vez de distorcer linhas em torno de apostadores de varejo. Essa disciplina de formadora de mercado é por que a usamos como referência de devig para +EV — as linhas deles são o mais próximo de um preço justo disponível no mercado. O trade-off é que as linhas pré-jogo podem permanecer no mesmo preço por longos períodos quando nada no mercado se moveu. Com `timestamp` como sinal de frescor, você sempre sabe que o dado é recente, mesmo quando o preço está estável. ## Relacionados -- [Snapshot de Odds](/pt-BR/api-reference/odds/) — campos `odds_changed_at` e `last_seen_at` na resposta REST de odds -- [Streaming](/pt-BR/api-reference/stream/) — `odds_changed_at` em deltas `odds:update` +- [Snapshot de Odds](/pt-BR/api-reference/odds/) — o campo `timestamp` na resposta REST de odds +- [Streaming](/pt-BR/api-reference/stream/) — `timestamp` em deltas `odds:update` - [Ao Vivo vs. Pré-Jogo](/pt-BR/concepts/live-vs-prematch/) — cadência de publicação e mecanismos de entrega das casas - [Cálculo de EV](/pt-BR/concepts/ev-calculation/) — por que a Pinnacle é a referência sharp diff --git a/content/pt-BR/streaming/overview.mdx b/content/pt-BR/streaming/overview.mdx index cd49c6a..8fbca73 100644 --- a/content/pt-BR/streaming/overview.mdx +++ b/content/pt-BR/streaming/overview.mdx @@ -188,7 +188,7 @@ for event in client.events(): | `connected` | Stream estabelecido, retorna ID do stream, filtros ativos e canais | | `snapshot` / `opportunities_snapshot` | Dump completo de dados de odds/oportunidades (todos os campos) | | `snapshot:complete` | Todos os dados iniciais foram enviados | -| `odds:update` | Delta compacto — apenas campos dinâmicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `odds_changed_at`). Faça merge por `id` no estado do snapshot. | +| `odds:update` | Delta compacto — apenas campos dinâmicos (`id`, `odds_american`, `odds_decimal`, `odds_probability`, `line`, `is_live`, `timestamp`). Faça merge por `id` no estado do snapshot. | | `odds:removed` | Odds removidas por uma sportsbook | | `ev:detected` | Nova oportunidade +EV encontrada | | `ev:expired` | Oportunidade +EV não está mais disponível | diff --git a/public/openapi.json b/public/openapi.json index b4d3d4a..3889530 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.1.0", "info": { "title": "SharpAPI", - "version": "2.3.0", + "version": "3.0.0", "description": "Real-time sports betting odds API with +EV detection, arbitrage, middles, and low-hold opportunities.\n\n## Spec Versioning\n\n`info.version` is bumped on every schema or path change. Minor version (`2.x.0`) for additive changes or breaking shape fixes that align the spec to the live response; major version (`x.0.0`) for backward-incompatible redesigns. Removed paths and renamed fields always bump the minor at minimum. Check `x-generated-at` and `x-commit-sha` for the build provenance of a given snapshot.\n\n## Authentication\n\nAll authenticated endpoints accept an API key via one of three methods:\n\n| Method | Header / Param | Use case |\n|--------|---------------|----------|\n| `X-API-Key` | `X-API-Key: sk_live_...` | Recommended for server-side |\n| `Authorization` | `Authorization: Bearer sk_live_...` | Standard Bearer token |\n| `api_key` query | `?api_key=sk_live_...` | SSE/EventSource (cannot set headers) |\n\n## Subscription Tiers\n\n| Tier | Rate Limit | Data Delay | Max Books | EV | Arb | Middles | Game State |\n|------|-----------|------------|-----------|-----|-----|---------|------------|\n| Free | 12/min | 60s | 2 (DK, FD) | - | - | - | - |\n| Hobby | 120/min | Real-time | 5 | - | Yes | - | - |\n| Pro | 300/min | Real-time | 15 | Yes | Yes | Yes | - |\n| Sharp | 1000/min | Real-time | All | Yes | Yes | Yes | - |\n| Enterprise | Custom | Real-time | All | Yes | Yes | Yes | Yes |\n\n## Rate Limit Headers\n\nEvery authenticated response includes:\n\n- `X-RateLimit-Limit` - Requests allowed per minute\n- `X-RateLimit-Remaining` - Requests remaining in current window\n- `X-RateLimit-Reset` - Unix timestamp when the window resets\n- `X-Data-Delay` - Odds delay in seconds for your tier (0 = real-time)\n- `X-Request-Id` - Unique request identifier for support\n\n## WebSocket Streaming\n\nThe WebSocket endpoint at `wss://ws.sharpapi.io` is documented separately in [`asyncapi.yaml`](./asyncapi.yaml) (AsyncAPI 3.0). OpenAPI 3.x cannot express WebSocket subprotocols and message channels, so the SSE endpoint (`/stream`) is the only stream covered by this document.\n\n## MCP Server\n\nThe `POST /mcp` endpoint is a Model Context Protocol server (JSON-RPC 2.0 over Streamable HTTP). Tools are self-described at runtime via `tools/list`, so it's documented as a setup guide rather than an OpenAPI path — see [`/sdks/mcp`](https://docs.sharpapi.io/sdks/mcp).\n", "contact": { "name": "SharpAPI Support", @@ -4462,28 +4462,10 @@ "type": "boolean", "description": "true (default) = market open and bettable; false = market suspended/closed with the price frozen. Mirrors OpticOdds locked-odds but exposed as a queryable field. Absent is treated as true. An active->suspended transition is emitted on the odds stream (odds:update with is_active=false)." }, - "odds_changed_at": { - "type": "string", - "format": "date-time", - "description": "Best-available last-price-change time for this line: the sportsbook's own source-update timestamp when provided, otherwise when SharpAPI first detected a price/line/is_live change — carried forward across unchanged refreshes. This is the freshness field to read." - }, "timestamp": { "type": "string", "format": "date-time", - "deprecated": true, - "description": "DEPRECATED — not emitted on the odds response; read `odds_changed_at` for price freshness." - }, - "last_seen_at": { - "type": "string", - "format": "date-time", - "deprecated": true, - "description": "DEPRECATED (being internalized, will be removed in a future release): liveness heartbeat — advances every ingest cycle even when the price is unchanged, so it is NOT a price-freshness signal. Read `odds_changed_at` instead." - }, - "wire_received_at": { - "type": "string", - "format": "date-time", - "deprecated": true, - "description": "DEPRECATED (being internalized, will be removed in a future release): SharpAPI pipeline-arrival stamp for ingest-latency benchmarking only — not a betting/price-freshness signal. Read `odds_changed_at` for price freshness." + "description": "ISO 8601 time SharpAPI last refreshed/observed this odd through its pipeline — advances on every ingest cycle. A feed-freshness / liveness signal, matching OpticOdds' `timestamp` (their field behaves identically). NOTE: this is delivery freshness, not a price-last-changed time; SharpAPI does not expose a separate when-the-price-moved field." }, "event_uuid": { "type": "string",