Data Overview

ShotTracker is a sensor based system that captures team and player stats in real time. The data that ShotTracker captures is used to build box scores, plot shots and show player and ball movement. ShotTracker data is broken down into 3 main categories, stats, shots and locations.

Stats

The system will emit all box score stats under the following abbreviations:

Stat Name Description
FGA field goal attempt
FG field goal
FGA3 3 point field goal attempt
FG3 3 point field goal
FTA free throw attempt
FT free throw
PTS points
AST assist
TO turnover
STL steal
REB rebound
OFFENSIVE_REB offensive rebound; typically paired with a REB to give more context
DEFENSIVE_REB defensive rebound; typically paired with a REB to give more context
DIST distance traveled in cm

In most cases, the stats will be paired together to represent the most current value(s) on the box score for the given player. Stats data will be paired together in single response; the example JSON snippet below represents a made field goal attempt:

{“type”:“stats”,“data”:{“occurred_at”:1500571319432,“team_id”:461,“player_id”:2623,“stats”:{“FGA”:15.0,“FG”:8.0,“PTS”:17.0},“classification”:“TWO_POINT_MAKE”,“version”:1941}}

The values in the above example reflect the most current stat values that would be reflective on the players box score.

Stats can also change with a manual correction. This means the example above would change to the following if the shot is deleted:

{“type”:“stats”,“data”:{“occurred_at”:1500571319432,“team_id”:461,“player_id”:2623,“stats”:{“FGA”:14.0,“FG”:7.0,“PTS”:15.0},“classification”:“DELETED_TWO_POINT_MAKE”,“version”:1942}}

Both adding and deleting of the field goal looks the same in the paired together stats response. As a result a classification field is added to each stats response to give more context around what the collected stats values represent. The following are all of the classification values:

Classification Value Description
FREE_THROW_MISS Missed free throw
FREE_THROW_MAKE Made free throw
TWO_POINT_MISS Missed field goal
TWO_POINT_MAKE Made field goal
THREE_POINT_MISS Missed 3 point field goal
THREE_POINT_MAKE Made 3 point field goal
ASSIST Assist
TURNOVER Turnover
STEAL Steal
REBOUND Rebound
OFFENSIVE_REBOUND Offensive rebound
DEFENSIVE_REBOUND Defensive rebound
DISTANCE Distance traveled
DELETED_FREE_THROW_MISS Deleted missed free throw
DELETED_FREE_THROW_MAKE Deleted made free throw
UPDATED_FREE_THROW_MAKE_TO_MISS Updated free throw make to miss
UPDATED_FREE_THROW_MISS_TO_MAKE Updated free throw miss to make
DELETED_TWO_POINT_MISS Deleted missed field goal
DELETED_TWO_POINT_MAKE Deleted made field goal
UPDATED_TWO_POINT_MAKE_TO_MISS Updated field goal from make to miss
UPDATED_TWO_POINT_MISS_TO_MAKE Updated field goal from miss to make
DELETED_THREE_POINT_MISS Deleted missed 3 point field goal
DELETED_THREE_POINT_MAKE Deleted made 3 point field goal
UPDATED_THREE_POINT_MAKE_TO_MISS Updated 3 point field goal from make to miss
UPDATED_THREE_POINT_MISS_TO_MAKE Updated 3 point field goal from miss to make
DELETED_ASSIST Deleted assist
DELETED_TURNOVER Deleted turnover
DELETED_STEAL Deleted steal
DELETED_REBOUND Deleted rebound
DELETED_OFFENSIVE_REBOUND Deleted offensive rebound
DELETED_DEFENSIVE_REBOUND Deleted defensive rebound

Shots

Shots are location data for each made and missed shot including the ShotTracker zone. Below is an example shot:

{“type”:“shot”,“data”:{“occurred_at”:1500571319432,“team_id”:461,“player_id”:2623,“is_make”:true,“is_3point”:false,“zone”:1,“hoop_player_x”:685,“hoop_player_y”:-475,“status”:“RECORDED”}}

Shot data contains a hoop_player_x and hoop_player_y that represents the xy location of the shot from the hoop. Representing a shot from the hoop assumes that the positive y runs from the hoop to the center of the court and positive x runs from the hoop to the right. Shots are also assigned a zone number 1 - 14 that represents the specific location around the hoop the shot occurred. The map below shows the shot locations.

