B1 | Start Guide to Play-By-Play Data Feed

Prerequisites

To be able to use the Trackman Play-By-Play Data-feed you will need to implement one or more Webhooks that support a Validation Handshake in order for the delivery to work.

This is required because the Trackman logic is built using Microsoft Azure Event Grid Topics, see more at https://aka.ms/esvalidation.

Microsoft have provided a small C# sample (but many programming languages are supported) of how to do this:

if (eventGridEvent.Data is SubscriptionValidationEventData)
               {
                   var eventData = (SubscriptionValidationEventData)eventGridEvent.Data;
                   log.Info($"Got SubscriptionValidation event data, validationCode: {eventData.ValidationCode},  validationUrl: {eventData.ValidationUrl}, topic: {eventGridEvent.Topic}");
                   // Do any additional validation (as required) such as validating that the Azure resource ID of the topic matches
                   // the expected topic and then return back the below response
                   var responseData = new SubscriptionValidationResponse()
                   {
                       ValidationResponse = eventData.ValidationCode
                   };
                   return req.CreateResponse(HttpStatusCode.OK, responseData);
               }

Validation of Webhook

This validation Handshake will happen when the webhook is first configured  by Trackman in Azure or if it needs to be updated later.

  • At the time of event subscription creation/update, Event Grid posts a subscription validation event to the target endpoint.
  • The event contains a header value aeg-event-type: SubscriptionValidation.
  • The event body has the same schema as other Event Grid events.
  • The eventType property of the event is Microsoft.EventGrid.SubscriptionValidationEvent.
  • The data property of the event includes a validationCode property with a randomly generated string. For example, validationCode: acb13….
  • The event data also includes a validationUrl property with a URL for manually validating the subscription.
  • The array contains only the validation event. Other events are sent in a separate request after you echo back the validation code.
  • The EventGrid data plane SDKs have classes corresponding to the subscription validation event data and subscription validation response

An example validation message will look like this:

[
 {
   "id": "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66",
   "topic": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
   "subject": "",
   "data": {
     "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6",
     "validationUrl": "https://rp-eastus2.eventgrid.azure.net:553/eventsubscriptions/myeventsub/validate?id=0000000000-0000-0000-0000-00000000000000&t=2022-10-28T04:23:35.1981776Z&apiVersion=2018-05-01-preview&token=1A1A1A1A"
   },
   "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
   "eventTime": "2022-10-28T04:23:35.1981776Z",
   "metadataVersion": "1",
   "dataVersion": "1"
 }
]

Calling this Webhook it must return the ValidationResponse in order for the handshake to pass. It needs to be a HTTP 200 OK and must happen within 30 seconds or else the operation will be canceled. 

{
 "validationResponse": "validationCode"
}

Look here for more information: https://learn.microsoft.com/en-us/azure/event-grid/end-point-validation-cloud-events-schema.

Data Feeds

The following list is the types and supported feeds and examples of the returned data.

The data will be wrapped in a message like this:

{
   "id": "1e532635-8086-4572-b3cb-041c331e87bb",
   "subject": "PlayByPlayFeed",
       "data": {
            "Payload here"
       },
   "eventType": "PlayByPlaySession",
   "dataVersion": "2.0",
   "metadataVersion": "1",
   "eventTime": "2023-04-26T06:55:08.8313986Z",
   "topic": "/subscriptions/faeb7dfb-7680-4a94-a196-a86269ca0747/resourceGroups/tmbaseball-organization-topics-release/providers/Microsoft.EventGrid/topics/9939933f-99ee-4eb6-9962-8ab99e15ce44"
}

Game Feeds

Session

{
    "Version" : "2.0.0",
    "Time": "2018-02-22T20:39:17.312076160Z", // UTC timestamp from when the session was last updated
    "SessionId" : "abc93729-ac13-11e9-9ed5-989096a0d95d", // unique session identifier
    "GameReference" : "20180222-1",
    "GameScheduleReference" : // can be null - will have data if game was started by game schedule
    {
        "ExternalSessionId" : "ABC123"
    },
    "SessionType" : "Standard", // Other types could be BattingPractice or HomeRunDerby
    "League": {
        "Name" : "AAA",
        "ShortName" : "AAA"            
    },
    "Level" : {
        "Name" : "BBB"            
    },
    "Location" : {
        "Venue" : {
            "Name" : "Tulsa (OK)"
        }, 
        "Field" : {
            "Name" : "ONEOK Field",
            "ShortName" : "ONEOKField"
        }
    },
    "HomeTeam" : {
        "ExternalTeamId" : "TTT",
        "Name" : "Tulsa Drillers",
        "ShortName" : "Tulsa",    
        "Lineup" : [
           {
                "ForeignId" : "12345", 
                "NameRef" : "Zastryzny, Rob", 
                "Position" : "P" // Possible positions are 1B, 2B, 3B, LF, CF, RF, SS, C, P, DH
            }, 
            {
                "ForeignId" : "34567", 
                "NameRef" : "Motter, Taylor", 
                "Position" : "1B" 
            }
        ]            
    }, 
    "AwayTeam" : {
        "ExternalTeamId" : "TTT",
        "Name" : "Midland RockHounds",
        "ShortName" : "MID_ROC",    
        "Lineup" : [
           {
                "ForeignId" : "12345",  
                "NameRef" : "Rob Zastryzny", 
                "Position" : "P" // Possible positions are 1B, 2B, 3B, LF, CF, RF, SS, C, P, DH
            }, 
            {
                "ForeignId" : "34567",  
                "NameRef" : "Taylor Motter", 
                "Position" : "1B" 
            }
        ]            
    },
    "SessionState" : {
        "State" : "SessionEnded", // Possible values: SessionStarted, SessionEnded
        "SessionStartedUtc" : "2019-07-22T06:49:55.5143686Z", // can be null
        "SessionStartedLocal" : "2019-07-22T06:49:55.5143686", // can be null
        "SessionEndedUtc" : "2019-07-22T09:49:55.5143686Z", // can be null
        "SessionEndedLocal" : "2019-07-22T09:49:55.5143686" // can be null
    }
}

