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

# Player Props

> Fetch player prop odds including points, rebounds, assists, three-pointers, and combo markets using the V2 markets system.

Player prop markets let you get odds on individual player performance -- points scored, rebounds, assists, and more. TheRundown V2 API models player props as markets with `type` of `TYPE_PLAYER`.

## Player Prop Market IDs

### Individual Stats

| Market | ID | Description |
| - | - | - |
| Player Points | 29 | Over/Under on points scored |
| Player Turnovers | 33 | Over/Under on turnovers |
| Player Rebounds | 35 | Over/Under on rebounds |
| Three Pointers Made | 38 | Over/Under on 3PT made |
| Player Assists | 39 | Over/Under on assists |
| Double Double | 87 | Yes/No on recording a double-double |
| Triple Double | 88 | Yes/No on recording a triple-double |
| Player Blocks | 98 | Over/Under on blocks |

### Combo Markets

Combo markets combine two or three stats into a single over/under line.

| Market | ID | Description |
| - | - | - |
| Player PRA | 93 | Points + Rebounds + Assists combined |
| Player Points + Assists | 99 | Points + Assists combined |
| Player Points + Rebounds | 297 | Points + Rebounds combined |
| Player Rebounds + Assists | 298 | Rebounds + Assists combined |

### Live / In-Play Variants

Live player props use separate market IDs but map to their prematch equivalents.

| Market | ID | Prematch Equivalent |
| - | - | - |
| Live Player Points | 90 | 29 |
| Live Player Assists | 91 | 39 |
| Live Three Pointers | 92 | 38 |
| Live Player Rebounds | 982 | 35 |
| Live Player Blocks | 983 | 98 |
| Live Player Turnovers | 984 | 33 |
| Live Double Double | 985 | 87 |
| Live Triple Double | 986 | 88 |
| Live Player PRA | 987 | 93 |
| Live Player Points + Rebounds | 988 | 297 |
| Live Player Points + Assists | 989 | 99 |
| Live Player Rebounds + Assists | 990 | 298 |

## Discovering Available Prop Markets

The tables above are a reference, but not every sport or event will have every prop market. Use the market discovery endpoints to see which prop markets are currently available.

### By sport and date

Returns all markets with active pricing for a sport on a given date. Filter to player props by checking the `proposition` field — prop markets have `proposition: true`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" "https://therundown.io/api/v2/sports/4/markets/2026-02-12?offset=300"
  ```

  ```python Python theme={null}
  import os
  import requests
  from datetime import date

  API_KEY = os.environ["THERUNDOWN_API_KEY"]
  BASE_URL = "https://therundown.io/api/v2"

  response = requests.get(
      f"{BASE_URL}/sports/4/markets/{date.today()}",
      headers={"X-TheRundown-Key": API_KEY},
      params={"offset": "300"}
  )

  # Response is keyed by sport ID
  for market in response.json().get("4", []):
      if market.get("proposition"):
          print(f"  {market['id']:>4}  {market['name']}")
  ```

  ```javascript Node.js 22+ (server ESM) theme={null}
  const API_KEY = process.env.THERUNDOWN_API_KEY;
  if (!API_KEY) throw Error('Set THERUNDOWN_API_KEY');
  const BASE_URL = "https://therundown.io/api/v2";
  const today = new Date().toISOString().split("T")[0];

  const response = await fetch(
    `${BASE_URL}/sports/4/markets/${today}?offset=300`,
    { headers: { "X-TheRundown-Key": API_KEY } }
  );
  const marketsBySport = await response.json();

  for (const market of marketsBySport["4"] || []) {
    if (market.proposition) {
      console.log(`  ${market.id}  ${market.name}`);
    }
  }
  ```
</CodeGroup>

### By event ID

Returns only the markets available for a specific event. Useful when building a props view for a single game.

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" "https://therundown.io/api/v2/events/EVENT_ID/markets"
  ```

  ```python Python theme={null}
  event_id = "EVENT_ID"
  response = requests.get(
      f"{BASE_URL}/events/{event_id}/markets",
      headers={"X-TheRundown-Key": API_KEY}
  )

  for market in response.json():
      if market.get("proposition"):
          print(f"  {market['id']:>4}  {market['name']}")
  ```

  ```javascript Node.js 22+ (server ESM) theme={null}
  const eventId = "EVENT_ID";
  const response = await fetch(
    `${BASE_URL}/events/${eventId}/markets`,
    { headers: { "X-TheRundown-Key": API_KEY } }
  );
  const markets = await response.json();

  for (const market of markets) {
    if (market.proposition) {
      console.log(`  ${market.id}  ${market.name}`);
    }
  }
  ```
