In-Game Play-By-Play Predictions#
This feature is BETA
Quarter4's In-game predictions use the power of our AI to give predicted outcomes on a play-by-play level, for each available game. Be among the first to experience our In-game next generation prediction model and help us make it better.
Check back here for changes as new features are added to the In-Game APIs.
Realtime APIs are available at the following endpoint:
https://api.quarter4.io/{sport}/v2/realtime/socket.io
where {sport}
is one of hockey
, basketball
, or american-football
.
The API uses the socket.io client libraries which use a WebSocket connection or, in the case a WebSocket connection is not possible, falls back to HTTP long-polling. It will also automatically try to reconnect if the connection is lost.
Message delay
Results coming into the realtime API are typically delayed about 8-15 seconds from live game play.
The Realtime APIs allow you to follow live play-by-play prediction updates during broadcast games. Not all games are available live. Most professional level games are available and some NCAA level games. You can check using use the sport's Events
Data API to retrieve the information about an event and look for the coverage
attribute with a value of full
.
Supported Events
Only events with full
coverage will have live play-by-play predictions available.
Quickstart#
To connect to the Realtime feed using socket.io, you'll need:
- your API key,
- the Event UUID you'd like to connect to,
- and the appropriate socket.io client libraries are isted here and include:
- JavaScript (which can be run either in Node.js or in React Native)
- Installation steps: https://socket.io/docs/v4/client-installation
- API: https://socket.io/docs/v4/client-api
- Source code: https://github.com/socketio/socket.io-client
- Java: https://github.com/socketio/socket.io-client-java
- C++: https://github.com/socketio/socket.io-client-cpp
- Swift: https://github.com/socketio/socket.io-client-swift
- Dart: https://github.com/rikulo/socket.io-client-dart
- Python: https://github.com/miguelgrinberg/python-socketio
- .Net: https://github.com/doghappy/socket.io-client-csharp
- Rust: https://github.com/1c3t3a/rust-socketio
- Kotlin: https://github.com/icerockdev/moko-socket-io
- JavaScript (which can be run either in Node.js or in React Native)
For example, using Node.js (server-to-server) you would do the following to make a new connection and join the feed for an event:
Danger
You should never include your private API key in public source code. In a production environment you would connect the socket stream server side and then feed the results to your users though your own messaging layers.
io = require("socket.io-client"),
const sport = 'basketball'
const apiKey = 'YOUR_API_KEY'
const eventUuid = 'EVENT_UUID'
const socket = io(server, {
path: "/" + sport + "/v2/realtime/socket.io",
auth: {
api_key: apiKey,
},
});
socket.on("connect", () => {
socket.emit("join", eventUuid);
});
socket.on("play", (item) => {
console.log("play", item, item.message);
});
socket.on("clock", (item) => {
console.log("clock", item, item.message);
});
socket.on("prediction", (item) => {
console.log("prediction", item, item.message);
});
// etc...
socket.connect();
In the above example, you connect to the socket at the endpoint and provide your API Key:
const socket = io(server, {
path: "/" + sport + "/v2/realtime/socket.io",
auth: {
api_key: apiKey,
},
});
Then, when the connection succeeds the connect
event will occur on the socket and you can then join the event you'd like messages for:
socket.on("connect", () => {
socket.emit("join", eventUuid);
});
You then listen for the incoming play
messages and process the message accordingly:
socket.on("play", (item) => {
console.log("play", item, item.message);
});
Message Types#
There are several types of messages in the push feeds. These can be received though the socket by listening for the specific type, for example:
socket.on("play", (item) => {
console.log("play", item, item.message);
});
or by checking the messageType
attribute of the message:
socket.onAny((item) => {
console.log(item.messageType);
});
Warning
Additional message types may be added in the future. If you are using any sort fo catchall for socket messages, your code should check the message type and ignore those that it doesn't understand so that error do not occur when new message types are added.
The play
Message Type#
Supported Leagues: NBA NFL NHL NCAAM
Note
This message type was formerly message
. Both message
and play
will appear in the feed but are identical.
This message type describes the last play and includes a prediction of what to expect for the next play.
Example play
message
{
"uuid": "4dc3347c-9568-458c-a9a4-cd09f0bb12b7",
"sequence": 1675210264293,
"message": "Heat lineup change (Jimmy Butler, Tyler Herro, Caleb Martin, Kyle Lowry, Bam Adebayo). Predicting the Heat to score next (69.85% chance) for 2 points (63.01% chance).",
"prediction": {
"is_home_next_score": "Heat",
"home_next_score": 0.3015226721763611,
"away_next_score": 0.6984773278236389,
"free_throw_make": "No free throws.",
"free_throw_made": 0.3643263578414917,
"free_throw_miss": 0.6356736421585083,
"next_basket_3pt": 0.3699267506599426,
"next_basket_2pt": 0.6300732493400574,
"is_home_win": 0.5882874727249146,
"is_away_win": 0.41171252727508545,
"description": "Predicting the Heat to score next (69.85% chance) for 2 points (63.01% chance)."
},
"play": {
"description": "Heat lineup change (Jimmy Butler, Tyler Herro, Caleb Martin, Kyle Lowry, Bam Adebayo)"
},
"game": {
"id": "585ad812-108f-49ba-a3f8-b632f6f435f3",
"period": 1,
"period_type": "quarter",
"period_sequence": 1,
"clock": "12:00",
"home": {
"id": "bb980b2c-88df-442b-b2d2-97e73c301c1f",
"image": "https://avatar.api.quarter4.io/basketball/avatar/bb980b2c-88df-442b-b2d2-97e73c301c1f/256/logo.png",
"used_timeouts": null,
"remaining_timeouts": null,
"points": 0
},
"away": {
"id": "bb425691-8689-4adc-a9ef-323dc6d8c6c1",
"image": "https://avatar.api.quarter4.io/basketball/avatar/bb425691-8689-4adc-a9ef-323dc6d8c6c1/256/logo.png",
"used_timeouts": null,
"remaining_timeouts": null,
"points": 0
}
},
"messageType": "play"
}
The content of the prediction
attribute will vary by sport.
The clock
Message Type#
Supported Leagues: NBA NFL NHL NCAAM
This message type contains information about the current game clock.
Example clock
message
{
"game": {
"id": "585ad812-108f-49ba-a3f8-b632f6f435f3"
},
"event": {
"id": "585ad812-108f-49ba-a3f8-b632f6f435f3"
},
"clocks": {
"game": "1157",
"running": true,
"shot": "21.00"
},
"period": {
"sequence": 1,
"number": 1,
"type": "REG"
},
"messageType": "clock"
}
The prediction
Message Type#
Supported Leagues: NBA
This message type contains end-of-game team and player predictions, along with the current in-game stats. The messages are sent periodically throughout the game at natural breaks (commercial, timeouts, fouls, etc.). The predicted values will update throughout the game based on the players performance in the game.
Example pediction
message
{
"uuid": "292c8823-7f65-4821-bf40-e9bd70227412",
"players": [
{
"fullName": "Caleb Martin",
"uniform": "16",
"uuid": "1a4e4949-ec7a-4495-8e4b-b03c04dcd34d",
"avatarUrl": "https://avatar.api.quarter4.io/basketball/avatar/bb425691-8689-4adc-a9ef-323dc6d8c6c1/256/uniform/16.png",
"teamName": "Miami Heat",
"position": "SF",
"props": {
"period": 1,
"position": 0,
"points": 0,
"rebounds": 0,
"assists": 0,
"blocks": 0,
"steals": 0,
"turnovers": 0,
"freeThrowsMade": 0,
"freeThrowsAtt": 0,
"fieldGoalsMade": 0,
"fieldGoalsAtt": 0,
"threePointsMade": 0,
"threePointsAtt": 0,
"offensiveRebounds": 0,
"defensiveRebounds": 0,
"personalFouls": 0
},
"predictions": {
"fieldGoalsMadeTotal": 2.729,
"fieldGoalsAttTotal": 6.299,
"freeThrowsMadeTotal": 0.982,
"freeThrowsAttTotal": 0.863,
"threePointsMadeTotal": 1.06,
"threePointsAttTotal": 3.175,
"offensiveReboundsTotal": 0.895,
"defensiveReboundsTotal": 2.61,
"stealsTotal": 0.99,
"blocksTotal": 0.223,
"turnoversTotal": 1.106,
"personalFoulsTotal": 1.883,
"assistsTotal": 0.651,
"reboundsTotal": 3.505,
"pointsTotal": 7.501
}
},
// etc. for each active player in the depth chart...
],
"event": {
"uuid": "585ad812-108f-49ba-a3f8-b632f6f435f3",
"period": 1,
"period_type": "quarter",
"period_sequence": 1,
"clock": "12:00",
"props": {
"overUnder": 223.514,
"homeWinLoss": 0.521314,
"awayWinLoss": 0.478686,
"homeSpread": -1,
"awaySpread": 1,
"winLossSpreadConsistency": 1,
"updatedAt": "2023-01-31T23:43:54",
"probFirstHalfWinHome": 0.483333,
"probFirstHalfWinAway": 0.516667,
"probFirstTo10PointsHome": 0.340476,
"probFirstTo10PointsAway": 0.659524,
"probFirstTo20PointsHome": 0.514286,
"probFirstTo20PointsAway": 0.485714,
"probFirstTo30PointsHome": 0.511905,
"probFirstTo30PointsAway": 0.488095,
"probFirstToEarn3ptHome": 0.545238,
"probFirstToEarn3ptAway": 0.454762,
"probFirstToScoreHome": 0.547619,
"probFirstToScoreAway": 0.452381,
"overtimeProbability": 0.0357143,
"predictAsOvertime": 0,
"homePoints": 0,
"awayPoints": 0,
"period": 1,
"totalScore": 223.514
}
},
"teams": {
"home": {
"location": "Cleveland",
"nickName": "Cavaliers",
"abbreviation": "cle",
"uuid": "bb980b2c-88df-442b-b2d2-97e73c301c1f"
},
"away": {
"location": "Miami",
"nickName": "Heat",
"abbreviation": "mia",
"uuid": "bb425691-8689-4adc-a9ef-323dc6d8c6c1"
}
},
"messageType": "prediction"
}
The status
Message Type#
Supported Leagues: NBA NFL NHL NCAAM
This message type contains the current game status (when it changes). For example when a game switches from inprogress
to halftime
.
Example status
message
{
"uuid": "585ad812-108f-49ba-a3f8-b632f6f435f3",
"status": "inprogress",
"messageType": "status"
}