zonemap

Note: All xy data is returned as mm.

Locations

The location data contains plotable xyz data for each player and ball on the court. Below are a few examples:

{“type”:“location”,“data”:{“occurred_at”:1500571321532,“type”:“PLAYER”,“id”:2942,“x”:2314,“y”:-8635,“z”:69}}

{“type”:“location”,“data”:{“occurred_at”:1500571321532,“type”:“BALL”,“id”:2147549498,“x”:-6039,“y”:-8833,“z”:1705}}

The type denotes what sensor; either the player or ball. The id in the PLAYER event relates to the player list from the subscription request. Lastly, the xyz reflects the current location of the sensor at the given occurred_at.

Note: All xyz data is returned as mm.

API Overview

The ShotTracker API consists of REST endpoints and websockets to deliver data in realtime. The API reference is broken down into the following sections:

Use Cases

Access to ShotTracker data can drive applications and solutions that do the following:

  • Display a leaderboard for team and player stats over the course of a season or a real time event.

  • Analyze stats and shots to reflect trends over the course of a season or a real time event.

  • Show live player movement in applications, broadcast or augmented reality solutions.

  • Analyze team and player movement for trends.

Authentication

All requests to the REST API must be signed using the ShotTracker issued username and secret. A ShotTracker API username/secret pair contains specific privileges; be sure to keep both secured.

Signing a request is done using HMAC. The following headers are needed for signing and required to be sent with each request.

Header Name Description
date Standard UTC date; be sure to keep the current time as the clock must not skew more than 5 minutes
host The servers host
Authorization The full hmac value with signature; see example below

Below is a nodejs example illustrating the data required and how to formulate the data into the signing stream.

var crypto = require("crypto");

var userName = 'ShotTracker supplied user name here';
var secret = 'ShotTracker supplied secret here';
var host = 'devapi.shottracker.com';
var path = '/v1/data/live/_search';
var method = 'GET';
var date = new Date().toUTCString();

var requestLine = method + ' ' + path + ' HTTP/1.1';
var stringToSign = 'date: ' + date.trim() + '\n'
                 + 'host: ' + host + '\n'
                 + requestLine;
var encodedSignature = crypto.createHmac("sha1", secret).update(stringToSign).digest("base64");
var hmacAuth = 'hmac username="' + userName + '",algorithm="hmac-sha1",headers="date host request-line",signature="' + encodedSignature + '"';

console.log('date: ' + date);
console.log('Authorization: ' + hmacAuth);

Note Only the API (REST Resources) require a signed request. Authentication to the websocket is done by only providing the acquired subscription token.

Environment Endpoints

Getting Started

When working with live data, how to get the data during the development cycle is the first step. To get started there is a ShotTracker mock service which plays a continuous loop of live data.

mock example

The data is only a few minutes in length and represents a portion of a live practice scrimmage. The mock service does not expose the Live Notification endpoints directly but they can be simulated. To simulate sending notifications from the mock service, the following mock service endpoints may be used. Please contact ShotTracker to obtain the {key}.

Start Notify

PUT http://mockapi.shottracker.com:8080/mock/{key}/do/live/notify/start?url={your notify url}

End Notify

PUT http://mockapi.shottracker.com:8080/mock/{key}/do/live/notify/end?url={your notify url}

Mock Service Endpoints

Mock Service Security

The mock service offers both a “Security Required” and “No Security Required” REST API access. “Security Required” means the request must contain the Authorization header. The “No Security Required” endpoint gives a developer the freedom to work with data and introduce authentication at a later point in the development cycle. In the non-mock environments all REST API’s are “Security Required”.

Below is the username and secret to use with the Security Required Mock Service API.

username: 2e4118d42e5011e6b4a4deecc6e6f587
secret: 2d64b892e8d434100001

Important The above username and secret is restricted only to the mock service. For access to the non-mock environments please contact ShotTracker to obtain a username and secret.

Quickstart Examples

Subscribing to Live Event

Below is a nodejs example that brings together using the REST endpoints and migrating controller to the websocket to consume the live stats, shots and player/ball locations.

var http = require('http')
var WebSocket = require('ws');

