> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sx.bet/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Product updates and announcements

<Update label="May 22, 2026">
  ## Quarter-line flags on `/trades` and `recent_trades:global`

  [`GET /trades`](/api-reference/get-trades) response items and the [`recent_trades:global`](/api-reference/centrifugo-trade-updates) realtime channel now carry two additive fields so you can identify quarter-line legs without inspecting market metadata:

  * **`isQuarterLineLeg`** (`boolean`, always present) — `true` when the trade's `marketHash` is one of the two legs of a quarter-line market.
  * **`quarterLineParentMarketHash`** (`string`, optional) — present only when `isQuarterLineLeg` is `true`. Holds the parent quarter-line market hash (the market the user originally placed on), which differs from the trade's own `marketHash`. Use this to group both legs back to the user-facing bet.

  This mirrors the [May 12 flags on consolidated trades](/changelog#quarter-line-flags-on-markets-and-consolidated-trades), but at the per-order grain.
</Update>

<Update label="May 13, 2026">
  ## `GET /orders` now reports pending fills

  [`GET /orders`](/api-reference/get-orders) now returns `pendingFillAmount` on each order — the sum of accepted fills not yet reflected in `fillAmount`, from the maker's perspective.
</Update>

<Update label="May 12, 2026">
  ## Quarter-line flags on markets and consolidated trades

  Quarter-line markets and trades are now explicitly flagged on the API surface, so you no longer need to infer them from `line` values or dedupe via `quarterLineFillHash` alone.

  ### What's new

  * **`Market.isQuarterLineMarket`** — returned on `GET /markets/active` and `GET /markets/find`. `true` when the market is a quarter line (Asian handicap or totals in .25 increments).
  * **`ConsolidatedTrade.isQuarterLineParent`** — `true` on the synthetic parent entry that aggregates a quarter-line bet's two legs. Use this for user-facing P\&L and volume.
  * **`ConsolidatedTrade.isQuarterLineLeg`** — `true` on each of the two underlying leg entries.
  * **New query params on `GET /trades/consolidated`:**
    * `hideQuarterLineParents=true` — return only raw leg entries.
    * `hideQuarterLineLegs=true` — return only parent entries (recommended for portfolio/P\&L views).

  The same `isQuarterLineParent` / `isQuarterLineLeg` flags are now included in payloads on the `recent_trades_consolidated:global` real-time channel.

  ### How to use the flags

  * **Aggregating P\&L or volume:** filter to `isQuarterLineParent === true` (or pass `hideQuarterLineLegs=true`) and treat non-quarter trades normally — the parent's `totalStake`, `totalReturn`, and `netReturn` already aggregate both legs.
  * **Settlement-level analysis:** filter to `isQuarterLineLeg === true` (or pass `hideQuarterLineParents=true`) to see the underlying on-chain settlements; each leg settles independently.
  * **Don't sum both** — parents and legs represent the same bet. Pick one side.

  This pairs with the existing `quarterLineFillHash` field from the [May 7 quarter-lines rollout](/changelog#quarter-lines-gradual-rollout); the booleans are an easier dedup signal for most integrations.

  See [`GET /markets/active`](/api-reference/get-markets-active), [`GET /markets/find`](/api-reference/get-markets-find), [`GET /trades/consolidated`](/api-reference/get-trades-consolidated), and [Consolidated Trade Updates](/api-reference/centrifugo-consolidated-trade-updates).
</Update>

<Update label="May 11, 2026">
  ## Cancel endpoints now report orders they couldn't cancel

  The success response from `POST /orders/cancel/v2`, `POST /orders/cancel/event`, and `POST /orders/cancel/all` now includes a `data.notCancelled` array. Each entry is an `{ orderHash, reason }` pair for an order that matched the cancel request but wasn't cancelled.

  Possible `reason` values:

  * `not_found_or_inactive` — order was not found or is no longer active.
  * `already_pending_cancel` — order already has a pending cancellation.
  * `order_locked` — order is temporarily locked, likely because another fill/cancel flow is processing it.
  * `update_failed` — order could not be cancelled due to an internal processing issue.

  Previously these orders failed silently. The `cancelledCount` and `orders` fields are unchanged.

  See [Cancel individual orders →](/api-reference/post-cancel-orders), [Cancel orders by event →](/api-reference/post-cancel-event), and [Cancel all orders →](/api-reference/post-cancel-all).
</Update>

<Update label="May 8, 2026">
  ## `GET /trades` now requires a scoping filter

  Requests must now include at least one of `bettor`, `marketHashes`, `sportXeventId`, or `startDate`. Calls without any of these will be rejected.

  Existing queries that already filter by user, market, event, or time window are unaffected.

  See the [endpoint reference →](/api-reference/get-trades).
</Update>

<Update label="May 7, 2026">
  ## Quarter lines (gradual rollout)

  Soccer markets now support quarter lines (Asian handicap and Asian totals in .25 increments — e.g. `-1.25`, `+0.75`, `Over 2.75`).

  We're rolling this out gradually: quarter lines are currently enabled on a subset of soccer fixtures and will expand across the rest of soccer over the coming weeks.

  Quarter-line markets are returned by `/markets/active` and `/markets/find` alongside all other lines, with `line` set to the quarter value.

  <Accordion title="Example quarter-line market">
    ```json theme={null}
    {
      "status": "success",
      "data": [
        {
          "status": "ACTIVE",
          "marketHash": "0x59b0e45f79d4b6eedaed199011b8bf72a8b4342e3b410457cc42abcf05d3592d",
          "outcomeOneName": "Brighton and Hove Albion -1.25",
          "outcomeTwoName": "Wolverhampton Wanderers +1.25",
          "outcomeVoidName": "NO_GAME_OR_EVEN",
          "teamOneName": "Brighton and Hove Albion",
          "teamTwoName": "Wolverhampton Wanderers",
          "type": 3,
          "gameTime": 1778335200,
          "line": -1.25,
          "sportXeventId": "L18724593",
          "liveEnabled": false,
          "sportLabel": "Soccer",
          "sportId": 5,
          "leagueId": 29,
          "leagueLabel": "English Premier League",
          "group1": "English Premier League",
          "chainVersion": "SXR",
          "participantOneId": 1002,
          "participantTwoId": 998,
          "mainLine": false,
          "sxTeamOneId": 100,
          "sxTeamTwoId": 97,
          "__type": "Market"
        }
      ]
    }
    ```
  </Accordion>

  ### How quarter-lines work

  A bet on a quarter-line market is split by the API into two trades on the surrounding whole and half lines, with half the stake on each at the same odds. A 50 USDC bet on `Brighton -1.25 @ 1.9` is recorded as:

  * 25 USDC on `Brighton -1.0 @ 1.9`
  * 25 USDC on `Brighton -1.5 @ 1.9`

  The two child trades settle independently against the same final score, which reproduces the five quarter-line outcomes that can't be expressed by a single binary market:

  | Result                  | `Brighton -1.0` | `Brighton -1.5` | Net payout on 50 USDC |
  | ----------------------- | --------------- | --------------- | --------------------- |
  | Brighton wins by 2+     | Win             | Win             | 47.50 USDC (full win) |
  | Brighton wins by 1      | Push            | Loss            | 25 USDC (half loss)   |
  | Brighton draws or loses | Loss            | Loss            | 0 USDC (full loss)    |

  ### What this means for integrators

  * A single quarter-line bet appears as:
    * **two entries** in `/trades` — one raw on-chain trade per leg, each on its own leg `marketHash`.
    * **three entries** in `/trades/consolidated` — the two leg consolidated trades (each on its leg `marketHash`) plus a synthetic **parent** consolidated trade keyed to the quarter-line market's `marketHash` and a derived parent `fillHash`. The parent consolidated trade aggregates `totalStake` / `totalReturn` / `netReturn` across the legs and is the entry to use for user-facing P\&L on the bet.
  * Use `quarterLineFillHash` to dedupe `/trades/consolidated` responses: the two leg consolidated trades carry `quarterLineFillHash = <parent fillHash>` while the parent consolidated trade carries `fillHash = <parent fillHash>` and `quarterLineFillHash = null`. Sum just the parents — or just the legs, but never both — when aggregating P\&L or volume.
  * Each child trade settles independently, so a single bet may produce 0–2 settlement transactions depending on the result. The parent entry's settlement state in `/trades/consolidated` reflects the combined outcome once both leg entries have settled.
  * Orderbooks, posting orders, and filling on whole and half lines are unchanged.
</Update>

<Update label="May 4, 2026">
  ## Search fixtures by team name

  New `GET /search` endpoint returns up to 8 active fixtures matching a team name query.

  * **Query:** `query` (required) — team name or partial name, 3–100 characters
  * **Matching:** case-insensitive, partial matches supported
  * **Response:** active fixtures only, ordered by `gameTime`, including `eventId`, both team names, and the list of available market `type` IDs

  ```bash theme={null}
  curl "https://api.sx.bet/search?query=mia"
  ```

  See the [endpoint reference →](/api-reference/search) for the full schema.
</Update>

<Update label="March 24, 2026">
  ## WebSocket API migrating from Ably to Centrifugo

  The new Centrifugo-based WebSocket API is now live. The legacy Ably-based API will continue to run in parallel until **July 1, 2026**, when it will be shut down. All clients must migrate before that date.

  ### What's changing

  * **SDK:** Replace `ably` with `centrifuge`
  * **Auth endpoint:** `GET /user/token` → `GET /user/realtime-token/api-key`
  * **WebSocket URL:** Now explicit — `wss://realtime.sx.bet/connection/websocket`
  * **Channel names:** All channel names have changed (see table below)
  * **Subscription API:** `channel.subscribe(message => ...)` → event-based `sub.on("publication", ctx => ...)`
  * **Gap recovery:** Time-based `rewind` replaced by the snapshot + subscribe pattern using `positioned: true` and `recoverable: true`

  ### Channel name changes

  | Old (Ably)                               | New (Centrifugo)                                         |
  | ---------------------------------------- | -------------------------------------------------------- |
  | `active_orders_v2:{baseToken}:{maker}`   | `active_orders:{maker}`                                  |
  | `order_book_v2:{baseToken}:{marketHash}` | `order_book:market_{marketHash}`                         |
  | `best_odds:{baseToken}`                  | `best_odds:global`                                       |
  | `markets`                                | `markets:global`                                         |
  | `recent_trades`                          | `recent_trades:global`                                   |
  | `recent_trades_consolidated`             | `recent_trades_consolidated:global`                      |
  | `main_line`                              | `main_line:global`                                       |
  | `fixtures:fixture_update`                | `fixtures:global`                                        |
  | `live_scores:{sportXEventId}`            | `fixtures:live_scores` (now global — filter client-side) |
  | `ce_refunds:{user}`                      | `ce_refunds:{bettor}`                                    |
  | `markets:parlay`                         | `parlay_markets:global`                                  |

  New channel: `order_book:event_{sportXEventId}` — subscribes to all markets in an event with a single subscription.

  ### What's improving

  * **Channel capacity:** 512 channels per connection (up from 200)
  * **Throughput:** No per-channel message rate cap (previously 200 msg/sec)
  * **Delivery reliability:** Exact gap recovery using message IDs and server-side history, replacing imprecise time-based rewind

  ### Action required

  Migrate before **July 1, 2026** — that is when the Ably API will be shut down. Message payloads are unchanged — only the SDK, auth flow, channel names, and subscription pattern require updates.

  See the [Migration Guide →](/api-reference/centrifugo-migration) for step-by-step instructions.
</Update>
