Documentation

PulseScore API Docs

Everything you need to integrate real-time Bet365 odds into your application. REST API, WebSocket, and code examples for every major language.

Bookmaker API References

Quick Start

Get live odds data in 3 steps:

  1. Create an account - Sign up at pulsescore.net (free BASIC plan: 500 requests/month)
  2. Generate an API key - Go to Dashboard → Generate API Key
  3. Make your first call - Use the key in the X-Secret header
Your first request
curl -X GET "https://api.pulsescore.net/api/v2/bet365/live-events?sport=soccer" \
  -H "X-Secret: YOUR_API_KEY"

Authentication

All API requests require an API key passed in the request header:

HeaderValue
X-SecretYour API key from the dashboard

API keys can be generated and revoked from your dashboard. Keep your keys secret - do not expose them in client-side code.

REST API

The REST API returns JSON responses. All endpoints use the base URL:

text
https://api.pulsescore.net/api/v2/bet365

Standard HTTP status codes indicate success or failure. Responses are returned as JSON arrays or objects.

Endpoints

Live Events

GET/live-events

Fetch all currently live events with real-time odds and market groups.

Parameters

NameTypeRequiredDescription
sportstringNoFilter by sport: soccer (default), tennis, basketball, ice-hockey, volleyball, handball, table-tennis, e-sports, american-football, baseball, rugby-league, rugby-union

Response

json
[
  {
    "fi": "98734521",
    "sport": "Soccer",
    "league": "Premier League",
    "home": "Liverpool",
    "away": "Man City",
    "live": 1,
    "tab": "Popular",
    "mg": [
      {
        "name": "Fulltime Result",
        "ma": [
          { "name": "Liverpool", "pa": [{ "decimal": "2.10" }] },
          { "name": "Draw", "pa": [{ "decimal": "3.40" }] },
          { "name": "Man City", "pa": [{ "decimal": "3.25" }] }
        ]
      },
      {
        "name": "Over/Under 2.5 Goals",
        "ma": [
          { "name": "Over 2.5", "pa": [{ "decimal": "1.75" }] },
          { "name": "Under 2.5", "pa": [{ "decimal": "2.05" }] }
        ]
      }
    ]
  }
]
GET/live-events/sports

Get a list of all sports that currently have live events.

Response

json
[
  { "sport": "Soccer", "count": 42 },
  { "sport": "Tennis", "count": 18 },
  { "sport": "Basketball", "count": 8 }
]
GET/live-events/:id

Fetch a single live event by its ID.

Parameters

NameTypeRequiredDescription
idstringYesEvent ID from /live-events response

Response

json
{
  "fi": "98734521",
  "sport": "Soccer",
  "league": "Premier League",
  "home": "Liverpool",
  "away": "Man City",
  "live": 1,
  "mg": [ ... ]
}

Pre-Match (by Sport)

Pre-match data is organized by sport. Replace {sport} with: soccer (root), tennis, basketball, ice-hockey, american-football, horse-racing, volleyball, handball, table-tennis, e-sports, baseball, greyhounds. Soccer uses the root path (no sport prefix).

GET/{sport}/leagues

Get all available leagues for a sport. For soccer, use /leagues (no prefix).

Response

json
[
  {
    "league": "Premier League",
    "sport": "Soccer",
    "live": 0,
    "events": [
      { "home": "Arsenal", "away": "Chelsea", "fi": "45921003" },
      { "home": "Liverpool", "away": "Tottenham", "fi": "45921004" }
    ]
  }
]
GET/{sport}/events

Get events for a specific league. For soccer, use /events (no prefix).

Parameters

NameTypeRequiredDescription
leaguestringYesLeague name from /leagues response
tabstringNoMarket tab filter (e.g., Popular)

Response

json
[
  {
    "fi": "45921003",
    "sport": "Soccer",
    "league": "Premier League",
    "home": "Arsenal",
    "away": "Chelsea",
    "live": 0,
    "tab": "Popular",
    "mg": [
      {
        "name": "Fulltime Result",
        "ma": [
          { "name": "Arsenal", "pa": [{ "decimal": "2.30" }] },
          { "name": "Draw", "pa": [{ "decimal": "3.20" }] },
          { "name": "Chelsea", "pa": [{ "decimal": "3.10" }] }
        ]
      }
    ]
  }
]
GET/{sport}/events/:fi