function subscribeToEvent(liveId, callback) {
  var options = {
      host: 'mockapi.shottracker.com',
      port: 8080,
      path: `/v1/data/live/${liveId}/_subscribe`,
      method: 'GET',
      headers: {
        Accept: 'application/json',
      }
    }

    console.log(`Requesting token from ${options.host}`)

    http.request(options, function(response) {
      var subscribeResponseData = '';
      response.on('data', function (chunk) {
        subscribeResponseData += chunk;
      });

      response.on('end', function () {
          var liveToken = JSON.parse(subscribeResponseData).token
          console.log(`Got token ${liveToken}`)
          callback(`ws://mocklive.shottracker.com:8081/?token=${liveToken}`);
      });
    }).end();
}

function establishWebsocketConnection(url) {
  console.log(`Connecting to ${url}`);
  wsConnection = new WebSocket(url);
  wsConnection.addEventListener('open', function(event){
    sendPing(this);
  });
  wsConnection.addEventListener('message', function(payload){
    console.log(payload.data);
    // TODO: Handle payload data
  });
}

function sendPing(conn) {
  setInterval(function(){
    conn.send(JSON.stringify({action: 'ping'}));
  },60000);
}

var liveIdFromSearchOrNotify = 'test'
subscribeToEvent(liveIdFromSearchOrNotify, establishWebsocketConnection);

Team Player Stats

The following command will retrieve team player stats over the from/to range.

curl -X GET "http://mockapi.shottracker.com:8080/v1/data/teams/490/players/practice/stats?from=1530403200000&to=1531353600000"

Team Events

The following command will retrieve past events over the from/to range.

curl -X GET "http://mockapi.shottracker.com:8080/v1/data/teams/490/events?from=1522540800000&to=1525132800000"

Live

The Live services allow a consumer to discover an existing live event and obtain the needed meta-data about the team and players. If the event is in the middle of a practice or game the consumer can request all existing stats and shots. Consumers can also request information about the court to aid in the handling of plotting locations and shots. It is important to understand that the api implies a call order, the discovery of live data to the point that application attaches to the live realtime data. Below is the api call order that all client application should consider to ensure that all meta data is obtained and if joining an existing live event the client application can obtain past stats and shots.

Get Live Information

Get Live Information
GET/v1/data/live/{live_id}

Example URI