</CodeGroup>

Pass the V2 `event_id` from the event payload into per-event endpoints. Do not substitute `event_uuid`.

Use the discovered market IDs in the `market_ids` parameter when fetching events to get odds for those props.

***

## Fetching Player Props

Request player prop markets by including the relevant `market_ids` in your events request.

<CodeGroup>
  ```bash cURL theme={null}
  # NBA player points, rebounds, assists, and 3PT props
  curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" "https://therundown.io/api/v2/sports/4/events/2026-02-12?\
  market_ids=29,35,38,39&affiliate_ids=19,23&offset=300"
  ```

  ```python Python theme={null}
  import os
  import requests
  from datetime import date

  API_KEY = os.environ["THERUNDOWN_API_KEY"]
  BASE_URL = "https://therundown.io/api/v2"

  # Fetch individual stat props
  PROP_MARKETS = "29,35,38,39"  # Points, Rebounds, 3PT, Assists

  response = requests.get(
      f"{BASE_URL}/sports/4/events/{date.today()}",
      headers={"X-TheRundown-Key": API_KEY},
      params={
          "market_ids": PROP_MARKETS,
          "affiliate_ids": "19,23",
          "offset": "300",
      }
  )

  data = response.json()
  for event in data["events"]:
      home = event["teams"][1]["name"]
      away = event["teams"][0]["name"]
      print(f"\n{'=' * 60}")
      print(f"{away} @ {home}")

      for market in event.get("markets", []):
          print(f"\n  {market['name']} (ID: {market['market_id']})")
          for participant in market["participants"]:
              for line in participant["lines"]:
                  for aff_id, price in line["prices"].items():
                      over_under = "O" if "Over" in participant.get("name", "") or \
                          participant.get("type") == "TYPE_OVER" else "U"
                      print(
                          f"    {participant['name']}: "
                          f"{over_under} {line.get('value', 'N/A')} "
                          f"({price['price']}) @ {aff_id}"
                      )
  ```

  ```javascript Node.js 22+ (server ESM) theme={null}
  const API_KEY = process.env.THERUNDOWN_API_KEY;
  if (!API_KEY) throw Error('Set THERUNDOWN_API_KEY');
  const BASE_URL = "https://therundown.io/api/v2";
  const today = new Date().toISOString().split("T")[0];

  // Fetch individual stat props
  const PROP_MARKETS = "29,35,38,39"; // Points, Rebounds, 3PT, Assists

  const params = new URLSearchParams({
    market_ids: PROP_MARKETS,
    affiliate_ids: "19,23",
    offset: "300",
  });

  const response = await fetch(
    `${BASE_URL}/sports/4/events/${today}?${params}`,
    { headers: { "X-TheRundown-Key": API_KEY } }
  );
  const data = await response.json();

  for (const event of data.events) {
    const away = event.teams[0].name;
    const home = event.teams[1].name;
    console.log(`\n${"=".repeat(60)}`);
    console.log(`${away} @ ${home}`);

    for (const market of event.markets || []) {
      console.log(`\n  ${market.name} (ID: ${market.market_id})`);
      for (const participant of market.participants) {
        for (const line of participant.lines) {
          for (const [affId, price] of Object.entries(line.prices)) {
            const overUnder =
              participant.name.includes("Over") ||
              participant.type === "TYPE_OVER"
                ? "O"
                : "U";
            console.log(
              `    ${participant.name}: ${overUnder} ${line.value ?? "N/A"} (${price.price}) @ ${affId}`
            );
          }
        }
      }
    }
  }
  ```
</CodeGroup>

## Understanding Participants in Player Props

In player prop markets, participants represent the player (not the team). Each participant has:

| Field | Description |
| - | - |
| `id` | Unique numeric identifier for the player |
| `name` | Player name (e.g., "LeBron James") |
| `type` | `TYPE_PLAYER` for player props |