Fetch a single pre-match event by fixture ID. For soccer, use /events/:fi.

Parameters

NameTypeRequiredDescription
fistringYesFixture ID from /leagues or /events response

Response

json
{
  "fi": "45921003",
  "sport": "Soccer",
  "league": "Premier League",
  "home": "Arsenal",
  "away": "Chelsea",
  "live": 0,
  "mg": [ ... ]
}

WebSocket

The WebSocket feed provides real-time streaming of all in-play events for a chosen bookmaker and sport. Server pushes a frame every ~2 seconds containing every live event for the subscribed sport. Available on PRO and MAX plans.

Endpoints by Bookmaker

BookmakerURL
Bet365wss://api.pulsescore.net/api/v2/bet365/ws/live
Unibet AUwss://api.pulsescore.net/api/unibetau/ws/live
Fanduelwss://api.pulsescore.net/api/fanduel/ws/live
Bwinwss://api.pulsescore.net/api/bwin/ws/live

All endpoints require ?key=YOUR_API_KEY&sport=SPORT as query parameters.

Valid Sports per Bookmaker

BookmakerSports
Bet365soccer, basketball, tennis, ice-hockey, rugby-league, rugby-union, volleyball, handball, table-tennis, e-sports, american-football, baseball, greyhounds, horse-racing
Unibet AUsoccer, basketball, tennis, ice-hockey, baseball, american-football, horse-racing, greyhounds
Fanduelsoccer, basketball, tennis, ice-hockey, baseball, american-football, cricket
Bwinsoccer, basketball, tennis, ice-hockey, baseball, american-football, cricket

Query Parameters

ParamRequiredDescription
keyYesYour API key
sportYesSport to stream (soccer, tennis, etc.)

Message Format

On successful connection, the server sends a confirmation message:

json
{ "type": "connected", "bookmaker": "fanduel", "sport": "soccer", "plan": "pro" }

Then every ~2 seconds, the server pushes a frame containing all live events for the subscribed sport:

json
{
  "sport": "soccer",
  "timestamp": 1709474521000,
  "count": 12,
  "data": [
    {
      "id": "98734521",
      "sport": "Soccer",
      "league": "Premier League",
      "home": "Liverpool",
      "away": "Man City",
      "score": "1-0",
      "mg": [
        {
          "name": "Fulltime Result",
          "ma": [
            { "name": "Liverpool", "pa": [{ "decimal": "2.10" }] },
            { "name": "Draw", "pa": [{ "decimal": "3.40" }] },
            { "name": "Man City", "pa": [{ "decimal": "3.25" }] }
          ]
        }
      ]
    }
  ]
}

Connection Limits

PlanMax Connections
BASIC (Free)0 (REST only)
STARTER (€20/mo)0 (REST only)
PRO1 concurrent
MAX3 concurrent

Code Examples

cURL

bash
# Fetch live soccer events
curl -X GET "https://api.pulsescore.net/api/v2/bet365/live-events?sport=soccer" \
  -H "X-Secret: YOUR_API_KEY"

# Fetch soccer leagues (pre-match)
curl -X GET "https://api.pulsescore.net/api/v2/bet365/leagues" \
  -H "X-Secret: YOUR_API_KEY"

# Fetch events for a league
curl -X GET "https://api.pulsescore.net/api/v2/bet365/events?league=Premier%20League" \
  -H "X-Secret: YOUR_API_KEY"

# Fetch tennis leagues
curl -X GET "https://api.pulsescore.net/api/v2/bet365/tennis/leagues" \
  -H "X-Secret: YOUR_API_KEY"

# Fetch a single event by fixture ID
curl -X GET "https://api.pulsescore.net/api/v2/bet365/events/98734521" \
  -H "X-Secret: YOUR_API_KEY"

Python

python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.pulsescore.net/api/v2/bet365"

# Fetch live events
response = requests.get(
    f"{BASE_URL}/live-events",
    headers={"X-Secret": API_KEY},
    params={"sport": "soccer"}
)

events = response.json()
for event in events:
    home = event["home"]
    away = event["away"]
    for mg in event["mg"]:
        print(f"{home} vs {away} — {mg['name']}")
        for ma in mg["ma"]:
            odds = ma["pa"][0]["decimal"]
            print(f"  {ma['name']}: {odds}")