GET /v1/data/live/live_id
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "teams": [
    {
      "id": 461,
      "name": "TeamAppTeam",
      "live": {
        "started_at": 1484940405508,
        "id": "6141681d-df46-11e6-a818-f20e96351dc1",
        "type": "SHOOTING",
        "name": "flex test",
        "facility_name": "ShotTracker Lab",
        "court_name": "Main Court",
        "location_id": "/114118d4-2e50-11e6-b4a4-deecc6e6f111/9e4118d4-2e50-11e6-b4a4-deecc6e6f112",
        "is_practice_event": true,
        "is_game_event": false,
        "event": {
          "started_at": 1484940405508,
          "id": "56141681d-df46-11e6-a818-f20e96351dc1",
          "name": "Adhoc Practice"
        }
      }
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Request Subscription Token

Request Subscription Token
GET/v1/data/live/{live_id}/_subscribe{?dt}

Example URI

GET /v1/data/live/live_id/_subscribe?dt=
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

dt
string (optional) 

Subscribe to a specific data type. More than one data type can be passed using the &dt= notation. Possible values for this field are STATS, SHOTS, or LOCATIONS.

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "token": "6141681d-df46-11e6-a818-f20e96351dc1",
  "token_data_types": [
    "STATS",
    "SHOTS",
    "LOCATIONS"
  ],
  "active_state": "LIVE",
  "teams": [
    {
      "id": 461,
      "name": "TeamAppTeam",
      "players": [
        {
          "id": 123,
          "first_name": "John",
          "last_name": "Doe",
          "display_name": "John Doe",
          "jersey_number": 1,
          "position": "center",
          "profile_image_link": "<image link>"
        }
      ]
    }
  ],
  "_stats": "https://api.shottracker.com/v1/data/live/6141681d-df46-11e6-a818-f20e96351dc1/stats",
  "_stats_details": "https://api.shottracker.com/v1/data/live/6141681d-df46-11e6-a818-f20e96351dc1/stats/details",
  "_shots": "https://api.shottracker.com/v1/data/live/6141681d-df46-11e6-a818-f20e96351dc1/shots",
  "event_completed_results": [
    {
      "id": "a59e3734-101f-11e8-be3e-0242286dfad2",
      "type": "GAME_ROUND",
      "name": null,
      "_stats": "http://api.shottracker.com/v1/data/live/a59e3734-101f-11e8-be3e-0242286dfad2/stats",
      "_stats_details": "http://api.shottracker.com/v1/data/live/a59e3734-101f-11e8-be3e-0242286dfad2/stats/details",
      "_shots": "http://api.shottracker.com/v1/data/live/a59e3734-101f-11e8-be3e-0242286dfad2/shots"
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to LOCATIONS|STATS|SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Request Court Points

Request Court Points
GET/v1/data/live/{live_id}/court

Example URI

GET /v1/data/live/live_id/court
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "xne": 0,
  "yne": 0,
  "xse": 2,
  "yse": 2,
  "xsw": 4,
  "ysw": 4,
  "xnw": 6,
  "ynw": 6,
  "hoops": [
    {
      "x": 0,
      "y": 0,
      "z": 13
    },
    {
      "x": 10,
      "y": 10,
      "z": 23
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Current Live Stats

Current Live Stats
GET/v1/data/live/{live_id}/stats

Example URI

GET /v1/data/live/live_id/stats
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "teams": [
    {
      "id": 461,
      "player_stats": [
        {
          "id": 123,
          "player_details": {
            "id": 123,
            "firstname": "John",
            "lastname": "Doe",
            "profile_image_link": "<image link>"
          },
          "version": 1,
          "stats": {
            "FG": 1,
            "FGA": 2,
            "PTS": 2
          }
        }
      ]
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Current Live Stats Details

Current Live Stats Details
GET/v1/data/live/{live_id}/stats/details

Example URI

GET /v1/data/live/live_id/stats/details
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "teams": [
    {
      "id": 461,
      "player_stats": [
        {
          "id": 123,
          "player_details": {
            "id": 123,
            "firstname": "John",
            "lastname": "Doe",
            "profile_image_link": "<image link>"
          },
          "stats": {
            "FGA": [
              {
                "occurred_at": 123456789,
                "value": 1
              },
              {
                "occurred_at": 234567890,
                "value": 1
              }
            ],
            "FG": [
              {
                "occurred_at": 123456789,
                "value": 1
              }
            ],
            "PTS": [
              {
                "occurred_at": 123456789,
                "value": 2
              }
            ]
          }
        }
      ]
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Current Live Shots

Current Live Shots
GET/v1/data/live/{live_id}/shots

Example URI

GET /v1/data/live/live_id/shots
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "teams": [
    {
      "id": 461,
      "player_shots": [
        {
          "id": 123,
          "player_details": {
            "id": 123,
            "firstname": "John",
            "lastname": "Doe",
            "profile_image_link": "<image link>"
          },
          "shots": [
            {
              "occurred_at": 123456789,
              "is_make": true,
              "is_3point": true,
              "zone": 1,
              "hoop_player_x": 12,
              "hoop_player_y": 3,
              "status": "RECORDED"
            }
          ]
        }
      ]
    }
  ]
}
Response  400
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 400,
  "message": "The live id is no longer active",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  404
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 404,
  "message": "Invalid id",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Video Recording

Video Recording
PUT/v1/data/live/{live_id}/video{?id,started_at}

Video providers can index video with ShotTracker live events. A provider must supply a unique identifier for the video and the exact epoch UTC timestamp when the video was started. For full integration, the provider must be a registered as a video provider so that it is known how ShotTracker can call back to get the video.

Example URI

PUT /v1/data/live/live_id/video?id=&started_at=
URI Parameters
HideShow
live_id
string (required) 

ID of the live session

id
string (required) 

The consumer supplied id representing a video recording. Max size is 255 bytes.

started_at
number (optional) 

The exact epoch timestamp (in milliseconds) the video recording was started. If not provided it is assumed the video starts at the time of the call.

Response  204

Live Data Feed

All live data is delivered over a websocket (ws://live.shottracker.com). A websocket is a long lived connection between the realtime server and the client application. Before attaching to the websocket a client must request a subscription token.

Important: Tokens are only one time use. If a token is used to attach to a live session a new token is needed to reattach.

Example Connection Request

ws://live.shottracker.com?token=6141681d-df46-11e6-a818-f20e96351dc1

Example Connection Response

  • Ack Response (application/json)

    {"data":{"socketSessionId":"2edbccd1","serverAttributes":{"maxInputBufferSizeInBytes":8192,"connectionTimeoutInMs":120000}},"action":"subscribe","type":"ack"}

Keep Alives

The Ack response indicates how long the connection will stay open before timing out when no data is traveling over the connection (connectionTimeoutInMs). Clients should send a ping request to ensure the connection stays open when no data is received. The server will send back a corresponding pong response.

  • Ping Request (application/json)

    {"action":"ping"}
  • Pong Response (application/json)

    {"type":"pong"}

Data Type Responses

  • Stats Response (application/json)

    {"type":"stats","data":{"occurred_at":1484865816836,"team_id":461,"player_id":123,"stats":{"FGA":4.0,"PTS":4.0,"FG":2.0},"classification":"TWO_POINT_MAKE","version":317}}
  • Shots Response (application/json)

    {"type":"shot","data":{"occurred_at":1484865816836,"team_id":461,"player_id":123,"is_make":true,"is_3point":true,"zone":1,"hoop_player_x":12,"hoop_player_y":3,"status":"RECORDED"}}
  • Location Response (application/json)

    {"type":"location","data":{"occurred_at":1478800197342,"type":"PLAYER","id":123,"x":123,"y":456,"z":789}}

Marker Type Responses

Marker data is emitted to consumers to know when play starts and ends for a given game or practice. The state markers indicate whether play is active (LIVE), non-active (PAUSED), or in a foul (FOUL).

Game Markers

  • Start Play Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197300,"type":"PLAY_START"}}
  • End of First Half Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197333,"type":"END_FIRST_HALF"}}
  • Play Next Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197339,"live_id":"a1140480-e1d5-4684-a619-402984b5c9ba","type":"PLAY_NEXT"}}
  • Start of Second Half Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197366,"type":"START_SECOND_HALF"}}
  • End Play Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197400,"type":"PLAY_END"}}