Ball

{
 "Version": "1.2.0",
 "Time": "2018-02-22T20:39:17.312076160Z", // UTC timestamp from when the message was last updated
 "SessionId": "abc93729-ac13-11e9-9ed5-989096a0d95d", // unique session identifier
 "PlayId": "53427fe0-52e3-4017-9aa2-236c87718f6c",
 "TrackId": "b2cc3109-7410-4150-867a-7b1bfb0fbc0c",
 "TrackStartTime": "2019-09-04T14:37:14.531193Z",
 "Kind": "Pitch", // can be Pitch, Hit or CatcherThrow (V3 only) 
 "Pitch": { // only if Kind = Pitch
   "Release": {
     "Speed": 0.0,
     "SpinRate": null,
     "Extension": 0.0,
     "VerticalAngle": 0.0,
     "HorizontalAngle": 0.0,
     "Height": 1.812,
     "Side": 0.652,
   },
   "Location": {
     "Speed" 0.0
     "Time": 0.0,
     "Height": 1.812,
     "Side": 0.652
   },
   "LocationMiddle": {
     "Height": 1.812,
     "Side": 0.652
   },
   "LocationBack": {
     "Height": 1.812,
     "Side": 0.652
   },
   "Movement": {
     "Horizontal": 0.0,
     "Vertical": 0.0,
     "InducedVertical": 0.0,
     "SpinAxis": 247.914355,
      "Tilt": "1.5"
   },
    "NineP": {
     "X0": {
              "X": 0.759779, 
              "Y": 15.24, 
              "Z": 1.680944
      },
     "V0": { 
              "X": -2.688154,
              "Y": -41.431425, 
             "Z": -0.591442
       },
     "A0": {
              "X": 4.581591, 
              "Y": 8.427442, 
              "Z": -5.936245
       },
     "Pfxx": 0.202506,
     "Pfxz": 0.171071
    }
 },
 "Hit": { // only if Kind = Hit
   "Launch": {
     "Speed": 0.0,
     "SpinRate": null,
     "VerticalAngle": 30.939,
     "HorizontalAngle": 21.68,
      "SpinAxis": 227.915447,
   },
   "LandingFlat": {
     "Time": 4.30478,
     "Distance": 100.771,
     "Bearing": 30.179
   }
 },
 "CatcherThrow": { // only if V3
   "ExchangeTime": 1.123,
   "PopTime": 1.123
    "Location":{
        "Time": 4.5
    }
    "Release":{
        "Speed":  53.2
    }
 }
}

PlayMetadata

{
 "Version": "1.0.0", version of the content of the message - always present
 "Time": "2018-02-22T20:39:17.312076160Z", // UTC timestamp from when the message was last updated - always present
 "SessionId": "abc93729-ac13-11e9-9ed5-989096a0d95d", // unique session identifier - always present
 "PlayId": "53427fe0-52e3-4017-9aa2-236c87718f6c", // unique play identifier - always present
 "TaggerBehavior": {
   "IsWarmup": false,
   "SequenceNumber": 3
 },
 "GameState": {
   "Inning": 1,
   "TopBottom": "Top"
 },  
 "Players": { // The players of the play      
     "Pitcher": null, // can be null
     // The batter
     "Batter": { // can be null         
         "ForeignId": "12345",
         "NameRef": "Jolly Wolly",
         "Handedness": "Left" // the Batting Handedness: Left, Right, Both, Undefined
     },
     "Catcher": null // can be null
 }
}

StrikeZone

