Publish a match to the system action by action as the match is in progress.
This method instantiates a long running call, which will remain open as long as data is being sent.
There are two different ways to establish a publish connection to the system a HTTP method or a RAW method. These two different ways exists to enable the client to potentially work around any port or proxy problems present at in venue areas. Connections can also be sent over one of two different ports, 80 or 5522
The same data, parameters and format is used in both methods, only the startup of the connection differs.
Note: This call makes use of the streaming API endpoint which differs from the standard API endpoint.
POST /v1/{sport}/publish
In the RAW method, a socket is opened to the streaming API endpoint and the request string is sent, followed by two carriage returns (\n\n
) or two carriage return line feeds (\r\n\r\n
). To initiate RAW mode the nohttp parameter must be present and set in the request string.
/v1/{sport}/publish
Parameter Name | Value | Description |
---|---|---|
Required Parameters | ||
streamKey |
string |
The unique authorisation key that allows the streaming of the match |
timestamp |
integer |
The UNIX timestamp for the current date and time indicating the number of seconds since January 1st 1970 at UTC. The client timestamp must be within 60 seconds of the correct time or else the connection will be refused. |
Optional Parameters | ||
nohttp |
integer |
If set to one then the connection will operate in RAW mode. If this parameter is not present and set to the value of 1, then the connection will operate in HTTP mode regardless of what connection string is sent. |
mode |
string |
The mode of the connection:
|
heartbeat |
integer |
If the value of heartbeat is set to 1, then a heartbeat message will be sent approximately every 10 seconds to the publisher. |
format |
string |
The format the data is being sent in. Options are
|
POST /v1/basketball/publish?streamKey=TESTSTREAMKEY×tamp=1412987153 HTTP/1.1 Host: localhost:8000 Connection: keep-aliveExample - RAW
/v1/basketball/publish?nohttp=1&streamKey=TESTSTREAMKEY×tamp=1412987153
The body of the request should be a series of messages (defined below). Each message must be delimited by a carriage return/line-feed \r\n
series of characters (in hex, 0x0D 0x0A). Consequently this series of characters must not appear in any message content.
The content if each message may be sent in a compressed format to reduce the size of the data being transferred. The message data should be compressed using a gzip/deflate algorithm (http://www.faqs.org/rfcs/rfc1951.html)and then Base64 encoded. Instead of the normal data being the value of the message
key, the compressed data should be the value of a compressedMessage
key.
{ "message": { "type": "master", "format": "json" } }Example - Compressed
{ "compressedMessage": "q1YqqSxIVbJSyk0sLkktUtJRSssvyk0sAYpkFefnKdUCAA==" }
To maintain the open connection at least one message must be sent every 10 seconds. A 'status' message may be sent if no other message needs to be sent.
The session will be closed automatically if it has been open for more than 4 hours, whether data is being sent or not.
For redundancy purposes the system supports multiple connections for the same match from different clients. There can only be one connection in master
mode, all the others must be in backup
mode. If a second connection is made in master
mode, or a connection changed to master
mode then the first master
connection is disconnected.
To monitor the latency of the entire streaming process as well as the connection between the client and the warehouse the latency of the connection is measured. This process involves the sending of a latencyrequest
message from the warehouse to the client. The client should immediately respond with a latencyresponse
message containing the information sent by the warehouse.
Messages should be sent as soon as possible after some kind of action occurs. You only need to send the message types where data has changed.
For example these are the sections you would send for particular events:
scoreboard, boxscore, status, action (Foul), action (PossessionChange)
scoreboard, boxscore, status, action(3pt)
boxscore, action, teams, action(substitution in)
For detailed information about the size and types of the field values, please check the corresponding resource description in the Warehouse API documentation.
This message type changes the mode of the connection from backup
to master
. Any other master
connections will be disconnected.
message |
|||
type |
master |
||
format |
The format the data is being sent in. Options are
|
{ "message": { "type": "master", "format": "json" } }
This message type has the current status of the match.
message |
|||
type |
status |
||
clock |
The current time on the clock. Format MM:SS:CC | ||
shotClock |
The current time on the shot clock. Format MM:SS:CC | ||
clockRunning |
Is the clock currently running? 1 = yes, 0 = no | ||
possession |
The number of the team in the match, 1 or 2 that currently has possession. 0 is valid. | ||
possessionArrow |
The number of the team in the match, 1 or 2 to which the possession Arrow is currently pointing. 0 is valid. | ||
period |
|||
current |
The current period number. Overtime periods start at 1 | ||
periodType |
The type of the current period.
|
||
status |
The current status of the match
|
||
periodStatus |
The current status of the period
|
||
scores |
An array of team records | ||
teamNumber |
The number of the team in the match, 1 or 2. | ||
score |
The total score for that team in the match |
{ "message": { "type": "status", "period": { "current": "1", "periodType": "REGULAR" }, "clock": "10:00:00", "clockRunning": 1, "shotClock": "00:10", "status": "INPROGRESS", "periodStatus": "STARTED", "scores": [ { "teamNumber":1, "score":5 }, { "teamNumber":2, "score":22 } ] } }
This message type has information about the how the match will be run.
message |
|||
type |
setup |
||
periods |
|||
number |
The number of periods | ||
length |
The length of the periods | ||
extraTime |
Is extra time available | ||
extraTimeLength |
The length of the extra time periods | ||
breakPeriod |
The length (in minutes) between periods | ||
breakHalftime |
The length (in minutes) at half time | ||
shotClock |
The length of time (in seconds) for the shotClock | ||
foulsPersonal |
The maximum number of fouls (personal) allowed | ||
foulsTechnical |
The maximum number of fouls (technical) allowed | ||
timeouts |
|||
style |
How are timeouts counted, by period or half | ||
period1 |
The maximum number of timeouts allowed in period 1 | ||
period2 |
The maximum number of timeouts allowed in period 2 | ||
period3 |
The maximum number of timeouts allowed in period 3 | ||
period4 |
The maximum number of timeouts allowed in period 4 | ||
half1 |
The maximum number of timeouts allowed in the first half | ||
half2 |
The maximum number of timeouts allowed in the second half | ||
extraTime |
The maximum number of timeouts allowed in extraTime |
{ "message": { "type": "setup", "periods": { "number":2, "length" : 20, "lengthOvertime" : 5, "breakPeriod" : 2, "breakHalftime" : 2, "overtime : 1 }, "maxFoulsPersonal": "5", "maxFoulsTechnical": "5", "shotClock": "25", "timeouts" : { "style": "period", "half1": "2", "half2": "3", "period1": "2", "period2": "2", "period3": "2", "period4": "2", "extraTime": "1" } } }
This message type defines the teams and players for the match.
It is compulsory to send at least one of these messages.
message |
||||
type |
teams |
|||
teams |
An array of team records | |||
teamNumber |
The number of the team in the match, 1 or 2. | |||
detail |
||||
teamName |
||||
teamId |
Unique identifier for the team (generated by the warehouse system) | |||
teamNickname |
||||
teamCode |
||||
players |
A list of players | |||
pno |
The number of the player in the match. This is a sequence number not a jumper number. | |||
firstName |
||||
familyName |
||||
personId |
Unique identifier for the person (generated by the warehouse system) | |||
shirtNumber |
||||
playingPosition |
||||
height |
||||
active |
Is this player currently active? 1 = yes, 0 = no | |||
captain |
Is this player the captain? 1 = yes, 0 = no | |||
starter |
Is this player a starter? 1 = yes, 0 = no | |||
coach |
||||
personId |
Unique identifier for the person (generated by the warehouse system) | |||
assistcoach1 |
||||
personId |
Unique identifier for the person (generated by the warehouse system) | |||
assistcoach2 |
||||
personId |
Unique identifier for the person (generated by the warehouse system) |
{ "message": { "type": "teams", "teams": [ { "teamNumber": 1, "detail": { "teamName": "Rotherberg Raiders", "teamId": 2065, "teamNickname": "Raiders", "teamCode": "RRD" }, "players": [ { "pno": 1, "firstName": "John", "familyName": "Smith", "personId": 3456, "captain": 1, "active": 1, "starter": 1 }, { "pno": 2, "firstName": "Aaron", "familyName": "Person", "personId": 57564, "captain": 0, "active": 1, "starter": 0 } ], "coach": { "personId": 57564 } }, { "teamNumber": 2, "detail": { "teamName": "Sackville Hawks", "teamId": 2066, "teamNickname": "Hawks", "teamCode": "SVH" }, "players": [ { "pno": 1, "firstName": "Martin", "familyName": "Mann", "personId": 3458, "captain": 1, "active": 1, "starter": 1 }, { "pno": 2, "firstName": "Archie", "familyName": "Person", "personId": 57544, "captain": 0, "active": 1, "starter": 0 } ], "coach": { "personId": 564 } } ] } }
This message type contains the information about the match officials assigned to the match.
On Publish this message type is optional.
message |
|||
type |
officials |
||
commissioner |
|||
personId |
Unique identifier for the person acting as Commissioner (generated by the warehouse system) | ||
firstName |
First name of person acting as Commissioner | ||
familyName |
Family name of person acting as Commissioner | ||
externalId |
ExternalId of person acting as Commissioner | ||
referee1 |
|||
personId |
Unique identifier for the person acting as Referee 1 (generated by the warehouse system) | ||
firstName |
First name of person acting as Referee 1 | ||
familyName |
Family name of person acting as Referee 1 | ||
externalId |
ExternalId of person acting as Referee 1 | ||
referee2 |
|||
personId |
Unique identifier for the person acting as Referee 2 (generated by the warehouse system) | ||
firstName |
First name of person acting as Referee 2 | ||
familyName |
Family name of person acting as Referee 2 | ||
externalId |
ExternalId of person acting as Referee 2 | ||
referee3 |
|||
personId |
Unique identifier for the person acting as Referee 3 (generated by the warehouse system) | ||
firstName |
First name of person acting as Referee 3 | ||
familyName |
Family name of person acting as Referee 3 | ||
externalId |
ExternalId of person acting as Referee 3 |
{ "message": { "type": "officials", "commissioner" : { "personId" : 2345, "name" : "John Smith", "externalId" : "HY3434" }, "referee1" : { "personId" : 34, "name" : "Angus Smythe", "externalId" : "56" }, "referee2" : { "personId" : 987, "name" : "Mary Richardson", "externalId" : "MR8" } } }
This message type has the current score of the match.
message |
||||
type |
scoreboard |
|||
clock |
The current time on the clock. Format MM:SS:CC | |||
shotClock |
The current time on the shot clock. Format MM:SS:CC | |||
period |
||||
current |
The current period number. Overtime periods start at 1 | |||
periodType |
The type of the current period.
|
|||
teams |
List of teams | |||
teamNumber |
The number of the team in the match, 1 or 2. | |||
score |
The total score for that team in the match | |||
periods |
An array of 1 to many periods | |||
period |
||||
periodType |
The type of the period.
|
|||
score |
The score for the team in that period | |||
timeouts |
The number of timeouts taken by the team in the period | |||
fouls |
The number of fouls by the team in the period |
{ "message": { "type": "scoreboard", "period": { "current": "1", "periodType": "OVERTIME" }, "clock": "00:02:00", "teams": [ { "teamNumber": 1, "score": "32", "periods": [ { "period": 1, "periodType": "REGULAR", "timeouts": 0, "fouls": 1, "score": "12" }, { "period": 2, "periodType": "REGULAR", "timeouts": 0, "fouls": 1, "score": "22" }, { "period": 3, "periodType": "REGULAR", "timeouts": 2, "fouls": 3, "score": "25" }, { "period": 4, "periodType": "REGULAR", "timeouts": 0, "fouls": 1, "score": "30" }, { "period": 1, "periodType": "OVERTIME", "timeouts": 1, "fouls": 1, "score": "32" } ] }, { "teamNumber": 2, "score": "35", "timeouts": 2, "fouls": 0, "periods": [ { "period": 1, "periodType": "REGULAR", "timeouts": 2, "fouls": 3, "score": "2" }, { "period": 2, "periodType": "REGULAR", "timeouts": 2, "fouls": 3, "score": "18" }, { "period": 3, "periodType": "REGULAR", "timeouts": 2, "fouls": 3, "score": "23" }, { "period": 4, "periodType": "REGULAR", "timeouts": 2, "fouls": 3, "score": "30" }, { "period": 1, "periodType": "OVERTIME", "timeouts": 2, "fouls": 3, "score": "35" } ] } ] } }
This message type contains the values for the box score (team and player statistics).
message |
|||||
type |
boxscore |
||||
teams |
An array of teams | ||||
teamNumber |
The number of the team in the match, 1 or 2. | ||||
total |
|||||
team |
|||||
statname |
This section can contain any number of team match statistics columns appropriate for the sport (as defined here). | ||||
players |
An array of 1 to many players | ||||
pno |
The number of the player in the match. This is a sequence number not a jumper number. | ||||
statname |
This section can contain any number of person match statistics columns appropriate for the sport (as defined here). | ||||
periods |
Optional. Any period data sent is aggregated with other period data previously sent. So you can send period 1 data in one call and period 2 data in another call. | ||||
period |
The period number. Overtime periods start at 1 | ||||
periodType |
The type of period.
|
||||
team |
|||||
statname |
This section can contain any number of team match statistics columns appropriate for the sport (as defined here). | ||||
players |
An array of 1 to many players | ||||
pno |
The number of the player in the match. This is a sequence number not a jumper number. | ||||
statname |
This section can contain any number of person match statistics columns appropriate for the sport (as defined here). |
{ "message": { "type": "boxscore", "teams": [ { "teamNumber": 1, "total": { "team": { "sTurnovers": 10, "sThreePointersAttempted": 50, "sThreePointersMade": 10 }, "players": [ { "pno": 1, "sFoulsOn": 2, "sBlocks": 3, "sAssists": 2, "sThreePointersAttempted": 10, "sThreePointersMade": 3 }, { "pno": 2, "sFoulsOn": 1, "sBlocks": 6, "sAssists": 4, "sThreePointersAttempted": 4, "sThreePointersMade": 4 } ] }, "periods": [ { "period": 1, "periodType": "REGULAR", "team": { "sTurnovers": 5, "sThreePointersAttempted": 30, "sThreePointersMade": 3 }, "players": [ { "pno": 1, "sFoulsOn": 1, "sBlocks": 2, "sAssists": 0, "sThreePointersAttempted": 5, "sThreePointersMade": 0 }, { "pno": 2, "sFoulsOn": 1, "sBlocks": 0, "sAssists": 2, "sThreePointersAttempted": 2, "sThreePointersMade": 2 } ] }, { "period": 2, "periodType": "REGULAR", "team": { "sTurnovers": 5, "sThreePointersAttempted": 20, "sThreePointersMade": 7 }, "players": [ { "pno": 1, "sFoulsOn": 1, "sBlocks": 1, "sAssists": 2, "sThreePointersAttempted": 5, "sThreePointersMade": 3 }, { "pno": 2, "sFoulsOn": 0, "sBlocks": 6, "sAssists": 2, "sThreePointersAttempted": 2, "sThreePointersMade": 2 } ] } ] }, { "teamNumber": 2, "total": { "team": { "sTurnovers": 9, "sThreePointersAttempted": 49, "sThreePointersMade": 9 }, "players": [ { "pno": 2, "sFoulsOn": 1, "sBlocks": 2, "sAssists": 1, "sThreePointersAttempted": 9, "sThreePointersMade": 2 }, { "pno": 3, "sFoulsOn": 0, "sBlocks": 5, "sAssists": 3, "sThreePointersAttempted": 3, "sThreePointersMade": 3 } ] }, "periods": [ { "period": 1, "periodType": "REGULAR", "team": { "sTurnovers": 2, "sThreePointersAttempted": 45, "sThreePointersMade": 8 }, "players": [ { "pno": 2, "sFoulsOn": 0, "sBlocks": 0, "sAssists": 0, "sThreePointersAttempted": 2, "sThreePointersMade": 0 }, { "pno": 3, "sFoulsOn": 0, "sBlocks": 4, "sAssists": 1, "sThreePointersAttempted": 3, "sThreePointersMade": 3 } ] }, { "period": 2, "periodType": "REGULAR", "team": { "sTurnovers": 7, "sThreePointersAttempted": 4, "sThreePointersMade": 1 }, "players": [ { "pno": 2, "sFoulsOn": 1, "sBlocks": 2, "sAssists": 1, "sThreePointersAttempted": 7, "sThreePointersMade": 2 }, { "pno": 3, "sFoulsOn": 0, "sBlocks": 1, "sAssists": 2, "sThreePointersAttempted": 0, "sThreePointersMade": 0 } ] } ] } ] } }
This message type contains a list of all the actions in the match.
message |
||||
type |
playbyplay |
|||
actions |
A list of actions | |||
actionNumber |
The unique sequence number given to this action | |||
clock |
The current time on the clock. Format MM:SS:CC | |||
shotClock |
The current time on the shot clock. Format MM:SS:CC | timeActual |
The actual time for this action in UTC. Format YYYY-MM-DD HH:MM:SS | |
period |
The period number. Overtime periods start at 1 | |||
periodType |
The type of period.
|
|||
teamNumber |
The team this action relates to. 1 or 2. 0 for not team related actions, eg start gane | |||
pno |
The player this action relates to. The player's number inside the team, not their playing number | |||
actionType |
The type of action occurring. Defined in Action Definitions. | |||
subType |
The subType of action occurring. Defined in Action Definitions. | |||
qualifiers |
A list of qualifiers to the action. Defined in Action Definitions. | |||
score1 |
The score for team number 1 when the action occurred | |||
score2 |
The score for team number 2 when the action occurred | |||
previousAction |
If this action is the result of another action. This field should hold the number of the previous action. | |||
success |
This action was completed successfully. 1 = yes, 0 = no. Generally all actions except shots are successful. | |||
officialId |
The unique identifier for the official that called this action. | |||
area |
The area on the playing surface where the action occurred. Defined in Playing Surface Definition. | |||
x |
The x coordinate for where the action occurred on the playing surface. Defined in Playing Surface Definition. | |||
y |
The y coordinate for where the action occurred on the playing surface. Defined in Playing Surface Definition. | |||
side |
The side of the playing surface, left or right. Defined in Playing Surface Definition. | |||
players |
||||
team1 |
A list of the pnos of the players that were active for team number 1 at the time of the action. | |||
team2 |
A list of the pnos of the players that were active for team number 2 at the time of the action. | |||
edited |
If the action has been edited (after being initially sent) this field should contain the last time it was edited (in UTC). The time should be in the following format (in UTC). Format YYYY-MM-DD HH:MM:SS. If the action has not been edited, then this field is not required. | |||
inserted |
If the action has been inserted (added out of sequence) this field should contain the time it was inserted (in UTC). The time should be in the following format (in UTC). Format YYYY-MM-DD HH:MM:SS. If the action has not been inserted, then this field should not be present. | |||
deleted |
If the action has been deleted (after being initially sent) this field should contain the time it was deleted (in UTC). The time should be in the following format (in UTC). Format YYYY-MM-DD HH:MM:SS. If the action has not been deleted, then this field is not required. | |||
underReview |
1 = yes, 0 = no. The action is not official as yet, it is being review by match officials or the organisation. This may occur in disputed actions or actions being checked by some kind of video. | |||
sendDelay |
Optional. If present, this floating point number represents the number of seconds that have elapsed (at the time of sending the message) since the action occurred. |
{ "message": { "type": "playbyplay", "actions": [ { "actionNumber": 1, "period": 1, "periodType": "REGULAR", "clock": "10:00:00", "timeActual": "2013-08-13 15:56:00", "shotClock": "00:20", "teamNumber": 1, "pno": 1, "score1": "0", "score2": "0", "actionType": "substitution", "subType": "in", "previousAction": 0 }, { "actionNumber": 2, "period": 1, "periodType": "REGULAR", "clock": "09:56:00", "timeActual": "2013-08-13 15:56:00", "shotClock": "00:15", "teamNumber": 1, "pno": 1, "score1": "1", "score2": "2", "actionType": "2pt", "subType": "dunk", "qualifier": ["2ndchance","fastbreak"], "x" : "300", "y" : "400", "side" : "left", "area" : "inthepaint", "previousAction": 0, "success" : 1, "players": { "team1": [ "1", "2", "6", "9", "10" ], "team2": [ "1", "4", "6", "7", "8" ] } }, { "actionNumber": 3, "period": 1, "periodType": "REGULAR", "clock": "09:56:00", "timeActual": "2013-08-13 15:56:00", "shotClock": "00:23", "teamNumber": 1, "pno": 1, "score1": "1", "score2": "2", "actionType": "freethrow", "subType": "1of2", "qualifier": ["turnover"], "x" : "200", "y" : "200", "side" : "left", "area" : "insidecenter", "previousAction": 0, "success" : 1, "players": { "team1": [ 1, 2, 6, 9, 1 ], "team2": [ 1, 4, 6, 7, 8 ] } } ] } }
This message type contains one specific action in the match.
This contains a singular action in the same format as a playbyplay action.
{ "message": { "type": "action", "actionNumber": 1, "period": 1, "periodType": "REGULAR", "clock": "10:00:00", "timeActual": "2013-08-13 15:56:00", "shotClock": "00:20", "teamNumber": 1, "pno": 1, "score1": "0", "score2": "0", "actionType": "substitution", "subType": "in", "previousAction": 0 } }
The client should send this message type in response to a latencyrequest
message.
message |
||||
type |
latencyresponse |
|||
number |
The number provided in the latencyrequest message. |
|||
timestamp |
The UNIX timestamp for the current date and time indicating the number of seconds since January 1st 1970 at UTC. The client timestamp must be within 60 seconds of the correct time or else the connection will be refused. | |||
readDelay |
Optional. The number of seconds the client takes to read information from the connection. Used if the client introduces a delay in reading responses from the server. eg. Only checks the socket every 2 seconds for requests/responses. |
{ "message": { "type": "latencyresponse", "number": 1394569858.9497 } }
The client should send this message to the server when it ends its connection.
message |
||||
type |
disconnection |
|||
reason |
The reason for the disconnection. The options available are:
|
|||
description |
An optional text description giving more information about the reason. |
{ "message": { "type": "disconnect", "reason": "USER_INITIATED", "description" : "User pressed disconnect" } }
While the publish call is primarily about streaming data to the warehouse, the connection is bi-directional and messages will also be sent from the warehouse.
The message type is returned from the warehouse on successful authentication.
{ "message": { "type": "authenticated", } }
The message type is returned from the warehouse on any type of error.
{ "message": { "type": "error", "error": "[message.clockRunning] is missing and it is required" } }
The message type is returned from the warehouse approximately every 10 seconds if the connection is made with the heartbeat parameter set to 1.
{ "message": { "type": "heartbeat", "timestamp": 1413161798.4328 } }
The message type is sent from the warehouse to measure latency for the connection. The client should immediately respond with a lantencyresponse
message.
message |
||||
type |
latencyrequest |
|||
number |
A unique number. This should be immediately returned by the client in a latencyresponse message. |
{ "message": { "type": "latencyrequest", "number": 1394569858.9497 } }