Practice Markers

  • Drill Start Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197300,"type":"DRILL_START"}}
  • Drill End Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197333,"type":"DRILL_END"}}
  • Drill Next Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197339,"live_id":"a1e80480-e1d5-4684-a619-402984b5c9ba","type":"DRILL_NEXT"}}
  • Practice End Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197400,"type":"PRACTICE_END"}}

State Markers

  • Live State Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197300,"type":"LIVE"}}
  • Paused State Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197300,"type":"PAUSED"}}
  • Foul State Marker Response (application/json)

    {"type":"marker","data":{"occurred_at":1478800197300,"type":"FOUL"}}

Live Notification

A live notify allows a service to be invoked when a practice drill or game is started. This eliminates the need to poll the search resource for new live events. When a notify url is registered the service will be called with the following query parameters:

PUT https://{url}?notify_id={registered notify id}&action=LIVE&data={live id}&state=[START|END]

The notification state indicates either the START or END of a practice drill or game half, quarter, etc… When a notification is created end notifications are disabled by default. Use the enable or disable endpoints to toggle notifications for the end notification state.

List LIVE Notifies

List LIVE Notifies
GET/v1/data/live/notify

Example URI

GET /v1/data/live/notify
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "notifications": [
    {
      "id": "abc-123",
      "action": "LIVE",
      "url": "http://localhost",
      "end_notification": false
    }
  ]
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Create LIVE Notify

Create LIVE Notify
PUT/v1/data/live/notify{?url}

Example URI

PUT /v1/data/live/notify?url=
URI Parameters
HideShow
url
string (required) 

Consumer provided url that will be called with the notification

Response  204
HideShow
Headers
X-ShotTracker-Notify-Id: <Live notify_id>
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Update LIVE Notify URL

Update LIVE Notify URL
PUT/v1/data/live/notify/{notify_id}{?url}

Example URI

PUT /v1/data/live/notify/notify_id?url=
URI Parameters
HideShow
notify_id
string (required) 

Specific id for the notify to update

url
string (required) 

New consumer provided url that will be called with the notification

