diff --git a/content/de/api-reference/odds-delta.mdx b/content/de/api-reference/odds-delta.mdx index 584379e..0ae23f3 100644 --- a/content/de/api-reference/odds-delta.mdx +++ b/content/de/api-reference/odds-delta.mdx @@ -133,6 +133,13 @@ while True: "status": "upcoming" } ], + "removed": [ + { + "id": "225107123583533", + "sportsbook": "pinnacle", + "removed_at": "2026-02-11T12:00:18.412Z" + } + ], "meta": { "count": 1, "total": 1, @@ -201,6 +208,16 @@ X-Request-Id: req_delta_abc123 Das `data`-Array enthält dieselben Quotenobjekte wie der [`/odds`](/de/api-reference/odds/)-Endpoint. Es werden nur Quoten einbezogen, die nach dem `since`-Zeitstempel aktualisiert wurden. +### Das `removed`-Array + +Das `removed`-Array auf oberster Ebene benennt jede Quotenzeile, die seit Ihrem `since`-Zeitstempel das Board verlassen hat — Märkte, die ein Buchmacher heruntergenommen hat (Aussetzung, ein durch eine Linienbewegung zurückgezogener Handicap-/Total-Schwellenwert, abgerechnetes Event). Löschen Sie diese `id`s aus Ihrem lokalen Zustand; dies ist das explizite Schlusssignal, Sie müssen also nie selbst Snapshots vergleichen. Nur vorhanden, wenn mindestens eine Entfernung Ihren Filtern entsprach. Siehe [Markt-Lebenszyklus](/de/concepts/market-lifecycle/) für die vollständige Übersicht der Schluss-/Aussetzungssignale. + +| Feld | Typ | Beschreibung | +|------|-----|--------------| +| `removed[].id` | string | Die Quoten-ID, die nicht mehr auf dem Board ist | +| `removed[].sportsbook` | string | Der Buchmacher, der sie entfernt hat | +| `removed[].removed_at` | string | ISO-8601-Zeitstempel, wann SharpAPI die Entfernung beobachtet hat | + Das `meta`-Objekt enthält zwei zusätzliche Felder: | Feld | Typ | Beschreibung | diff --git a/content/de/concepts/_meta.js b/content/de/concepts/_meta.js index 54a0fc4..8542a59 100644 --- a/content/de/concepts/_meta.js +++ b/content/de/concepts/_meta.js @@ -5,6 +5,7 @@ export default { "event-matching": "Event-Zuordnung", "entity-reference-ids": "Entitätsreferenz-IDs", "live-vs-prematch": "Live vs. Pre-Match", + "market-lifecycle": "Markt-Lebenszyklus", "pinnacle-odds-changed-at": "Das Feld `timestamp`", "polymarket-resolution": "Polymarket-Auflösung", } diff --git a/content/de/concepts/live-vs-prematch.mdx b/content/de/concepts/live-vs-prematch.mdx index 5dbfe68..5ac03ae 100644 --- a/content/de/concepts/live-vs-prematch.mdx +++ b/content/de/concepts/live-vs-prematch.mdx @@ -100,7 +100,7 @@ US-regulierte Buchmacher bieten Live-Wetten an, jedoch mit wichtigen Einschränk **Aussetzungen sind das Hauptproblem.** Wenn ein NBA-Team punktet, ziehen DraftKings und FanDuel typischerweise ihre Live-Moneylines, Spreads und Totals vom Brett, während sie neu bepreisen. In Hochphasen (4. Viertel eines knappen Spiels) können diese Buchmacher häufiger ausgesetzt als geöffnet sein. Dies ist ein regulatorisches Risikomanagement-Muster, keine API-Einschränkung. -Wenn ein DK- oder FD-Markt ausgesetzt ist, verschwindet er einfach aus der API — es gibt kein `status: suspended`-Feld. Wenn Sie `GET /api/v1/odds?live=true&sportsbook=draftkings` während eines Punktezugs aufrufen, erhalten Sie möglicherweise keine Ergebnisse für dieses Event, obwohl das Spiel läuft. +Wenn ein DK- oder FD-Markt ausgesetzt ist, verschwindet er einfach aus der API — diese Buchmacher ziehen den Markt zurück, statt ihn zu markieren. Die Entfernung selbst wird explizit signalisiert: Die `id` der Zeile erscheint in `removed[]` bei [`/odds/delta`](/de/api-reference/odds-delta/) und in einem `odds:removed`-Event auf dem Stream — siehe [Markt-Lebenszyklus](/de/concepts/market-lifecycle/). Wenn Sie `GET /api/v1/odds?live=true&sportsbook=draftkings` während eines Punktezugs aufrufen, erhalten Sie möglicherweise keine Ergebnisse für dieses Event, obwohl das Spiel läuft. ### Was das in der Praxis bedeutet diff --git a/content/de/concepts/market-lifecycle.mdx b/content/de/concepts/market-lifecycle.mdx new file mode 100644 index 0000000..3548245 --- /dev/null +++ b/content/de/concepts/market-lifecycle.mdx @@ -0,0 +1,107 @@ +--- +description: "Wie SharpAPI Marktschließungen, Aussetzungen und Entfernungen signalisiert — die expliziten Schlusssignale auf jeder Oberfläche (REST, Delta, SSE, WebSocket), wie Threshold-Leitern rotieren und wie Sie Ihren lokalen Zustand frei von veralteten Quoten halten." +--- + +import { Callout } from 'nextra/components' + +# Markt-Lebenszyklus: Aussetzungen und Entfernungen + +Märkte verschwinden ständig vom Board — ein Buchmacher setzt nach einem Tor aus, zieht eine Handicap- oder Total-Linie zurück, wenn sich die Hauptlinie bewegt, oder rechnet das Event ab. SharpAPI signalisiert jeden dieser Übergänge **explizit** auf jeder Konsumoberfläche. Sie müssen nie daraus schließen, dass ein Markt geschlossen wurde, indem Sie warten, bis sein Preis veraltet aussieht. + +Diese Seite ist die Übersicht: welches Signal wann ausgelöst wird, auf welcher Oberfläche, und wie Sie Ihren lokalen Zustand sauber halten. + +## Die zwei Arten, wie ein Markt das Board verlässt + +Sportwettenanbieter nehmen Märkte auf zwei unterschiedliche Arten vom Board, und SharpAPI spiegelt beide originalgetreu wider: + +| Modus | Was der Buchmacher tut | Was SharpAPI sendet | +|-------|------------------------|---------------------| +| **Entfernung** | Der Buchmacher nimmt den Markt vollständig herunter (dominanter Modus — z. B. Pinnacle zieht eine Handicap-/Total-Sprosse zurück, DK/FD setzen während eines Punktezugs aus, ein Event wird abgerechnet) | Die `id` der Zeile erscheint in `removed[]` bei [`/odds/delta`](/de/api-reference/odds-delta/) und in einem `odds:removed`-Event auf dem [SSE-Stream](/de/api-reference/stream/) und [WebSocket](/de/api-reference/websocket/). Die Zeile fehlt im nächsten `/odds`-Snapshot. | +| **Aussetzung an Ort und Stelle** | Der Buchmacher lässt den Markt gelistet, markiert ihn aber als geschlossen — der Preis ist eingefroren und nicht wettbar | Die Zeile bleibt vorhanden mit `is_active: false`. Der Übergang wird als `odds:update` mit `is_active: false` gepusht, plus ein dediziertes [`odds:locked`](/de/api-reference/stream/#odds-locked)-Event auf dem Stream. | + + +SharpAPI erfindet nie eine Zeile, die ein Buchmacher nicht veröffentlicht hat. Ein entfernter Markt wird durch ein explizites Entfernungs-Event mit seiner `id` signalisiert — nicht durch eine synthetische "geschlossen"-Preiszeile. Quoten-`id`s sind deterministisch — ein stabiler Hash aus Buchmacher, Event, Markt, Linie und Auswahl — sodass ein zurückkehrender Markt unter der **gleichen `id`** wieder eintrifft, und Löschen-bei-Entfernung plus Upsert-bei-Update hält Ihren Zustand exakt synchron mit dem Board. + + +## Signal-Matrix nach Oberfläche + +| Oberfläche | Entfernungssignal | Aussetzungssignal | +|------------|-------------------|-------------------| +| `GET /odds` (Snapshot-Polling) | Zeile fehlt in der nächsten Antwort | `is_active: false` auf der Zeile | +| `GET /odds/delta` | `removed[]` — `{id, sportsbook, removed_at}`-Objekte | `is_active: false` auf Zeilen in `data[]` | +| SSE `/stream` | `odds:removed` — `{ids: [...], count, book}` | `odds:update` mit `is_active: false`, plus `odds:locked` | +| WebSocket | `odds:removed`-Event | `odds:update` mit `is_active: false`, plus `odds:locked` | + +**Wenn Sie nur `/odds` pollen**, wird die Entfernung durch Abwesenheit kommuniziert: Vergleichen Sie jeden Snapshot mit dem vorherigen und entfernen Sie Zeilen, deren `id`s nicht mehr erscheinen. Das funktioniert, aber *Sie* müssen den Diff selbst berechnen — für explizite Entfernungsmeldungen nutzen Sie `/odds/delta` (dessen `removed[]`-Array jede seit Ihrem letzten Poll entfernte `id` benennt) oder den Stream (Push, gar kein Polling). + + +Der Delta-Endpunkt hält Entfernungen **10 Minuten** vor. Pollen Sie in der empfohlenen Kadenz (verketten Sie `since` aus `meta.server_time`), und Sie verpassen keine einzige; siehe [Quoten-Delta](/de/api-reference/odds-delta/) zu den Sicherheits-Flags `removed_truncated` und `since_clamped`. + + +## Threshold-Leitern: Handicaps und Totals + +Handicap- (Spread-) und Total-Märkte sind **Leitern** — eine Menge von Sprossen auf verschiedenen Linien (`-2.5`, `-3`, `-3.5`, …; `O/U 2.25`, `2.5`, `2.75`, …). Wenn sich die Hauptlinie bewegt, ziehen Buchmacher — insbesondere Pinnacle — Sprossen an den alten Schwellenwerten zurück und veröffentlichen neue. Jede Sprosse ist eine eigene Quotenzeile mit eigener `id`, daher: + +- Eine **zurückgezogene Sprosse** (der verschwindende Threshold-Markt) löst `odds:removed` aus / erscheint in `removed[]`, genau wie jede andere Entfernung. +- Die **neue Sprosse** trifft als frische Zeile via `odds:update` ein (oder im nächsten Snapshot/Delta), mit den Flags `is_main_line` / `is_alternate_line`, die Ihnen sagen, wo sie in der Leiter sitzt. +- Eine **zurückkehrende** Sprosse (häufig im Live-Spiel — Buchmacher zentrieren Leitern ständig neu) trifft unter der gleichen deterministischen `id` wieder ein. + +Die Leiterrotation ist während des Live-Spiels intensiv: alternative Sprossen kommen und gehen viele Male pro Spiel. Behandeln Sie eine Entfernung als "gerade *jetzt* nicht auf dem Board", nicht als endgültige Schließung — nur die Event-Abrechnung ist final. + +```text +total 2.5 (id …_total_over_2.5) ── Linie bewegt sich auf 3 ──▶ odds:removed [..._total_over_2.5] + odds:update [..._total_over_3] (neue Sprosse) +``` + +### Empfohlenes Client-Muster + +Indizieren Sie Ihren lokalen Zustand nach Quoten-`id` und wenden Sie drei Regeln in Event-Reihenfolge an: + +1. `odds:update` (oder eine Zeile in `data[]`) → Zeile upserten. +2. `odds:removed` (oder eine `id` in `removed[]`) → Zeile löschen. +3. `is_active: false` → Zeile behalten, aber als nicht wettbar markieren (ausgrauen); eine Wiedereröffnung trifft als normales `odds:update` mit `is_active: true` und einem frischen Preis ein. + +```python +# Delta-polling loop: explicit removals, no client-side diffing +since = initial_timestamp +while True: + r = get(f"/api/v1/odds/delta?since={since}&sportsbook=pinnacle").json() + for row in r["data"]: + local_state[row["id"]] = row # upsert (covers is_active flips) + for gone in r.get("removed", []): + local_state.pop(gone["id"], None) # delete — the close signal + since = r["meta"]["server_time"] + sleep(5) +``` + +```javascript +// SSE: push-based, the same three rules +es.addEventListener('odds:update', (e) => { + for (const row of JSON.parse(e.data).odds) localState.set(row.id, row); +}); +es.addEventListener('odds:removed', (e) => { + for (const id of JSON.parse(e.data).ids) localState.delete(id); +}); +``` + +## Eingefrorene Preise und Schutz vor veralteten Preisen + +Zwei Flags auf Zeilenebene schützen Sie davor, auf einen Preis zu reagieren, den der Buchmacher nicht mehr anbietet: + +| Feld | Bedeutung | +|------|-----------| +| `is_active` | `false` = der Markt ist ausgesetzt/geschlossen, der Preis ist auf seinem letzten Wert **eingefroren**. Ausgrauen; nicht wetten, nicht in EV-Berechnungen einspeisen. Fehlend bedeutet `true`. | +| `is_stale_pregame_price` | `true` auf einer Live-Zeile, die noch einen Pre-Game-Preis trägt, der sich seit Anpfiff nicht bewegt hat — filtern Sie mit `?is_stale_pregame_price=false`, wenn Sie nur in-play neu bepreiste Quoten wollen. | + +SharpAPIs eigene EV- und Arbitrage-Engines schließen `is_active: false`-Legs aus, sodass die [Opportunity-Endpunkte](/de/api-reference/opportunities-ev/) nie eine Edge gegen einen eingefrorenen, nicht wettbaren Preis ausweisen. + + +Pinnacle **entfernt** ausgesetzte Märkte überwiegend (→ `odds:removed`) und markiert eine kleinere Teilmenge als an Ort und Stelle geschlossen (→ `is_active: false` / `odds:locked`). US-Retail-Buchmacher wie DraftKings und FanDuel ziehen Märkte während Punktezügen vollständig zurück — Sie sehen Entfernungen, keine `is_active`-Wechsel. Behandeln Sie beide Modi, und Sie sind für jeden Buchmacher abgedeckt. + + +## Verwandte Themen + +- [Quoten-Delta](/de/api-reference/odds-delta/) — `removed[]`-Referenz, Aufbewahrungsfenster, Polling-Muster +- [SSE-Stream](/de/api-reference/stream/) — `odds:removed`, `odds:locked`, `is_active` auf `odds:update` +- [WebSocket](/de/api-reference/websocket/) — dieselben Events über WS +- [Live vs. Pre-Match](/de/concepts/live-vs-prematch/) — Aussetzungsverhalten der Buchmacher im Live-Spiel diff --git a/content/en/api-reference/odds-delta.mdx b/content/en/api-reference/odds-delta.mdx index e635d2f..e950274 100644 --- a/content/en/api-reference/odds-delta.mdx +++ b/content/en/api-reference/odds-delta.mdx @@ -133,6 +133,13 @@ while True: "status": "upcoming" } ], + "removed": [ + { + "id": "225107123583533", + "sportsbook": "pinnacle", + "removed_at": "2026-02-11T12:00:18.412Z" + } + ], "meta": { "count": 1, "total": 1, @@ -201,6 +208,16 @@ X-Request-Id: req_delta_abc123 The `data` array contains the same odds objects as the [`/odds`](/en/api-reference/odds/) endpoint. Only odds updated after the `since` timestamp are included. +### The `removed` Array + +The top-level `removed` array names every odds row that left the board since your `since` timestamp — markets a book took down (suspension, a handicap/total threshold retired by a line move, event settled). Delete these `id`s from your local state; this is the explicit close signal, so you never need to diff snapshots yourself. Present only when at least one removal matched your filters. See [Market Lifecycle](/en/concepts/market-lifecycle/) for the full close/suspend signal map. + +| Field | Type | Description | +|-------|------|-------------| +| `removed[].id` | string | The odds ID that is no longer on the board | +| `removed[].sportsbook` | string | The book that removed it | +| `removed[].removed_at` | string | ISO 8601 timestamp of when SharpAPI observed the removal | + The `meta` object includes two additional fields: | Field | Type | Description | diff --git a/content/en/concepts/_meta.js b/content/en/concepts/_meta.js index 38f3713..abc3001 100644 --- a/content/en/concepts/_meta.js +++ b/content/en/concepts/_meta.js @@ -5,6 +5,7 @@ export default { "event-matching": "Event Matching", "entity-reference-ids": "Entity Reference IDs", "live-vs-prematch": "Live vs. Pre-Match", + "market-lifecycle": "Market Lifecycle", liquidity: "Liquidity and Limits", "pinnacle-odds-changed-at": "The `timestamp` Field", "polymarket-resolution": "Polymarket Resolution", diff --git a/content/en/concepts/live-vs-prematch.mdx b/content/en/concepts/live-vs-prematch.mdx index c7bcb7a..0ce39e1 100644 --- a/content/en/concepts/live-vs-prematch.mdx +++ b/content/en/concepts/live-vs-prematch.mdx @@ -100,7 +100,7 @@ US regulated books have live betting, but with important limitations: **Suspension is the key issue.** When an NBA team scores, DraftKings and FanDuel typically pull their live moneylines, spreads, and totals off the board while they reprice. During peak action (4th quarter of a close game), these books may be suspended more often than they are open. This is a regulatory risk-management pattern, not an API limitation. -When a DK or FD market is suspended, it simply disappears from the API — there is no `status: suspended` field. If you call `GET /api/v1/odds?live=true&sportsbook=draftkings` during a scoring drive, you may get zero results for that event even though the game is in progress. +When a DK or FD market is suspended, it simply disappears from the API — these books pull the market rather than flagging it. The removal itself is signaled explicitly: the row's `id` appears in `removed[]` on [`/odds/delta`](/en/api-reference/odds-delta/) and in an `odds:removed` event on the stream — see [Market Lifecycle](/en/concepts/market-lifecycle/). If you call `GET /api/v1/odds?live=true&sportsbook=draftkings` during a scoring drive, you may get zero results for that event even though the game is in progress. ### What This Means in Practice diff --git a/content/en/concepts/market-lifecycle.mdx b/content/en/concepts/market-lifecycle.mdx new file mode 100644 index 0000000..0651dd4 --- /dev/null +++ b/content/en/concepts/market-lifecycle.mdx @@ -0,0 +1,107 @@ +--- +description: "How SharpAPI signals market closes, suspensions, and removals — the explicit close signals on every surface (REST, delta, SSE, WebSocket), how threshold ladders churn, and how to keep your local state free of stale odds." +--- + +import { Callout } from 'nextra/components' + +# Market Lifecycle: Suspensions and Removals + +Markets leave the board constantly — a book suspends after a goal, retires a handicap or total threshold as the line moves, or settles the event. SharpAPI signals every one of these transitions **explicitly** on every consumption surface. You never need to infer that a market closed by waiting for its price to look stale. + +This page is the map: which signal fires when, on which surface, and how to keep your local state clean. + +## The Two Ways a Market Leaves the Board + +Sportsbooks take markets off the board in two distinct ways, and SharpAPI mirrors both faithfully: + +| Mode | What the book does | What SharpAPI emits | +|------|--------------------|---------------------| +| **Removal** | The book takes the market down entirely (dominant mode — e.g. Pinnacle pulling a handicap/total rung, DK/FD suspending during a scoring play, an event settling) | The row's `id` appears in `removed[]` on [`/odds/delta`](/en/api-reference/odds-delta/) and in an `odds:removed` event on the [SSE stream](/en/api-reference/stream/) and [WebSocket](/en/api-reference/websocket/). The row is absent from the next `/odds` snapshot. | +| **Suspension in place** | The book keeps the market posted but flags it closed — the price is frozen and not bettable | The row stays present with `is_active: false`. The transition is pushed as an `odds:update` carrying `is_active: false`, plus a dedicated [`odds:locked`](/en/api-reference/stream/#odds-locked) event on the stream. | + + +SharpAPI never fabricates a row a book didn't post. A removed market is signaled by an explicit removal event carrying its `id` — not by a synthetic "closed" price row. Odds `id`s are deterministic — a stable hash of book, event, market, line, and selection — so a market that comes back re-arrives under the **same `id`**, and delete-on-removal plus upsert-on-update keeps your state exactly in sync with the board. + + +## Signal Matrix by Surface + +| Surface | Removal signal | Suspension signal | +|---------|----------------|-------------------| +| `GET /odds` (snapshot polling) | Row absent from the next response | `is_active: false` on the row | +| `GET /odds/delta` | `removed[]` — `{id, sportsbook, removed_at}` objects | `is_active: false` on rows in `data[]` | +| SSE `/stream` | `odds:removed` — `{ids: [...], count, book}` | `odds:update` with `is_active: false`, plus `odds:locked` | +| WebSocket | `odds:removed` event | `odds:update` with `is_active: false`, plus `odds:locked` | + +**If you poll plain `/odds`**, removal is communicated by absence: diff each snapshot against the previous one and drop rows whose `id`s no longer appear. This works, but it makes *you* do the diffing — for explicit removal notices, use `/odds/delta` (its `removed[]` array names every dropped `id` since your last poll) or the stream (push, no polling at all). + + +The delta endpoint retains removals for **10 minutes**. Poll at the recommended cadence (chain `since` from `meta.server_time`) and you'll never miss one; see [Odds Delta](/en/api-reference/odds-delta/) for the `removed_truncated` and `since_clamped` safety flags. + + +## Threshold Ladders: Handicaps and Totals + +Handicap (spread) and total markets are **ladders** — a set of rungs at different lines (`-2.5`, `-3`, `-3.5`, …; `O/U 2.25`, `2.5`, `2.75`, …). When the main line moves, books — Pinnacle in particular — retire rungs at the old thresholds and post new ones. Each rung is its own odds row with its own `id`, so: + +- A **retired rung** (the threshold-point market disappearing) fires `odds:removed` / shows up in `removed[]`, exactly like any other removal. +- The **new rung** arrives as a fresh row via `odds:update` (or in the next snapshot/delta), with `is_main_line` / `is_alternate_line` flags telling you where it sits in the ladder. +- A rung that **returns** (common in live play — books re-center ladders constantly) re-arrives under the same deterministic `id`. + +Ladder churn is heavy during live play: alternate rungs come and go many times per game. Treat a removal as "off the board *right now*", not as a terminal close — only event settlement is final. + +```text +total 2.5 (id …_total_over_2.5) ── line moves to 3 ──▶ odds:removed [..._total_over_2.5] + odds:update [..._total_over_3] (new rung) +``` + +### Recommended client pattern + +Key your local state by odds `id` and apply three rules, in event order: + +1. `odds:update` (or a row in `data[]`) → upsert the row. +2. `odds:removed` (or an `id` in `removed[]`) → delete the row. +3. `is_active: false` → keep the row but mark it unbettable (grey it out); a re-open arrives as a normal `odds:update` with `is_active: true` and a fresh price. + +```python +# Delta-polling loop: explicit removals, no client-side diffing +since = initial_timestamp +while True: + r = get(f"/api/v1/odds/delta?since={since}&sportsbook=pinnacle").json() + for row in r["data"]: + local_state[row["id"]] = row # upsert (covers is_active flips) + for gone in r.get("removed", []): + local_state.pop(gone["id"], None) # delete — the close signal + since = r["meta"]["server_time"] + sleep(5) +``` + +```javascript +// SSE: push-based, the same three rules +es.addEventListener('odds:update', (e) => { + for (const row of JSON.parse(e.data).odds) localState.set(row.id, row); +}); +es.addEventListener('odds:removed', (e) => { + for (const id of JSON.parse(e.data).ids) localState.delete(id); +}); +``` + +## Frozen Prices and Stale-Price Guards + +Two row-level flags protect you from acting on a price the book is no longer honoring: + +| Field | Meaning | +|-------|---------| +| `is_active` | `false` = the market is suspended/closed with the price **frozen** at its last value. Grey it out; don't bet it, don't feed it into EV math. Absent means `true`. | +| `is_stale_pregame_price` | `true` on a live row that still carries a pre-game price that hasn't moved since kickoff — filter with `?is_stale_pregame_price=false` if you only want prices repriced in-play. | + +SharpAPI's own EV and arbitrage engines exclude `is_active: false` legs, so [opportunity endpoints](/en/api-reference/opportunities-ev/) never surface an edge against a frozen, unbettable price. + + +Pinnacle mostly **removes** suspended markets (→ `odds:removed`) and flags a smaller subset closed in place (→ `is_active: false` / `odds:locked`). US retail books like DraftKings and FanDuel pull markets entirely during scoring plays — you'll see removals, not `is_active` flips. Handle both modes and you're covered for every book. + + +## Related + +- [Odds Delta](/en/api-reference/odds-delta/) — `removed[]` reference, retention window, polling pattern +- [SSE Stream](/en/api-reference/stream/) — `odds:removed`, `odds:locked`, `is_active` on `odds:update` +- [WebSocket](/en/api-reference/websocket/) — the same events over WS +- [Live vs. Pre-Match](/en/concepts/live-vs-prematch/) — book suspension behavior during live play diff --git a/content/es/api-reference/odds-delta.mdx b/content/es/api-reference/odds-delta.mdx index d32b304..f407fba 100644 --- a/content/es/api-reference/odds-delta.mdx +++ b/content/es/api-reference/odds-delta.mdx @@ -133,6 +133,13 @@ while True: "status": "upcoming" } ], + "removed": [ + { + "id": "225107123583533", + "sportsbook": "pinnacle", + "removed_at": "2026-02-11T12:00:18.412Z" + } + ], "meta": { "count": 1, "total": 1, @@ -201,6 +208,16 @@ X-Request-Id: req_delta_abc123 El array `data` contiene los mismos objetos de cuotas que el endpoint [`/odds`](/es/api-reference/odds/). Solo se incluyen las cuotas actualizadas después de la marca de tiempo `since`. +### El Array `removed` + +El array `removed` de nivel superior nombra cada fila de cuotas que salió del tablero desde tu marca de tiempo `since` — mercados que una casa retiró (suspensión, un umbral de hándicap/total retirado por un movimiento de línea, evento liquidado). Borra estos `id`s de tu estado local; esta es la señal de cierre explícita, así que nunca necesitas comparar snapshots tú mismo. Presente solo cuando al menos una eliminación coincidió con tus filtros. Consulta [Ciclo de Vida del Mercado](/es/concepts/market-lifecycle/) para el mapa completo de señales de cierre/suspensión. + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `removed[].id` | string | El ID de la cuota que ya no está en el tablero | +| `removed[].sportsbook` | string | La casa que la eliminó | +| `removed[].removed_at` | string | Marca de tiempo ISO 8601 de cuándo SharpAPI observó la eliminación | + El objeto `meta` incluye dos campos adicionales: | Campo | Tipo | Descripción | diff --git a/content/es/concepts/_meta.js b/content/es/concepts/_meta.js index 985439e..08b5b82 100644 --- a/content/es/concepts/_meta.js +++ b/content/es/concepts/_meta.js @@ -5,6 +5,7 @@ export default { "event-matching": "Emparejamiento de Eventos", "entity-reference-ids": "IDs de Referencia de Entidades", "live-vs-prematch": "En Vivo vs. Pre-Partido", + "market-lifecycle": "Ciclo de Vida del Mercado", "pinnacle-odds-changed-at": "El campo `timestamp`", "polymarket-resolution": "Resolución de Polymarket", } diff --git a/content/es/concepts/live-vs-prematch.mdx b/content/es/concepts/live-vs-prematch.mdx index 6bdbfe1..a3ce368 100644 --- a/content/es/concepts/live-vs-prematch.mdx +++ b/content/es/concepts/live-vs-prematch.mdx @@ -100,7 +100,7 @@ Las casas reguladas estadounidenses tienen apuestas en vivo, pero con limitacion **La suspensión es el problema clave.** Cuando un equipo de la NBA anota, DraftKings y FanDuel típicamente retiran sus moneylines, hándicaps y totales en vivo del tablero mientras revalorizan. Durante la acción más intensa (cuarto cuarto de un partido reñido), estas casas pueden estar suspendidas con más frecuencia de la que están abiertas. Este es un patrón regulatorio de gestión de riesgos, no una limitación de la API. -Cuando un mercado de DK o FD está suspendido, simplemente desaparece de la API: no existe un campo `status: suspended`. Si llamas a `GET /api/v1/odds?live=true&sportsbook=draftkings` durante una jugada de anotación, puedes obtener cero resultados para ese evento aunque el partido esté en curso. +Cuando un mercado de DK o FD está suspendido, simplemente desaparece de la API: estas casas retiran el mercado en lugar de marcarlo. La eliminación en sí se señala explícitamente: el `id` de la fila aparece en `removed[]` en [`/odds/delta`](/es/api-reference/odds-delta/) y en un evento `odds:removed` en el stream — consulta [Ciclo de Vida del Mercado](/es/concepts/market-lifecycle/). Si llamas a `GET /api/v1/odds?live=true&sportsbook=draftkings` durante una jugada de anotación, puedes obtener cero resultados para ese evento aunque el partido esté en curso. ### Qué Significa Esto en la Práctica diff --git a/content/es/concepts/market-lifecycle.mdx b/content/es/concepts/market-lifecycle.mdx new file mode 100644 index 0000000..8ca319e --- /dev/null +++ b/content/es/concepts/market-lifecycle.mdx @@ -0,0 +1,107 @@ +--- +description: "Cómo SharpAPI señala cierres, suspensiones y eliminaciones de mercados — las señales explícitas de cierre en cada superficie (REST, delta, SSE, WebSocket), cómo rotan las escaleras de umbrales y cómo mantener tu estado local libre de cuotas obsoletas." +--- + +import { Callout } from 'nextra/components' + +# Ciclo de Vida del Mercado: Suspensiones y Eliminaciones + +Los mercados salen del tablero constantemente — una casa suspende tras un gol, retira un umbral de hándicap o total cuando la línea se mueve, o liquida el evento. SharpAPI señala cada una de estas transiciones **explícitamente** en cada superficie de consumo. Nunca necesitas inferir que un mercado cerró esperando a que su precio parezca obsoleto. + +Esta página es el mapa: qué señal se dispara cuándo, en qué superficie, y cómo mantener limpio tu estado local. + +## Las Dos Formas en que un Mercado Sale del Tablero + +Las casas de apuestas retiran mercados del tablero de dos maneras distintas, y SharpAPI refleja ambas fielmente: + +| Modo | Qué hace la casa | Qué emite SharpAPI | +|------|------------------|--------------------| +| **Eliminación** | La casa retira el mercado por completo (modo dominante — p. ej. Pinnacle retirando un peldaño de hándicap/total, DK/FD suspendiendo durante una jugada de anotación, un evento liquidándose) | El `id` de la fila aparece en `removed[]` en [`/odds/delta`](/es/api-reference/odds-delta/) y en un evento `odds:removed` en el [stream SSE](/es/api-reference/stream/) y [WebSocket](/es/api-reference/websocket/). La fila está ausente del siguiente snapshot de `/odds`. | +| **Suspensión en el sitio** | La casa mantiene el mercado publicado pero lo marca como cerrado — el precio queda congelado y no apostable | La fila permanece presente con `is_active: false`. La transición se envía como un `odds:update` con `is_active: false`, más un evento dedicado [`odds:locked`](/es/api-reference/stream/#odds-locked) en el stream. | + + +SharpAPI nunca fabrica una fila que una casa no publicó. Un mercado eliminado se señala con un evento de eliminación explícito que lleva su `id` — no con una fila de precio "cerrado" sintética. Los `id`s de cuotas son deterministas — un hash estable de casa, evento, mercado, línea y selección — así que un mercado que regresa llega bajo el **mismo `id`**, y borrar-al-eliminar más upsert-al-actualizar mantiene tu estado exactamente sincronizado con el tablero. + + +## Matriz de Señales por Superficie + +| Superficie | Señal de eliminación | Señal de suspensión | +|------------|----------------------|---------------------| +| `GET /odds` (polling de snapshots) | Fila ausente de la siguiente respuesta | `is_active: false` en la fila | +| `GET /odds/delta` | `removed[]` — objetos `{id, sportsbook, removed_at}` | `is_active: false` en filas de `data[]` | +| SSE `/stream` | `odds:removed` — `{ids: [...], count, book}` | `odds:update` con `is_active: false`, más `odds:locked` | +| WebSocket | Evento `odds:removed` | `odds:update` con `is_active: false`, más `odds:locked` | + +**Si haces polling de `/odds` plano**, la eliminación se comunica por ausencia: compara cada snapshot con el anterior y elimina las filas cuyos `id`s ya no aparecen. Funciona, pero te obliga a *ti* a calcular el diff — para avisos de eliminación explícitos, usa `/odds/delta` (su array `removed[]` nombra cada `id` retirado desde tu último poll) o el stream (push, sin polling alguno). + + +El endpoint delta retiene las eliminaciones durante **10 minutos**. Haz polling a la cadencia recomendada (encadena `since` desde `meta.server_time`) y nunca perderás ninguna; consulta [Delta de Cuotas](/es/api-reference/odds-delta/) para los flags de seguridad `removed_truncated` y `since_clamped`. + + +## Escaleras de Umbrales: Hándicaps y Totales + +Los mercados de hándicap (spread) y total son **escaleras** — un conjunto de peldaños en distintas líneas (`-2.5`, `-3`, `-3.5`, …; `O/U 2.25`, `2.5`, `2.75`, …). Cuando la línea principal se mueve, las casas — Pinnacle en particular — retiran los peldaños en los umbrales antiguos y publican nuevos. Cada peldaño es su propia fila de cuotas con su propio `id`, así que: + +- Un **peldaño retirado** (el mercado de umbral que desaparece) dispara `odds:removed` / aparece en `removed[]`, exactamente como cualquier otra eliminación. +- El **peldaño nuevo** llega como una fila fresca vía `odds:update` (o en el siguiente snapshot/delta), con los flags `is_main_line` / `is_alternate_line` indicándote dónde se sitúa en la escalera. +- Un peldaño que **regresa** (común en juego en vivo — las casas recentran las escaleras constantemente) vuelve a llegar bajo el mismo `id` determinista. + +La rotación de la escalera es intensa durante el juego en vivo: los peldaños alternativos van y vienen muchas veces por partido. Trata una eliminación como "fuera del tablero *ahora mismo*", no como un cierre terminal — solo la liquidación del evento es definitiva. + +```text +total 2.5 (id …_total_over_2.5) ── la línea se mueve a 3 ──▶ odds:removed [..._total_over_2.5] + odds:update [..._total_over_3] (peldaño nuevo) +``` + +### Patrón de cliente recomendado + +Indexa tu estado local por `id` de cuota y aplica tres reglas, en orden de eventos: + +1. `odds:update` (o una fila en `data[]`) → upsert de la fila. +2. `odds:removed` (o un `id` en `removed[]`) → borrar la fila. +3. `is_active: false` → conservar la fila pero marcarla como no apostable (atenuarla); una reapertura llega como un `odds:update` normal con `is_active: true` y un precio fresco. + +```python +# Delta-polling loop: explicit removals, no client-side diffing +since = initial_timestamp +while True: + r = get(f"/api/v1/odds/delta?since={since}&sportsbook=pinnacle").json() + for row in r["data"]: + local_state[row["id"]] = row # upsert (covers is_active flips) + for gone in r.get("removed", []): + local_state.pop(gone["id"], None) # delete — the close signal + since = r["meta"]["server_time"] + sleep(5) +``` + +```javascript +// SSE: push-based, the same three rules +es.addEventListener('odds:update', (e) => { + for (const row of JSON.parse(e.data).odds) localState.set(row.id, row); +}); +es.addEventListener('odds:removed', (e) => { + for (const id of JSON.parse(e.data).ids) localState.delete(id); +}); +``` + +## Precios Congelados y Protecciones contra Precios Obsoletos + +Dos flags a nivel de fila te protegen de actuar sobre un precio que la casa ya no honra: + +| Campo | Significado | +|-------|-------------| +| `is_active` | `false` = el mercado está suspendido/cerrado con el precio **congelado** en su último valor. Atenúalo; no lo apuestes, no lo alimentes a cálculos de EV. Ausente se trata como `true`. | +| `is_stale_pregame_price` | `true` en una fila en vivo que aún lleva un precio pre-partido que no se ha movido desde el inicio — filtra con `?is_stale_pregame_price=false` si solo quieres precios reajustados en vivo. | + +Los propios motores de EV y arbitraje de SharpAPI excluyen las patas con `is_active: false`, de modo que los [endpoints de oportunidades](/es/api-reference/opportunities-ev/) nunca muestran una ventaja contra un precio congelado y no apostable. + + +Pinnacle mayormente **elimina** los mercados suspendidos (→ `odds:removed`) y marca un subconjunto menor como cerrado en el sitio (→ `is_active: false` / `odds:locked`). Las casas minoristas de EE. UU. como DraftKings y FanDuel retiran los mercados por completo durante las jugadas de anotación — verás eliminaciones, no cambios de `is_active`. Maneja ambos modos y estarás cubierto para todas las casas. + + +## Relacionado + +- [Delta de Cuotas](/es/api-reference/odds-delta/) — referencia de `removed[]`, ventana de retención, patrón de polling +- [Stream SSE](/es/api-reference/stream/) — `odds:removed`, `odds:locked`, `is_active` en `odds:update` +- [WebSocket](/es/api-reference/websocket/) — los mismos eventos sobre WS +- [En Vivo vs. Pre-Partido](/es/concepts/live-vs-prematch/) — comportamiento de suspensión de las casas en juego en vivo diff --git a/content/pt-BR/api-reference/odds-delta.mdx b/content/pt-BR/api-reference/odds-delta.mdx index 7320f3c..780c04b 100644 --- a/content/pt-BR/api-reference/odds-delta.mdx +++ b/content/pt-BR/api-reference/odds-delta.mdx @@ -133,6 +133,13 @@ while True: "status": "upcoming" } ], + "removed": [ + { + "id": "225107123583533", + "sportsbook": "pinnacle", + "removed_at": "2026-02-11T12:00:18.412Z" + } + ], "meta": { "count": 1, "total": 1, @@ -201,6 +208,16 @@ X-Request-Id: req_delta_abc123 O array `data` contém os mesmos objetos de odds que o endpoint [`/odds`](/pt-BR/api-reference/odds/). Apenas odds atualizadas após o timestamp `since` são incluídas. +### O Array `removed` + +O array `removed` de nível superior nomeia cada linha de odds que saiu do quadro desde o seu timestamp `since` — mercados que uma casa retirou (suspensão, um limiar de handicap/total retirado por um movimento de linha, evento liquidado). Delete esses `id`s do seu estado local; este é o sinal de fechamento explícito, então você nunca precisa comparar snapshots por conta própria. Presente apenas quando ao menos uma remoção correspondeu aos seus filtros. Veja [Ciclo de Vida do Mercado](/pt-BR/concepts/market-lifecycle/) para o mapa completo de sinais de fechamento/suspensão. + +| Campo | Tipo | Descrição | +|-------|------|-----------| +| `removed[].id` | string | O ID da odd que não está mais no quadro | +| `removed[].sportsbook` | string | A casa que a removeu | +| `removed[].removed_at` | string | Timestamp ISO 8601 de quando a SharpAPI observou a remoção | + O objeto `meta` inclui dois campos adicionais: | Campo | Tipo | Descrição | diff --git a/content/pt-BR/concepts/_meta.js b/content/pt-BR/concepts/_meta.js index c2497f5..973f0dc 100644 --- a/content/pt-BR/concepts/_meta.js +++ b/content/pt-BR/concepts/_meta.js @@ -5,6 +5,7 @@ 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", + "market-lifecycle": "Ciclo de Vida do Mercado", "pinnacle-odds-changed-at": "O campo `timestamp`", "polymarket-resolution": "Resolução do Polymarket", } diff --git a/content/pt-BR/concepts/live-vs-prematch.mdx b/content/pt-BR/concepts/live-vs-prematch.mdx index 40cd2de..b7cc46b 100644 --- a/content/pt-BR/concepts/live-vs-prematch.mdx +++ b/content/pt-BR/concepts/live-vs-prematch.mdx @@ -100,7 +100,7 @@ Casas reguladas dos EUA têm apostas ao vivo, mas com limitações importantes: **A suspensão é a questão central.** Quando um time da NBA pontua, DraftKings e FanDuel normalmente retiram seus moneylines, spreads e totais ao vivo do quadro enquanto reprecificam. Durante ações de pico (4º quarto de um jogo apertado), essas casas podem estar suspensas com mais frequência do que abertas. Esse é um padrão de gestão de risco regulatório, não uma limitação da API. -Quando um mercado da DK ou FD é suspenso, ele simplesmente desaparece da API — não há um campo `status: suspended`. Se você chamar `GET /api/v1/odds?live=true&sportsbook=draftkings` durante uma jogada de pontuação, pode obter zero resultados para esse evento, mesmo que o jogo esteja em andamento. +Quando um mercado da DK ou FD é suspenso, ele simplesmente desaparece da API — essas casas retiram o mercado em vez de marcá-lo. A remoção em si é sinalizada explicitamente: o `id` da linha aparece em `removed[]` no [`/odds/delta`](/pt-BR/api-reference/odds-delta/) e em um evento `odds:removed` no stream — veja [Ciclo de Vida do Mercado](/pt-BR/concepts/market-lifecycle/). Se você chamar `GET /api/v1/odds?live=true&sportsbook=draftkings` durante uma jogada de pontuação, pode obter zero resultados para esse evento, mesmo que o jogo esteja em andamento. ### O Que Isso Significa na Prática diff --git a/content/pt-BR/concepts/market-lifecycle.mdx b/content/pt-BR/concepts/market-lifecycle.mdx new file mode 100644 index 0000000..4d2c3dd --- /dev/null +++ b/content/pt-BR/concepts/market-lifecycle.mdx @@ -0,0 +1,107 @@ +--- +description: "Como a SharpAPI sinaliza fechamentos, suspensões e remoções de mercados — os sinais explícitos de fechamento em cada superfície (REST, delta, SSE, WebSocket), como as escadas de linhas alternativas giram e como manter seu estado local livre de odds obsoletas." +--- + +import { Callout } from 'nextra/components' + +# Ciclo de Vida do Mercado: Suspensões e Remoções + +Mercados saem do quadro o tempo todo — uma casa suspende após um gol, retira uma linha de handicap ou total quando a linha principal se move, ou liquida o evento. A SharpAPI sinaliza cada uma dessas transições **explicitamente** em todas as superfícies de consumo. Você nunca precisa inferir que um mercado fechou esperando o preço parecer obsoleto. + +Esta página é o mapa: qual sinal dispara quando, em qual superfície, e como manter seu estado local limpo. + +## As Duas Formas de um Mercado Sair do Quadro + +As casas de apostas retiram mercados do quadro de duas maneiras distintas, e a SharpAPI espelha ambas fielmente: + +| Modo | O que a casa faz | O que a SharpAPI emite | +|------|------------------|------------------------| +| **Remoção** | A casa retira o mercado por completo (modo dominante — p. ex. a Pinnacle retirando um degrau de handicap/total, DK/FD suspendendo durante uma jogada de pontuação, um evento sendo liquidado) | O `id` da linha aparece em `removed[]` no [`/odds/delta`](/pt-BR/api-reference/odds-delta/) e em um evento `odds:removed` no [stream SSE](/pt-BR/api-reference/stream/) e [WebSocket](/pt-BR/api-reference/websocket/). A linha fica ausente do próximo snapshot de `/odds`. | +| **Suspensão no lugar** | A casa mantém o mercado publicado mas o marca como fechado — o preço fica congelado e não apostável | A linha permanece presente com `is_active: false`. A transição é enviada como um `odds:update` com `is_active: false`, mais um evento dedicado [`odds:locked`](/pt-BR/api-reference/stream/#odds-locked) no stream. | + + +A SharpAPI nunca fabrica uma linha que a casa não publicou. Um mercado removido é sinalizado por um evento de remoção explícito com seu `id` — não por uma linha de preço "fechado" sintética. Os `id`s das odds são determinísticos — um hash estável de casa, evento, mercado, linha e seleção — então um mercado que retorna chega sob o **mesmo `id`**, e deletar-na-remoção mais upsert-na-atualização mantém seu estado exatamente em sincronia com o quadro. + + +## Matriz de Sinais por Superfície + +| Superfície | Sinal de remoção | Sinal de suspensão | +|------------|------------------|--------------------| +| `GET /odds` (polling de snapshots) | Linha ausente da próxima resposta | `is_active: false` na linha | +| `GET /odds/delta` | `removed[]` — objetos `{id, sportsbook, removed_at}` | `is_active: false` nas linhas de `data[]` | +| SSE `/stream` | `odds:removed` — `{ids: [...], count, book}` | `odds:update` com `is_active: false`, mais `odds:locked` | +| WebSocket | Evento `odds:removed` | `odds:update` com `is_active: false`, mais `odds:locked` | + +**Se você faz polling do `/odds` simples**, a remoção é comunicada por ausência: compare cada snapshot com o anterior e remova as linhas cujos `id`s não aparecem mais. Funciona, mas obriga *você* a calcular o diff — para avisos de remoção explícitos, use o `/odds/delta` (seu array `removed[]` nomeia cada `id` retirado desde o seu último poll) ou o stream (push, sem polling algum). + + +O endpoint delta retém remoções por **10 minutos**. Faça polling na cadência recomendada (encadeie `since` a partir de `meta.server_time`) e você nunca perderá nenhuma; consulte [Delta de Odds](/pt-BR/api-reference/odds-delta/) para os flags de segurança `removed_truncated` e `since_clamped`. + + +## Escadas de Linhas: Handicaps e Totais + +Mercados de handicap (spread) e total são **escadas** — um conjunto de degraus em linhas diferentes (`-2.5`, `-3`, `-3.5`, …; `O/U 2.25`, `2.5`, `2.75`, …). Quando a linha principal se move, as casas — a Pinnacle em particular — retiram os degraus nos limiares antigos e publicam novos. Cada degrau é sua própria linha de odds com seu próprio `id`, então: + +- Um **degrau retirado** (o mercado de limiar que desaparece) dispara `odds:removed` / aparece em `removed[]`, exatamente como qualquer outra remoção. +- O **degrau novo** chega como uma linha nova via `odds:update` (ou no próximo snapshot/delta), com os flags `is_main_line` / `is_alternate_line` indicando onde ele se posiciona na escada. +- Um degrau que **retorna** (comum no jogo ao vivo — as casas recentralizam as escadas constantemente) chega novamente sob o mesmo `id` determinístico. + +O giro da escada é intenso durante o jogo ao vivo: degraus alternativos vêm e vão muitas vezes por partida. Trate uma remoção como "fora do quadro *agora*", não como um fechamento terminal — somente a liquidação do evento é definitiva. + +```text +total 2.5 (id …_total_over_2.5) ── a linha se move para 3 ──▶ odds:removed [..._total_over_2.5] + odds:update [..._total_over_3] (degrau novo) +``` + +### Padrão de cliente recomendado + +Indexe seu estado local pelo `id` da odd e aplique três regras, em ordem de eventos: + +1. `odds:update` (ou uma linha em `data[]`) → upsert da linha. +2. `odds:removed` (ou um `id` em `removed[]`) → deletar a linha. +3. `is_active: false` → manter a linha mas marcá-la como não apostável (esmaecê-la); uma reabertura chega como um `odds:update` normal com `is_active: true` e um preço novo. + +```python +# Delta-polling loop: explicit removals, no client-side diffing +since = initial_timestamp +while True: + r = get(f"/api/v1/odds/delta?since={since}&sportsbook=pinnacle").json() + for row in r["data"]: + local_state[row["id"]] = row # upsert (covers is_active flips) + for gone in r.get("removed", []): + local_state.pop(gone["id"], None) # delete — the close signal + since = r["meta"]["server_time"] + sleep(5) +``` + +```javascript +// SSE: push-based, the same three rules +es.addEventListener('odds:update', (e) => { + for (const row of JSON.parse(e.data).odds) localState.set(row.id, row); +}); +es.addEventListener('odds:removed', (e) => { + for (const id of JSON.parse(e.data).ids) localState.delete(id); +}); +``` + +## Preços Congelados e Proteções contra Preços Obsoletos + +Dois flags no nível da linha protegem você de agir sobre um preço que a casa não está mais honrando: + +| Campo | Significado | +|-------|-------------| +| `is_active` | `false` = o mercado está suspenso/fechado com o preço **congelado** no último valor. Esmaeça-o; não aposte, não alimente cálculos de EV com ele. Ausente é tratado como `true`. | +| `is_stale_pregame_price` | `true` em uma linha ao vivo que ainda carrega um preço pré-jogo que não se moveu desde o início — filtre com `?is_stale_pregame_price=false` se você só quer preços reprecificados ao vivo. | + +Os próprios motores de EV e arbitragem da SharpAPI excluem pernas com `is_active: false`, então os [endpoints de oportunidades](/pt-BR/api-reference/opportunities-ev/) nunca mostram uma vantagem contra um preço congelado e não apostável. + + +A Pinnacle majoritariamente **remove** mercados suspensos (→ `odds:removed`) e marca um subconjunto menor como fechado no lugar (→ `is_active: false` / `odds:locked`). Casas de varejo dos EUA como DraftKings e FanDuel retiram os mercados por completo durante jogadas de pontuação — você verá remoções, não mudanças de `is_active`. Trate os dois modos e você estará coberto para todas as casas. + + +## Relacionado + +- [Delta de Odds](/pt-BR/api-reference/odds-delta/) — referência de `removed[]`, janela de retenção, padrão de polling +- [Stream SSE](/pt-BR/api-reference/stream/) — `odds:removed`, `odds:locked`, `is_active` no `odds:update` +- [WebSocket](/pt-BR/api-reference/websocket/) — os mesmos eventos via WS +- [Ao Vivo vs. Pré-Jogo](/pt-BR/concepts/live-vs-prematch/) — comportamento de suspensão das casas no jogo ao vivo