Node.js

javascript
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.pulsescore.net/api/v2/bet365";

// Fetch live events
const response = await fetch(`${BASE_URL}/live-events?sport=soccer`, {
  headers: { "X-Secret": API_KEY },
});

const events = await response.json();

for (const event of events) {
  console.log(`${event.home} vs ${event.away}`);
  for (const mg of event.mg) {
    console.log(`  ${mg.name}:`);
    for (const ma of mg.ma) {
      console.log(`    ${ma.name}: ${ma.pa[0].decimal}`);
    }
  }
}

WebSocket (Node.js)

javascript
const WebSocket = require("ws");

const API_KEY = "YOUR_API_KEY";

// All bookmakers with live WebSocket support
const ENDPOINTS = {
  bet365:   "wss://api.pulsescore.net/api/v2/bet365/ws/live",
  unibetau: "wss://api.pulsescore.net/api/unibetau/ws/live",
  fanduel:  "wss://api.pulsescore.net/api/fanduel/ws/live",
  bwin:     "wss://api.pulsescore.net/api/bwin/ws/live",
};

const bookmaker = "fanduel"; // bet365 | unibetau | fanduel | bwin
const sport = "soccer";
const ws = new WebSocket(
  `${ENDPOINTS[bookmaker]}?key=${API_KEY}&sport=${sport}`
);

ws.on("open", () => {
  console.log(`Connected to ${bookmaker} (${sport})`);
});

ws.on("message", (raw) => {
  const msg = JSON.parse(raw);
  if (msg.type === "connected") {
    console.log(`Subscribed to ${msg.bookmaker} ${msg.sport} (plan: ${msg.plan})`);
    return;
  }
  // Broadcast frame
  console.log(`${msg.count} live ${msg.sport} events`);
  for (const event of msg.data) {
    console.log(`  ${event.home} vs ${event.away}`);
  }
});

ws.on("close", (code, reason) => {
  console.log(`Disconnected: ${code} ${reason}`);
});

WebSocket (Python)

python
import asyncio
import json
import websockets

API_KEY = "YOUR_API_KEY"

# All bookmakers with live WebSocket support
ENDPOINTS = {
    "bet365":   "wss://api.pulsescore.net/api/v2/bet365/ws/live",
    "unibetau": "wss://api.pulsescore.net/api/unibetau/ws/live",
    "fanduel":  "wss://api.pulsescore.net/api/fanduel/ws/live",
    "bwin":     "wss://api.pulsescore.net/api/bwin/ws/live",
}

BOOKMAKER = "fanduel"  # bet365 | unibetau | fanduel | bwin
SPORT = "soccer"
URL = f"{ENDPOINTS[BOOKMAKER]}?key={API_KEY}&sport={SPORT}"

async def stream():
    async with websockets.connect(URL) as ws:
        print(f"Connected to {BOOKMAKER} ({SPORT})")
        async for message in ws:
            msg = json.loads(message)
            if msg.get("type") == "connected":
                print(f"Subscribed to {msg['bookmaker']} {msg['sport']} (plan: {msg['plan']})")
                continue
            # Broadcast frame
            for event in msg["data"]:
                print(f"{event['home']} vs {event['away']}")

asyncio.run(stream())

Error Codes

CodeMeaning
200Success
401Invalid or missing API key
403Access denied (plan restriction)
404Resource not found
429Rate limit exceeded
500Internal server error

WebSocket Close Codes

CodeMeaningRetry?
4001Authentication failedNo
4003Plan too low (PRO or MAX required)No
4004Invalid sport for this bookmakerNo
4010Subscription expiredNo
4011Plan downgrade - reconnect requiredYes
4012Session replaced by new connectionYes
4029Connection limit reachedNo

Rate Limits

PlanRequestsRate (per bookmaker)WebSocketPrice
BASIC500/month1 req/secNoneFree
STARTER30,000/month1 req/minNone€20/mo
PROUnlimited1 req/sec1 connection€79/mo
MAXUnlimited3 req/sec3 connections€149/mo

Rate-limited requests return HTTP 429. Implement exponential backoff for retries. WebSocket connections automatically receive updates - no polling needed.