Response  204
Response  422
HideShow
Body
{
  "status": 422,
  "message": "Notify id not found",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Enable LIVE End Notify

Enable LIVE End Notify
PUT/v1/data/live/notify/{notify_id}/_enableEndNotify

Example URI

PUT /v1/data/live/notify/notify_id/_enableEndNotify
URI Parameters
HideShow
notify_id
string (required) 

Specific id for the notify to update

Response  204
Response  422
HideShow
Body
{
  "status": 422,
  "message": "Notify id not found",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Disable LIVE End Notify

Disable LIVE End Notify
PUT/v1/data/live/notify/{notify_id}/_disableEndNotify

Example URI

PUT /v1/data/live/notify/notify_id/_disableEndNotify
URI Parameters
HideShow
notify_id
string (required) 

Specific id for the notify to update

Response  204
Response  422
HideShow
Body
{
  "status": 422,
  "message": "Notify id not found",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Delete LIVE Notify

Delete LIVE Notify
DELETE/v1/data/live/notify/{notify_id}

Example URI

DELETE /v1/data/live/notify/notify_id
URI Parameters
HideShow
notify_id
string (required) 

Specific id for the notify to update

Response  204
Response  422
HideShow
Body
{
  "status": 422,
  "message": "Notify id not found",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Locations

List Locations

List Locations
GET/v1/data/locations

Example URI

GET /v1/data/locations
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "locations": [
    {
      "facility_name": "Test Facility",
      "court_name": "Test Facility Main Court",
      "location_id": "/114118d4-2e50-11e6-b4a4-deecc6e6f111/9e4118d4-2e50-11e6-b4a4-deecc6e6f112"
    }
  ]
}

List Nearest Locations

List Nearest Locations
GET/v1/data/locations/nearest/latlong/{latitude}/{longitude}{?radius,unit}

Example URI

GET /v1/data/locations/nearest/latlong/latitude/longitude?radius=&unit=
URI Parameters
HideShow
latitude
number (required) 

Callers current latitude

longitude
number (required) 

Callers current longitude

radius
number (required) 

The radius to include facilities

unit
string (required) 

The unit of measure; either MILES or KILOMETERS

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "locations": [
    {
      "facility_name": "Joes Gym",
      "court_name": "main court",
      "location_id": "/114118d4-2e50-11e6-b4a4-deecc6e6f112/9e4118d4-2e50-11e6-b4a4-deecc6e6f122",
      "distance": {
        "unit": "MILES",
        "value": 11.76
      }
    }
  ]
}

Users

All user services require a user access token. This token is obtained using an oAuth2 Implicit Flow.

User Profile

User Profile
GET/v1/data/user/profile

Example URI

GET /v1/data/user/profile
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 123,
  "first_name": "User First Name",
  "last_name": "User Last Name",
  "email": "user@shottracker.com"
}

Teams

List Teams

List Teams
GET/v1/data/teams

Example URI

GET /v1/data/teams
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "teams": [
    {
      "id": 46,
      "name": "Test Team"
    }
  ]
}

Search Team Events

Search Team Events
GET/v1/data/teams/{team_id}/events{?from,to}

Example URI

GET /v1/data/teams/team_id/events?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "events": [
    {
      "id": "cf3ba789-06c4-11e8-bb65-0242286dfad2",
      "name": "TeamAppTeam vs TestTeamAlpha",
      "results": [
        {
          "id": "cf56d0aa-06c4-11e8-bb65-0242286dfad2",
          "name": null,
          "type": "GAME_ROUND",
          "started_at": 1517430299810,
          "ended_at": 1517431728868,
          "_stats": "https://api.shottracker.com/v1/data/live/cf56d0aa-06c4-11e8-bb65-0242286dfad2/stats",
          "_stats_details": "https://api.shottracker.com/v1/data/live/cf56d0aa-06c4-11e8-bb65-0242286dfad2/stats/details",
          "_shots": "https://api.shottracker.com/v1/data/live/cf56d0aa-06c4-11e8-bb65-0242286dfad2/shots"
        },
        {
          "id": "23d3344b-06c8-11e8-bb65-0242286dfad2",
          "name": null,
          "type": "GAME_ROUND",
          "started_at": 1517431730064,
          "ended_at": 1517431732978,
          "_stats": "https://api.shottracker.com/v1/data/live/23d3344b-06c8-11e8-bb65-0242286dfad2/stats",
          "_stats_details": "https://api.shottracker.com/v1/data/live/23d3344b-06c8-11e8-bb65-0242286dfad2/stats/details",
          "_shots": "https://api.shottracker.com/v1/data/live/23d3344b-06c8-11e8-bb65-0242286dfad2/shots"
        }
      ],
      "is_practice_event": false,
      "is_game_event": true,
      "started_at": 1517430299810,
      "ended_at": 1517431732978
    }
  ]
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Stats