Within each participant, the `lines` array contains the over/under values and their prices from each sportsbook. Each line has a `value` field (a string, e.g., `"25.5"`) and a `prices` map keyed by affiliate ID. Each price object includes the `price`, `is_main_line` boolean, and `updated_at` timestamp.

<Note>
  **Join player props on `participant.id`, not `name`.** For `TYPE_PLAYER` participants, `id` is the stable player ID — the same key used everywhere else in the API. Fetch the full player record (team, names, position) at `GET /api/v2/players/{player_id}`. Because each player has a distinct `id`, joining on `id` resolves shared-name collisions that joining on `name` cannot. To resolve a name to an `id` once, use the roster at `GET /api/v2/teams/{team_id}/players`. You can also narrow the response server-side with `participant_ids` (comma-separated, max 99) and `participant_type=TYPE_PLAYER`. See the [Participant object](/reference/data-model#participant-object) reference for full definitions.
</Note>

### Example Response Structure

```json theme={null}
{
  "market_id": 29,
  "name": "Player Points",
  "period_id": 0,
  "participants": [
    {
      "id": 12345,
      "name": "LeBron James Over",
      "type": "TYPE_OVER",
      "lines": [
        {
          "value": "25.5",
          "prices": {
            "19": { "price": -115, "is_main_line": true, "updated_at": "2026-02-12T18:30:00Z" },
            "23": { "price": -110, "is_main_line": true, "updated_at": "2026-02-12T18:29:45Z" }
          }
        }
      ]
    },
    {
      "id": 12345,
      "name": "LeBron James Under",
      "type": "TYPE_UNDER",
      "lines": [
        {
          "value": "25.5",
          "prices": {
            "19": { "price": -105, "is_main_line": true, "updated_at": "2026-02-12T18:30:00Z" },
            "23": { "price": -110, "is_main_line": true, "updated_at": "2026-02-12T18:29:45Z" }
          }
        }
      ]
    }
  ]
}
```

## Fetching Combo Props

Combo markets combine multiple stats. The request pattern is the same -- just use the combo market IDs.

<CodeGroup>
  ```python Python theme={null}
  # Fetch combo props: PRA, PA, PR, RA
  COMBO_MARKETS = "93,99,297,298"

  response = requests.get(
      f"{BASE_URL}/sports/4/events/{date.today()}",
      headers={"X-TheRundown-Key": API_KEY},
      params={
          "market_ids": COMBO_MARKETS,
          "affiliate_ids": "19",
      }
  )

  data = response.json()
  for event in data["events"]:
      print(f"\n{event['teams'][0]['name']} @ {event['teams'][1]['name']}")
      for market in event.get("markets", []):
          print(f"\n  {market['name']}:")
          for participant in market["participants"]:
              for line in participant["lines"]:
                  price_obj = line["prices"].get("19", {})
                  price = price_obj.get("price", "N/A")
                  print(f"    {participant['name']}: {line.get('value')} ({price})")
  ```

  ```javascript Node.js 22+ (server ESM) theme={null}
  // Fetch combo props: PRA, PA, PR, RA
  const COMBO_MARKETS = "93,99,297,298";

  const params = new URLSearchParams({
    market_ids: COMBO_MARKETS,
    affiliate_ids: "19",
  });

  const response = await fetch(
    `${BASE_URL}/sports/4/events/${today}?${params}`,
    { headers: { "X-TheRundown-Key": API_KEY } }
  );
  const data = await response.json();

  for (const event of data.events) {
    console.log(`\n${event.teams[0].name} @ ${event.teams[1].name}`);
    for (const market of event.markets || []) {
      console.log(`\n  ${market.name}:`);
      for (const participant of market.participants) {
        for (const line of participant.lines) {
          const price = line.prices["19"]?.price ?? "N/A";
          console.log(`    ${participant.name}: ${line.value} (${price})`);
        }
      }
    }
  }
  ```
</CodeGroup>

## Fetching All Props at Once

You can request all prop market IDs in a single call. This is useful if you want to build a comprehensive player props page.

```bash theme={null}
# All individual + combo props
curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" "https://therundown.io/api/v2/sports/4/events/2026-02-12?\
market_ids=29,33,35,38,39,87,88,93,98,99,297,298\
&affiliate_ids=19,23"
```

## Live Player Props

Live player props are available once a game starts. Use the live market IDs to fetch in-play prop odds.

```bash theme={null}
# Live player points (90), assists (91), 3PT (92)
curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" "https://therundown.io/api/v2/sports/4/events/2026-02-12?\
market_ids=90,91,92&affiliate_ids=19"
```

You can also subscribe to live prop updates via the V2 Markets WebSocket. WebSocket access requires an Ultra plan or higher; run this Node.js 22+ client on your server and install its dependency with `npm install ws`. Native browser WebSocket clients cannot set the authentication header, so browser consumers should use an authenticated backend relay.

```javascript Node.js 22+ (ws) theme={null}
const WebSocket = require("ws");
const API_KEY = process.env.THERUNDOWN_API_KEY;
if (!API_KEY) throw Error('Set THERUNDOWN_API_KEY');

const ws = new WebSocket(
  "wss://therundown.io/api/v2/ws/markets?sport_ids=4&market_ids=90,91,92",
  { headers: { "X-TheRundown-Key": API_KEY } }
);

ws.on("message", (raw) => {
  const data = JSON.parse(raw.toString());
  if (data.meta?.type === "heartbeat") return;

  console.log(`Live prop update: market=${data.market_id}`);
  for (const participant of data.participants || []) {
    console.log(`  ${participant.name}`);
  }
});
```

## Building a Player Props Display

Here is a complete example that organizes props by player for display in a UI.

```python theme={null}
import os
import requests
from collections import defaultdict
from datetime import date

API_KEY = os.environ["THERUNDOWN_API_KEY"]
BASE_URL = "https://therundown.io/api/v2"

MARKET_NAMES = {
    29: "Points", 35: "Rebounds", 38: "3PT Made",
    39: "Assists", 93: "PRA", 98: "Blocks",
    99: "Pts+Ast", 297: "Pts+Reb", 298: "Reb+Ast",
}

response = requests.get(
    f"{BASE_URL}/sports/4/events/{date.today()}",
    headers={"X-TheRundown-Key": API_KEY},
    params={
        "market_ids": ",".join(str(m) for m in MARKET_NAMES),
        "affiliate_ids": "19",
        "main_line": "true",
    }
)

data = response.json()

for event in data["events"]:
    home = event["teams"][1]["name"]
    away = event["teams"][0]["name"]
    print(f"\n{'=' * 60}")
    print(f"{away} @ {home}")
    print(f"{'=' * 60}")

    # Group props by player
    players = defaultdict(list)

    for market in event.get("markets", []):
        mid = market["market_id"]
        market_label = MARKET_NAMES.get(mid, market["name"])

        for participant in market["participants"]:
            # Extract player name (remove "Over"/"Under" suffix)
            player_name = participant["name"]
            for suffix in [" Over", " Under"]:
                player_name = player_name.replace(suffix, "")

            is_over = "Over" in participant.get("name", "") or \
                participant.get("type") == "TYPE_OVER"

            for line in participant["lines"]:
                price_obj = line["prices"].get("19", {})
                price = price_obj.get("price")
                if price == 0.0001:
                    price = None

                players[player_name].append({
                    "market": market_label,
                    "value": line.get("value"),
                    "side": "Over" if is_over else "Under",
                    "price": price,
                })

    # Display grouped by player
    for player, props in sorted(players.items()):
        print(f"\n  {player}:")
        for prop in props:
            price_str = f"{prop['price']:+d}" if prop["price"] else "N/A"
            print(f"    {prop['market']}: {prop['side']} {prop['value']} ({price_str})")
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Market IDs Reference" icon="hashtag" href="/reference/markets">
    Full list of all market IDs
  </Card>

  <Card title="Getting Live Odds" icon="signal" href="/guides/getting-live-odds">
    Core game odds (moneyline, spread, total)
  </Card>

  <Card title="WebSocket Streaming" icon="bolt" href="/guides/websocket-streaming">
    Real-time updates for live props
  </Card>

  <Card title="Historical Odds" icon="chart-line" href="/guides/historical-odds">
    Track prop line movement over time
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.