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

# Events

> List current matches with active odds, or fetch every market for a single match.

## GET /api/events

Returns distinct events (matches) that currently have bookmaker odds. Each event has a `slug` you pass to `GET /api/events/{id}` to retrieve all market odds.

### Query Parameters

| Parameter       | Type    | Default | Description                                                    |
| --------------- | ------- | ------- | -------------------------------------------------------------- |
| `sport`         | string  | —       | Filter by sport name (e.g. `Football`, `Basketball`, `Tennis`) |
| `competition`   | string  | —       | Filter by competition code (e.g. `EPL`, `NBA`, `LIG1`)         |
| `bookmaker`     | string  | —       | Only events where this bookmaker has odds                      |
| `is_live`       | boolean | —       | `true` = in-play only, `false` = pre-match only                |
| `stale_minutes` | integer | `10`    | Max age of odds to include (1–60 min)                          |
| `limit`         | integer | `200`   | Max events returned, up to 1000                                |

### Response

```json theme={null}
{
  "data": [
    {
      "slug": "Crystal%20Palace%20-%20West%20Ham%20United",
      "match_name": "Crystal Palace - West Ham United",
      "competition": "EPL",
      "sport": "Football",
      "match_date": "2026-04-20T20:00:00Z",
      "is_live": false,
      "bookmaker_count": 7
    },
    {
      "slug": "PSG%20-%20Lyon",
      "match_name": "PSG - Lyon",
      "competition": "LIG1",
      "sport": "Football",
      "match_date": "2026-04-20T21:00:00Z",
      "is_live": false,
      "bookmaker_count": 5
    }
  ],
  "meta": {
    "count": 1616,
    "rate_limit_remaining": 297
  }
}
```

### Response Fields

| Field             | Type                    | Description                                                         |
| ----------------- | ----------------------- | ------------------------------------------------------------------- |
| `slug`            | string                  | URL-encoded `match_name` — pass to `GET /api/events/{id}`           |
| `match_name`      | string                  | Canonical match name as stored by the scraper (e.g. `"PSG - Lyon"`) |
| `competition`     | string                  | Competition code (e.g. `EPL`, `LIG1`)                               |
| `sport`           | string                  | Sport derived from competition code                                 |
| `match_date`      | ISO-8601 string \| null | Scheduled kick-off time (UTC), null if unknown                      |
| `is_live`         | boolean                 | `true` if any bookmaker has this event live right now               |
| `bookmaker_count` | integer                 | Number of distinct bookmakers covering this event                   |

<Warning>
  The same fixture can appear multiple times with different `match_name` values if different
  bookmakers use different team name formats. Use `bookmaker_count` to identify the canonical
  listing (highest count = most coverage = most canonical name).
</Warning>

***

## GET /api/events/{id}

Returns all bookmaker odds and Pinnacle reference lines for a single event, grouped by `(bookmaker × market_type × period)`. This is the **most granular endpoint** — every odds line for every market from every bookmaker for one match.

### Path Parameter

| Parameter | Description                                                       |
| --------- | ----------------------------------------------------------------- |
| `id`      | URL-encoded match name from the `slug` field in `GET /api/events` |

### Query Parameters

| Parameter       | Type    | Default | Description                                                          |
| --------------- | ------- | ------- | -------------------------------------------------------------------- |
| `bookmaker`     | string  | —       | Filter to a single bookmaker                                         |
| `market_type`   | string  | —       | Filter to a single market type (e.g. `moneyline`, `total`, `spread`) |
| `period`        | integer | —       | Filter to a single period (0=full-time, 1=first-half)                |
| `stale_minutes` | integer | `20`    | Max age of odds to include (1–60 min)                                |

### Response