{
     "Version":"1.0.0",
     "Time":"2025-02-12T14:45:36.0957935Z",
     "PlayId":"4d3936a8-4211-4b2d-bdb5-1dbb2d03b6e6",
     "SessionId": "eb3e6925-60f1-435e-95fc-4c95b49bdcf9",
     "StrikeZones":[
        {
           "Method":"Front",
           "Top":40.15501,
           "Bottom":19.69626,
           "Right":8.75,
           "Left":-8.75
        },
        {
           "Method":"Middle",
           "Top":40.15501,
           "Bottom":19.69626,
           "Right":8.75,
           "Left":-8.75
        },
        {
           "Method":"Back",
           "Top":40.15501,
           "Bottom":19.69626,
           "Right":8.75,
           "Left":-8.75
        }
     ],
     "Type":"HeightBased",
     "Decision":"In",
     "Batter":{
        "Height":71.26
     }
  },
}

Practice Feeds

Session

{
    "Version" : "3.0.0",
    "Time": "2018-02-22T20:39:17.312076160Z",
    "SessionId" : "abc93729-ac13-11e9-9ed5-989096a0d95d",
    "SessionType" : "Pitching",
    "Location" : {
        "Venue" : {
            "Name" : "Practice Field Trip 1"
        }, 
        "Field" : {
            "Name" : "Lane 1"
        }
    },
    "Batters" : [
            {
                "ForeignId" : "123456", 
                "NameRef" : "Zastryzny, Rob" 
            }, 
            {
                "ForeignId" : "345678", 
                "NameRef" : "Motter, Taylor" 
            }
        ],
    "Pitchers" : [
            {
                "ForeignId" : "123456", 
                "NameRef" : "Henderson, Jason" 
            }, 
            {
                "ForeignId" : "345678", 
                "NameRef" : "Gonzarles, Juan" 
            }
        ],
    "SessionState" : {
        "State" : "SessionEnded",
        "SessionStartedUtc" : "2019-07-22T06:49:55.5143686Z",
        "SessionStartedLocal" : "2019-07-22T06:49:55.5143686",
        "SessionEndedUtc" : "2019-07-22T09:49:55.5143686Z",
        "SessionEndedLocal" : "2019-07-22T09:49:55.5143686"
    }
}

Ball

{
 "Version": "1.2.0",
 "Time": "2018-02-22T20:39:17.312076160Z",
 "SessionId": "abc93729-ac13-11e9-9ed5-989096a0d95d",
 "PlayId": "53427fe0-52e3-4017-9aa2-236c87718f6c",
 "TrackId": "b2cc3109-7410-4150-867a-7b1bfb0fbc0c",
 "TrackStartTime": "2019-09-04T14:37:14.531193Z",
 "Kind": "Pitch",
 "Pitch": {
   "Release": {
     "Speed": 0.0,
     "SpinRate": null,
     "Extension": 0.0,
     "VerticalAngle": 0.0,
     "HorizontalAngle": 0.0,
     "Height": 1.812,
     "SpinAxis3dTilt": "1:15",
     "SpinAxis3dActiveSpinRate": 2126.816089,
     "SpinAxis3dSpinEfficiency": 0.9985436257,
     "SpinAxis3dTransverseAngle": 214.5010932,
     "SpinAxis3dLongitudinalAngle": 3.092622133
   },
   "Location": {
     "Time": 0.0,
     "Height": 1.812,
     "Side": 0.652
   },
   "Movement": {
     "Horizontal": 0.0,
     "Vertical": 0.0,
     "InducedVertical": 0.0,
     "SpinAxis": 247.914355
   },
    "NineP": {
     "X0": [0.759779, 15.24, 1.680944],
     "V0": [-2.688154, -41.431425, -0.591442],
     "A0": [4.581591, 8.427442, -5.936245],
     "Pfxx": 0.202506,
     "Pfxz": 0.171071
    }
 },
 "Hit": {
   "Launch": {
     "Speed": 0.0,
     "SpinRate": null,
     "VerticalAngle": 30.939,
     "HorizontalAngle": 21.68
   },
   "LandingFlat": {
     "Time": 4.30478,
     "Distance": 100.771,
     "Bearing": 30.179
   }
 }
}

PlayMetadata

{
 "Version": "1.0.0", // version of the content of the message - always present
 "Time": "2018-02-22T20:39:17.312076160Z", // UTC timestamp from when the message was last updated - always present
 "SessionId": "abc93729-ac13-11e9-9ed5-989096a0d95d", // unique session identifier - always present
 "PlayId": "53427fe0-52e3-4017-9aa2-236c87718f6c", // unique play identifier - always present
 "TaggerBehavior": {
   "IsWarmup": false,
   "SequenceNumber": 3
 },  
 "Players": { // The players of the play      
     "Pitcher": null, // can be null
     // The batter
     "Batter": { // can be null         
         "NameRef": "Jolly Wolly",
         "Handedness": "Left", // the Batting Handedness can be Left Right Both Undefined          
         "ForeignId": "32341" // Prioritized foreign identifier for the player without prefix and taking the Pro Id override into account
     },
     "Catcher": null // can be null
 }
}

Didn't find what you were looking for?

Search