Team Practice Stats
GET/v1/data/teams/{team_id}/players/practice/stats{?from,to}

A practice can consist of a team practice with shooting and scrimmage drills or a players individual workout. This endpoint will return team players stats that include both team practice drills (shooting and scrimmage) and workouts.

Example URI

GET /v1/data/teams/team_id/players/practice/stats?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_stats": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "version": 1,
      "stats": {
        "FG": 1,
        "FGA": 2,
        "PTS": 2
      }
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Scrimmage Stats

Team Practice Scrimmage Stats
GET/v1/data/teams/{team_id}/players/practice/scrimmage/stats{?from,to}

Example URI

GET /v1/data/teams/team_id/players/practice/scrimmage/stats?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_stats": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "version": 1,
      "stats": {
        "FG": 1,
        "FGA": 2,
        "PTS": 2
      }
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Shooting Drill Stats

Team Practice Shooting Drill Stats
GET/v1/data/teams/{team_id}/players/practice/shooting/stats{?from,to}

Example URI

GET /v1/data/teams/team_id/players/practice/shooting/stats?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_stats": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "version": 1,
      "stats": {
        "FG": 1,
        "FGA": 2,
        "PTS": 2
      }
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Game Stats

Team Game Stats
GET/v1/data/teams/{team_id}/players/game/stats{?from,to}

Example URI

GET /v1/data/teams/team_id/players/game/stats?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_stats": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "version": 1,
      "stats": {
        "FG": 1,
        "FGA": 2,
        "PTS": 2
      }
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to STATS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Shots

Team Practice Shots
GET/v1/data/teams/{team_id}/players/practice/shots{?from,to}

Example URI

GET /v1/data/teams/team_id/players/practice/shots?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_shots": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "shots": [
        {
          "occurred_at": 123456789,
          "is_make": true,
          "is_3point": true,
          "zone": 1,
          "hoop_player_x": 12,
          "hoop_player_y": 3,
          "status": "RECORDED"
        }
      ]
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Scrimmage Shots

Team Practice Scrimmage Shots
GET/v1/data/teams/{team_id}/players/practice/scrimmage/shots{?from,to}

Example URI

GET /v1/data/teams/team_id/players/practice/scrimmage/shots?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_shots": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "shots": [
        {
          "occurred_at": 123456789,
          "is_make": true,
          "is_3point": true,
          "zone": 1,
          "hoop_player_x": 12,
          "hoop_player_y": 3,
          "status": "RECORDED"
        }
      ]
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Practice Shooting Drill Shots

Team Practice Shooting Drill Shots
GET/v1/data/teams/{team_id}/players/practice/shooting/shots{?from,to}

Example URI

GET /v1/data/teams/team_id/players/practice/shooting/shots?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_shots": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "shots": [
        {
          "occurred_at": 123456789,
          "is_make": true,
          "is_3point": true,
          "zone": 1,
          "hoop_player_x": 12,
          "hoop_player_y": 3,
          "status": "RECORDED"
        }
      ]
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}

Team Game Shots

Team Game Shots
GET/v1/data/teams/{team_id}/players/game/shots{?from,to}

Example URI

GET /v1/data/teams/team_id/players/game/shots?from=&to=
URI Parameters
HideShow
team_id
number (required) 

ID of the team

from
number (required) 

The starting epoch timestamp (in milliseconds)

to
number (required) 

The ending epoch timestamp (in milliseconds)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 461,
  "player_shots": [
    {
      "id": 123,
      "player_details": {
        "id": 123,
        "firstname": "John",
        "lastname": "Doe",
        "profile_image_link": "<image link>"
      },
      "shots": [
        {
          "occurred_at": 123456789,
          "is_make": true,
          "is_3point": true,
          "zone": 1,
          "hoop_player_x": 12,
          "hoop_player_y": 3,
          "status": "RECORDED"
        }
      ]
    }
  ]
}
Response  403
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 403,
  "message": "No access to SHOTS data",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  422
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 422,
  "message": "Both from and to must be greater than 0 | from timestamp must be less than to timestamp | Request may not exceed more than 8 months",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}
Response  500
HideShow
Headers
Content-Type: application/json
Body
{
  "status": 500,
  "message": "<General System Error Message>",
  "shottrackerRequestId": "f1e80480-e1d5-4684-a619-402984b5c9ba"
}