```json theme={null}
{
  "data": {
    "match_name": "Crystal Palace - West Ham United",
    "competition": "EPL",
    "sport": "Football",
    "match_date": null,
    "slug": "Crystal%20Palace%20-%20West%20Ham%20United",
    "markets": [
      {
        "bookmaker": "Betsson",
        "market_type": "moneyline",
        "period": 0,
        "selections": [
          { "selection": "Crystal Palace", "odds": 3.40 },
          { "selection": "Draw", "odds": 3.25 },
          { "selection": "West Ham United", "odds": 2.10 }
        ],
        "scraped_at": "2026-04-20T14:11:09Z",
        "url": "https://www.betsson.fr/paris-sportifs/event/1234.1"
      },
      {
        "bookmaker": "Betsson",
        "market_type": "total",
        "period": 0,
        "selections": [
          { "selection": "Over 2.5", "odds": 1.87 },
          { "selection": "Under 2.5", "odds": 1.98 }
        ],
        "scraped_at": "2026-04-20T14:11:09Z",
        "url": "https://www.betsson.fr/paris-sportifs/event/1234.1"
      },
      {
        "bookmaker": "Betsson",
        "market_type": "total",
        "period": 1,
        "selections": [
          { "selection": "Over 0.5", "odds": 1.22 },
          { "selection": "Under 0.5", "odds": 3.90 }
        ],
        "scraped_at": "2026-04-20T14:11:09Z",
        "url": "https://www.betsson.fr/paris-sportifs/event/1234.1"
      },
      {
        "bookmaker": "Winamax",
        "market_type": "moneyline",
        "period": 0,
        "selections": [
          { "selection": "Crystal Palace", "odds": 3.35 },
          { "selection": "Draw", "odds": 3.20 },
          { "selection": "West Ham United", "odds": 2.15 }
        ],
        "scraped_at": "2026-04-20T14:07:00Z",
        "url": "https://www.winamax.fr/paris-sportifs/sports/..."
      }
    ],
    "pinnacle": [
      {
        "market_type": "moneyline",
        "period": 0,
        "selections": [
          { "selection": "Crystal Palace", "odds": 3.20 },
          { "selection": "Draw", "odds": 3.15 },
          { "selection": "West Ham United", "odds": 2.00 }
        ],
        "scraped_at": "2026-04-20T13:47:16Z"
      }
    ],
    "summary": {
      "bookmakers": ["1xbet", "Bet365", "Betify", "Betsson", "Cloudbet", "Duel", "Mystake", "Polymarket", "Winamax"],
      "market_types": ["3way_handicap", "btts", "moneyline", "player_prop", "spread", "team_total", "total"],
      "total_markets": 57
    }
  },
  "meta": {
    "rate_limit_remaining": 296
  }
}
```

### `markets` Array Fields

Each object in `markets` represents all the odds a single bookmaker has for one market at one period:

| Field         | Type            | Description                                                                            |
| ------------- | --------------- | -------------------------------------------------------------------------------------- |
| `bookmaker`   | string          | Bookmaker name                                                                         |
| `market_type` | string          | Market type — see [Market Types](/api-reference/introduction#market-types)             |
| `period`      | integer         | Time period — see [Period Values](/api-reference/introduction#period-values)           |
| `selections`  | array           | All outcomes for this market. Each has `selection` (string) and `odds` (decimal float) |
| `scraped_at`  | ISO-8601 string | When this bookmaker's odds were last scraped                                           |
| `url`         | string \| null  | Direct deep-link to the bookmaker's page for this event                                |

### `pinnacle` Array Fields

Same structure as `markets` but without `bookmaker` or `url`. Pinnacle is the **sharp reference line** — it represents the sharpest market consensus. Compare any bookmaker's odds against Pinnacle to estimate edge.

### `summary` Fields

| Field           | Type      | Description                                                        |
| --------------- | --------- | ------------------------------------------------------------------ |
| `bookmakers`    | string\[] | All bookmakers covering this event (sorted alphabetically)         |
| `market_types`  | string\[] | All market types available across all bookmakers (sorted)          |
| `total_markets` | integer   | Total `(bookmaker × market_type × period)` groups in this response |

<Tip>
  **Finding value**: Compare `markets[n].selections[k].odds` against the corresponding selection
  in `pinnacle`. When a bookmaker's odds are higher than Pinnacle's fair price for the same
  outcome, that's a potential +EV opportunity. See `GET /api/value-bets` for pre-calculated
  EV detections.
</Tip>

### Drilldown Examples

```bash theme={null}
# All markets for one event
curl "https://api.oddsstream.io/api/events/Crystal%20Palace%20-%20West%20Ham%20United" \
  -H "X-Api-Key: os_live_YOUR_KEY"

# Moneyline only
curl "https://api.oddsstream.io/api/events/Crystal%20Palace%20-%20West%20Ham%20United?market_type=moneyline" \
  -H "X-Api-Key: os_live_YOUR_KEY"

# Betsson only
curl "https://api.oddsstream.io/api/events/Crystal%20Palace%20-%20West%20Ham%20United?bookmaker=Betsson" \
  -H "X-Api-Key: os_live_YOUR_KEY"

# Betsson's 1st-half totals
curl "https://api.oddsstream.io/api/events/Crystal%20Palace%20-%20West%20Ham%20United?bookmaker=Betsson&market_type=total&period=1" \
  -H "X-Api-Key: os_live_YOUR_KEY"
```

### Full Python Example

```python theme={null}
import requests, urllib.parse

API_KEY = "os_live_YOUR_KEY"
BASE = "https://api.oddsstream.io"

# Step 1: find EPL events
resp = requests.get(
    f"{BASE}/api/events",
    params={"competition": "EPL", "limit": 10},
    headers={"X-Api-Key": API_KEY}
)
events = resp.json()["data"]
print(f"Found {len(events)} EPL events")

# Step 2: pick an event and get all its markets
event = events[0]
slug = event["slug"]  # already URL-encoded

resp2 = requests.get(
    f"{BASE}/api/events/{slug}",
    headers={"X-Api-Key": API_KEY}
)
detail = resp2.json()["data"]
print(f"Match: {detail['match_name']}")
print(f"Bookmakers: {detail['summary']['bookmakers']}")
print(f"Markets available: {detail['summary']['market_types']}")

# Step 3: find all moneyline odds across bookmakers
moneyline_markets = [m for m in detail["markets"] if m["market_type"] == "moneyline" and m["period"] == 0]
for market in moneyline_markets:
    odds_str = ", ".join(f"{s['selection']} {s['odds']}" for s in market["selections"])
    print(f"  {market['bookmaker']}: {odds_str}")
```

### JavaScript Example

```javascript theme={null}
const API_KEY = "os_live_YOUR_KEY";
const BASE = "https://api.oddsstream.io";

// Get all Football events with 5+ bookmakers
const resp = await fetch(`${BASE}/api/events?sport=Football&limit=100`, {
  headers: { "X-Api-Key": API_KEY }
});
const { data: events } = await resp.json();
const deepCoverage = events.filter(e => e.bookmaker_count >= 5);

// Get one event's full detail
const event = deepCoverage[0];
const detailResp = await fetch(`${BASE}/api/events/${event.slug}`, {
  headers: { "X-Api-Key": API_KEY }
});
const { data } = await detailResp.json();

// Compare Betsson moneyline against Pinnacle
const betssonML = data.markets.find(m => m.bookmaker === "Betsson" && m.market_type === "moneyline" && m.period === 0);
const pinnacleML = data.pinnacle.find(p => p.market_type === "moneyline" && p.period === 0);

if (betssonML && pinnacleML) {
  betssonML.selections.forEach(sel => {
    const pin = pinnacleML.selections.find(p => p.selection === sel.selection);
    if (pin && sel.odds > pin.odds) {
      const edge = ((sel.odds / pin.odds) - 1) * 100;
      console.log(`${sel.selection}: Betsson ${sel.odds} > Pinnacle ${pin.odds} (+${edge.toFixed(1)}%)`);
    }
  });
}
```
