{"__v":0,"_id":"57c47c298588a30e00a99e05","initVersion":{"_id":"55773a5ba042551900b002ce","version":"1"},"project":"55773a5ba042551900b002cb","user":{"_id":"546d17e2eb9cfd1400dd4529","username":"","name":"Gareth Davies"},"hidden":false,"createdAt":"2016-08-29T18:17:13.088Z","fullscreen":false,"htmlmode":false,"html":"","body":"[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Version 1.1 of the Live Timing Standard will be mandatory for all World Triathlon Series events\",\n  \"body\": \"For World Cup and other events the implementation of the standard will be optional but implementing will enable live timing to be shown on Triathlon.org as well as other custom-built applications.\"\n}\n[/block]\n**Version 1.1** of the live timing standard builds upon the original [version 1](https://developers.triathlon.org/v1/page/live-timing-standard-v10) of the live timing standard with some notable changes in order to enhance the timing delivery. We have attempted to maintain as much consistency as possible with the prior version to ease the upgrade process. The most notable changes are:\n\n* All results are now provided in a single XML or JSON output rather than the separate leaderboard and splits files that were previously required.\n* All athletes (and corresponding split data) are now included in the timing output regardless of the position of the athlete. This differs in that, in the prior version, only athletes that had crossed the latest timing point were included in the output.\n* Timers now have the option of either hosting the XML or JSON file or making a POST request to ITU servers with the timing data if it is preferred to eliminate the requirement to host any files (see [delivery options](https://developers.triathlon.org/v1/page/live-timing-standard-v11#delivery-options) for an enhanced explanation).\n* Race incidents such as DNFs are now able to be included which may be publicly viewable on a race incidents page.\n* This timing standard removes the requirement for timers to upload intermediate results to Triathlon.org for ranking generation purposes.\n* Timers have the option of sending JSON data rather than only XML as before.\n* Live timing is now available to all ITU events that support the live timing standard.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Overview\"\n}\n[/block]\nThe aim of **Version 1.1** of the Triathlon.org Live Timing Standard is to produce a higher quality of real-time timing data directly from races which may be delivered via the Triathlon.org API platform to subscribers. \n\nThe improvements in the standard greatly increase the potential for displaying timing data and developing feature-rich timing applications when used in conjunction with other [available APIs](https://developers.triathlon.org/docs). The standard also removes the requirement for timers to host any web-facing files as timing may be pushed to the Triathlon.org API platform which will handle the delivery of timing messages to all connected clients. This push method of delivery is entirely optional as the standard also allows for a single timing file hosted by the timers to be accessed solely by ITU's servers and is not public facing (see [delivery options](https://developers.triathlon.org/v1/page/live-timing-standard-v11#delivery-options)).\n\n## Timing Message Format\n\n**Each timing message should contain complete timing information** such that a user may be able to retrieve all information by receiving the latest timing message. **All message characters should be UTF-8 formatted**. All times and dates should be formatted according to the [ISO 8601 standard](https://en.wikipedia.org/wiki/ISO_8601) and millisecond data should be included if available.  Data should only be included if available e.g. segment values should only be included once an athlete has completed the segment.\n[block:api-header]\n{\n  \"title\": \"Example Messages\"\n}\n[/block]\nThe following messages only contain 2 athletes for brevity and you should refer to the extended examples below for full timing messages.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n   \\\"date\\\":\\\"2017-03-04 18:25:11+04:00\\\",\\n   \\\"start_time\\\":\\\"2017-03-04 15:55:00+04:00\\\",\\n   \\\"event_id\\\":\\\"107158\\\",\\n   \\\"event_name\\\":\\\"2017 ITU World Triathlon Abu Dhabi\\\",\\n   \\\"prog_id\\\":\\\"307158\\\",\\n   \\\"prog_name\\\":\\\"Elite Men\\\",\\n   \\\"wetsuit\\\":\\\"false\\\",\\n   \\\"sandbox\\\":\\\"false\\\",\\n   \\\"num_athletes\\\":\\\"2\\\",\\n   \\\"status\\\":\\\"live\\\",\\n   \\\"latest\\\":{\\n      \\\"segment_id\\\":\\\"2\\\",\\n      \\\"segment_name\\\":\\\"Swim Exit\\\",\\n      \\\"num_athletes\\\":\\\"1\\\"\\n   },\\n   \\\"conditions\\\":{\\n      \\\"air_temp\\\":\\\"28.8\\\",\\n      \\\"water_temp\\\":\\\"23.2\\\"\\n   },\\n   \\\"athletes\\\":[\\n      {\\n         \\\"id\\\":\\\"5695\\\",\\n         \\\"start_num\\\":\\\"26\\\",\\n         \\\"name\\\":\\\"Javier Gomez Noya\\\",\\n         \\\"country\\\":\\\"ESP\\\",\\n         \\\"segment_id\\\":\\\"18\\\",\\n         \\\"time\\\":\\\"00:18:37.911\\\",\\n         \\\"difference\\\":\\\"00:00:00.000\\\",\\n         \\\"position\\\":\\\"1\\\",\\n         \\\"status\\\":null,\\n         \\\"incidents\\\":null,\\n         \\\"splits\\\":[\\n            {\\n               \\\"id\\\":\\\"1\\\",\\n               \\\"name\\\":\\\"Swim Lap 1\\\",\\n               \\\"total_time\\\":\\\"00:10:54.799\\\",\\n               \\\"time\\\":\\\"00:10:54.799\\\",\\n               \\\"difference\\\":\\\"00:00:11.001\\\",\\n               \\\"position\\\":\\\"10\\\"\\n            },\\n            {\\n               \\\"id\\\":\\\"2\\\",\\n               \\\"name\\\":\\\"Swim Exit\\\",\\n               \\\"total_time\\\":\\\"00:18:37.911\\\",\\n               \\\"time\\\":\\\"00:07:43.112\\\",\\n               \\\"difference\\\":\\\"00:00:11.320\\\",\\n               \\\"position\\\":\\\"14\\\"\\n            }\\n         ]\\n      },\\n      {\\n         \\\"id\\\":\\\"18719\\\",\\n         \\\"start_num\\\":\\\"22\\\",\\n         \\\"name\\\":\\\"Thomas Bishop\\\",\\n         \\\"country\\\":\\\"GBR\\\",\\n         \\\"segment_id\\\":\\\"1\\\",\\n         \\\"time\\\":\\\"00:10:53.996\\\",\\n         \\\"difference\\\":\\\"00:00:10.198\\\",\\n         \\\"position\\\":\\\"2\\\",\\n         \\\"status\\\":null,\\n         \\\"incidents\\\":null,\\n         \\\"splits\\\":[\\n            {\\n               \\\"id\\\":\\\"1\\\",\\n               \\\"name\\\":\\\"Swim Lap 1\\\",\\n               \\\"total_time\\\":\\\"00:10:53.996\\\",\\n               \\\"time\\\":\\\"00:10:53.996\\\",\\n               \\\"difference\\\":\\\"00:00:10.198\\\",\\n               \\\"position\\\":\\\"9\\\"\\n            }\\n         ]\\n      }\\n   ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n<timing>\\n   <date>2017-01-01T13:34:59.123Z</date>\\n   <start_time>2017-01-01T13:30:59.123Z</start_time>\\n   <event_id>123456</event_id>\\n   <event_name>ITU World Triathlon Series Yokohama</event_name>\\n   <prog_id>123456</prog_id>\\n   <prog_name>Elite Women</prog_name>\\n   <wetsuit>false</wetsuit>\\n   <sandbox>false</sandbox>\\n   <num_athletes>2</num_athletes>\\n   <status>live</status>\\n   <latest>\\n      <segment_id>2</segment_id>\\n      <segment_name>Swim Exit</segment_name>\\n      <num_athletes>1</num_athletes>\\n   </latest>\\n   <conditions>\\n      <air_temp>16.5</air_temp>\\n      <water_temp>18.4</water_temp>\\n   </conditions>\\n   <athletes>\\n      <athlete>\\n         <id>40887</id>\\n         <start_num>2</start_num>\\n         <name>Gwen Jorgensen</name>\\n         <country>USA</country>\\n         <segment_id>2</segment_id>\\n         <time>00:18:12</time>\\n         <difference>00:00:00</difference>\\n         <position>1</position>\\n         <status></status>\\n         <incidents></incidents>\\n         <splits>\\n            <segment>\\n               <id>1</id>\\n               <name>Swim Lap 1</name>\\n               <time>00:09:00</time>\\n               <total_time>00:09:00</total_time>\\n               <difference>00:00:11</difference>\\n               <position>2</position>\\n            </segment>\\n            <segment>\\n               <id>2</id>\\n               <name>Swim Exit</name>\\n               <time>00:09:12</time>\\n               <total_time>00:18:12</total_time>\\n               <difference>00:00:00</difference>\\n               <position>1</position>\\n            </segment>\\n         </splits>\\n      </athlete>\\n      <athlete>\\n         <id>31438</id>\\n         <start_num>1</start_num>\\n         <name>Non Stanford</name>\\n         <country>GBR</country>\\n         <segment_id>1</segment_id>\\n         <time>00:08:57</time>\\n         <difference>00:00:00</difference>\\n         <position>1</position>\\n         <status></status>\\n         <incidents></incidents>\\n         <splits>\\n            <segment>\\n               <id>1</id>\\n               <name>Swim Lap 1</name>\\n               <time>00:08:57</time>\\n               <total_time>00:08:57</total_time>\\n               <difference>00:00:00</difference>\\n               <position>1</position>\\n            </segment>\\n         </splits>\\n      </athlete>\\n   </athletes>\\n</timing>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Complete Timing Examples\",\n  \"body\": \"A full timing example in JSON is available [here](https://gist.githubusercontent.com/garethtdavies/fe58f5085b6e474884b93852a43c8058/raw/ca92c21f64a0fe56cbede113db3826f19c0c9c95/yokohama-ew-official.json).\"\n}\n[/block]\n## Demonstration Links\n\nA very basic front-end implementation of an XML [sample file](https://gist.github.com/garethtdavies/1f47cd7c7133593b0137963f0a72c0d9) is available at the following links:\n\n* [Leaderboard](https://data.triathlon.org/timing/281501)\n* [Segment Splits](https://data.triathlon.org/timing/281501/splits/2)\n* [Race Incidents](https://data.triathlon.org/timing/281501/incidents)\n[block:api-header]\n{\n  \"title\": \"Timing Parameters\"\n}\n[/block]\nA breakdown of each parameter is listed below ( a penalty field will be added shortly).\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Parameter\",\n    \"h-1\": \"Example\",\n    \"h-2\": \"Description\",\n    \"0-0\": \"date\",\n    \"0-1\": \"2017-01-01T13:34:59.123Z\",\n    \"0-2\": \"An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) of the time the message was published\",\n    \"5-0\": \"prog_name\",\n    \"5-1\": \"Elite Men\",\n    \"5-2\": \"A descriptive name for the race corresponding to the [Events API](https://developers.triathlon.org/docs/events-api-overview)\",\n    \"h-3\": \"Format\",\n    \"0-3\": \"string\",\n    \"5-3\": \"string\",\n    \"8-0\": \"num_athletes\",\n    \"10-0\": \"**latest** \",\n    \"10-3\": \"object\",\n    \"10-2\": \"The latest object contains information regarding the latest timing point data (may be *null* if no timing data)\",\n    \"11-0\": \"latest.segment_id\",\n    \"12-0\": \"latest.segment_name\",\n    \"13-0\": \"latest.num_athletes\",\n    \"11-2\": \"The segment_id containing the latest result\",\n    \"11-1\": \"1\",\n    \"11-3\": \"integer\",\n    \"12-2\": \"The segment name containing the latest results\",\n    \"12-1\": \"Swim Exit\",\n    \"12-3\": \"string\",\n    \"13-1\": \"12\",\n    \"13-2\": \"The number of athletes that have passed through the timing point\",\n    \"13-3\": \"number\",\n    \"8-2\": \"The number of athletes in the race (which must correspond to the number of items in the athletes array)\",\n    \"8-1\": \"12\",\n    \"8-3\": \"integer\",\n    \"17-0\": \"**athletes** \",\n    \"17-2\": \"An object containing an array of all athlete objects in the race\",\n    \"17-3\": \"object\",\n    \"19-0\": \"athlete.id\",\n    \"20-0\": \"athlete.start_num\",\n    \"21-0\": \"athlete.name\",\n    \"22-0\": \"athlete.country\",\n    \"24-0\": \"athlete.position\",\n    \"29-0\": \"**athletes.splits** \",\n    \"25-0\": \"athlete.time\",\n    \"22-2\": \"The three letter [IOC country code](https://en.wikipedia.org/wiki/List_of_IOC_country_codes)\",\n    \"22-3\": \"string\",\n    \"22-1\": \"GBR\",\n    \"19-2\": \"The unique athlete_id corresponding to the athlete_id in the [Athletes API](https://developers.triathlon.org/docs/athletes-api-overview)\",\n    \"19-1\": \"123456\",\n    \"19-3\": \"integer\",\n    \"20-1\": \"12\",\n    \"20-2\": \"The start number of the athlete\",\n    \"20-3\": \"integer\",\n    \"21-1\": \"Alistair Brownlee\",\n    \"21-2\": \"The name of the athlete\",\n    \"21-3\": \"string\",\n    \"24-1\": \"12\",\n    \"24-2\": \"The position of the athlete (may be *null* if no data) at the latest timing point\",\n    \"24-3\": \"number\",\n    \"25-1\": \"00:17:16.145\",\n    \"25-2\": \"An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of the athlete's latest timing point\",\n    \"25-3\": \"string\",\n    \"29-1\": \"\",\n    \"29-2\": \"An array of split objects containing data for each segment completed by the athlete (may be *null *if no data)\",\n    \"29-3\": \"object\",\n    \"31-0\": \"segment.id\",\n    \"32-0\": \"segment.name\",\n    \"33-0\": \"segment.time\",\n    \"34-0\": \"segment.total_time\",\n    \"35-0\": \"segment.position\",\n    \"36-0\": \"segment.difference\",\n    \"31-2\": \"The segment_id of the split\",\n    \"32-2\": \"The name of the timing segment\",\n    \"33-2\": \"The time to complete this segment\",\n    \"34-2\": \"The cumulative time of all segments to this point\",\n    \"34-3\": \"string\",\n    \"35-2\": \"The position of the athlete at this timing point\",\n    \"35-3\": \"integer\",\n    \"36-2\": \"An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of difference of the athlete to the leader at this timing point\",\n    \"36-3\": \"string\",\n    \"36-1\": \"00:01:07.123\",\n    \"35-1\": \"12\",\n    \"34-1\": \"00:14:12.345\",\n    \"33-1\": \"00:08:16.345\",\n    \"32-1\": \"Swim Exit\",\n    \"31-1\": \"3\",\n    \"31-3\": \"integer\",\n    \"32-3\": \"string\",\n    \"33-3\": \"string\",\n    \"7-0\": \"sandbox\",\n    \"7-1\": \"true\",\n    \"7-3\": \"boolean\",\n    \"7-2\": \"Boolean to indicate whether to use the sandbox environment for development (defaults to false)\",\n    \"1-0\": \"start_time\",\n    \"1-1\": \"2017-01-01T13:34:59.123Z\",\n    \"1-2\": \"An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the start time of the race\",\n    \"1-3\": \"string\",\n    \"2-0\": \"event_id\",\n    \"3-0\": \"event_name\",\n    \"2-1\": \"123456\",\n    \"3-1\": \"2016 ITU World Triathlon Abu Dhabi\",\n    \"2-2\": \"The unique event_id corresponding to the event_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)\",\n    \"3-2\": \"A descriptive name for the event corresponding to the  [Events API](https://developers.triathlon.org/docs/events-api-overview)\",\n    \"4-0\": \"prog_id\",\n    \"4-1\": \"123456\",\n    \"4-2\": \"The unique prog_id corresponding to the prog_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)\",\n    \"4-3\": \"integer\",\n    \"3-3\": \"string\",\n    \"2-3\": \"integer\",\n    \"18-0\": \"**athletes.athlete**\",\n    \"18-2\": \"An object containing the timing data for an individual athlete\",\n    \"18-3\": \"object\",\n    \"26-0\": \"athlete.difference\",\n    \"26-1\": \"00:01:13.134\",\n    \"26-2\": \"An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the difference at the latest timing point\",\n    \"26-3\": \"string\",\n    \"23-0\": \"athlete.segment_id\",\n    \"23-3\": \"integer\",\n    \"23-1\": \"1\",\n    \"23-2\": \"The latest segment_id of the athlete\",\n    \"27-0\": \"athlete.status\",\n    \"27-1\": \"DNF\",\n    \"27-2\": \"An optional field to include additional information regarding the race status of the athlete which should be one of DNS, DNF, DSQ, LAP or NC\",\n    \"27-3\": \"string\",\n    \"30-0\": \"**athletes.splits.segment**\",\n    \"30-2\": \"A segment object containing athlete timing data for each individual segment.\",\n    \"30-3\": \"object\",\n    \"9-0\": \"status\",\n    \"9-1\": \"live\",\n    \"9-2\": \"The status of the results (one of prerace, live, official). Once confirmed by race referee the status should be updated to official. Prior to the race a status of prerace should be used and once timing has started changed to live.\",\n    \"9-3\": \"string\",\n    \"6-0\": \"wetsuit\",\n    \"6-1\": \"true\",\n    \"6-2\": \"Boolean to indicate whether it is a wetsuit swim\",\n    \"6-3\": \"boolean\",\n    \"14-0\": \"**conditions**\",\n    \"14-2\": \"An object containing the latest course conditions\",\n    \"14-3\": \"object\",\n    \"15-0\": \"air_temp\",\n    \"15-1\": \"12.5\",\n    \"15-3\": \"float\",\n    \"16-0\": \"water_temp\",\n    \"16-1\": \"18.4\",\n    \"16-3\": \"float\",\n    \"15-2\": \"The official air temperature in degrees Celsius\",\n    \"16-2\": \"The official water temperature in degrees Celsius\",\n    \"28-0\": \"athlete.incidents\",\n    \"28-1\": \"10 second penalty for bike infringement\",\n    \"28-2\": \"An optional field to include additional information regarding any incidents such as penalties that an athlete has incurred formatted according to the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines).\",\n    \"28-3\": \"string\"\n  },\n  \"cols\": 4,\n  \"rows\": 37\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Sending JSON or XML data\",\n  \"body\": \"You may send JSON or XML data. To send JSON you must include a header of `Content-Type` set to `application/json`. For XML data the `Content-Type` must be set to `application/xml`.\"\n}\n[/block]\n## Athlete Ordering\n\nAthletes should be ordered in the **athletes** array according to the position at the respective timing points. Naturally, athletes who have passed the latest timing point will be ordered first followed by previous timing points. At the start of the race or where ordering is not possible due to non-completion of segments athletes should by default be ordered by start number.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Default to ordering by start_num where no further ordering is possible\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Timing Points\"\n}\n[/block]\nSegment IDs should be named according to the convention below and increase sequentially for each segment. The first timing segment will always be 1.\n\n**Example Standard Distance Race**\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Segment ID\",\n    \"h-1\": \"Segment Name\",\n    \"0-0\": \"0\",\n    \"14-0\": \"14\",\n    \"1-0\": \"1\",\n    \"2-0\": \"2\",\n    \"3-0\": \"3\",\n    \"4-0\": \"4\",\n    \"5-0\": \"5\",\n    \"6-0\": \"6\",\n    \"7-0\": \"7\",\n    \"8-0\": \"8\",\n    \"9-0\": \"9\",\n    \"10-0\": \"10\",\n    \"11-0\": \"11\",\n    \"12-0\": \"12\",\n    \"13-0\": \"13\",\n    \"15-0\": \"15\",\n    \"16-0\": \"16\",\n    \"0-1\": \"Start\",\n    \"1-1\": \"Swim Lap 1\",\n    \"2-1\": \"Swim Exit\",\n    \"3-1\": \"Transition 1\",\n    \"4-1\": \"Bike Lap 1\",\n    \"5-1\": \"Bike Lap 2\",\n    \"6-1\": \"Bike Lap 3\",\n    \"7-1\": \"Bike Lap 4\",\n    \"8-1\": \"Bike Lap 5\",\n    \"9-1\": \"Bike Lap 6\",\n    \"10-1\": \"Bike Lap 7\",\n    \"11-1\": \"Bike End\",\n    \"12-1\": \"Transition 2\",\n    \"13-1\": \"Run Lap 1\",\n    \"14-1\": \"Run Lap 2\",\n    \"15-1\": \"Run Lap 3\",\n    \"16-1\": \"Finish\"\n  },\n  \"cols\": 2,\n  \"rows\": 17\n}\n[/block]\n\n**Example Sprint Distance Race**\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Segment ID\",\n    \"h-1\": \"Segment Name\",\n    \"0-0\": \"0\",\n    \"1-0\": \"1\",\n    \"2-0\": \"2\",\n    \"3-0\": \"3\",\n    \"4-0\": \"4\",\n    \"5-0\": \"5\",\n    \"6-0\": \"6\",\n    \"7-0\": \"7\",\n    \"8-0\": \"8\",\n    \"9-0\": \"9\",\n    \"0-1\": \"Start\",\n    \"1-1\": \"Swim Exit\",\n    \"2-1\": \"Transition 1\",\n    \"3-1\": \"Bike Lap 1\",\n    \"4-1\": \"Bike Lap 2\",\n    \"5-1\": \"Bike Lap 3\",\n    \"6-1\": \"Bike End\",\n    \"7-1\": \"Transition 2\",\n    \"8-1\": \"Run Lap 1\",\n    \"9-1\": \"Finish\"\n  },\n  \"cols\": 2,\n  \"rows\": 10\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Timing Delivery\"\n}\n[/block]\nThere are two options for timing delivery namely a hosting of a static file and a POST method. Choice of timing delivery is up to the individual timer.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Option #2 is preferred\",\n  \"body\": \"Whilst we offer static file hosting to support existing timers the POST method of delivery is much preferred and should be chosen where it is an option.\"\n}\n[/block]\n## 1 - Static File Hosting\n\nThis method replicates the prior version of the timing standard where a timer hosts a single JSON or XML file and this is polled by the Triathlon.org servers (note this is not a public facing application and only accessed by Triathlon.org which acts as a proxy). **The URL format is completely discretionary** as long as it is accessible on the internet (you may protect the file if required such as using basic authentication or a token). \n\nTiming updates should be provided as quickly as possible whilst maintaining consistency. Updates to the file should preferably only be made when new timing information is available. Whilst the lower latency the better any update frequency under **10,000ms** (10 seconds) will be deemed acceptable.\n\n## 2 - POST JSON or XML Data \n\nThis method removes the requirement for a timer to host any files as the XML is simply POSTed to the Triathlon API ([https://api.triathlon.org/live/timing](https://api.triathlon.org/live/timing)) on any change of data i.e. an athlete crossing a timing mat.\n\nTiming messages should be delivered as soon as feasible. Data messages should be sent as soon as an athlete crosses a timing point. For occasions when there would be an overwhelming number of updates e.g. a large bike pack crossing a timing point, messages should be combined into a single message such that push frequency do not exceed one push every 1000ms. If POSTing data, **messages should only be pushed when there is a change of information in the message** and messages should not be sent according to a fixed time schedule.\n\nMessages should be sent with a `Content-Type` set to `application/xml` with the XML forming the body of the request or `application/json` for JSON data.\n\n### Authentication\n\nTimers will use the [standard API authentication](https://developers.triathlon.org/docs/authentication) method adding authentication parameters to the header of all requests sent. **Each timer will be provided a unique API key to use specific to their timing application**.\n\n### Response Codes\n\nThe Triathlon.org API will respond with a 2xx response on successful receipt of the message. All other response codes should be considered a failure. Badly formatted or unauthenticated messages will result in a 4xx code. For reference, our general response codes are available [here](https://developers.triathlon.org/docs/responses-and-status-codes).\n\n### Retry Policy\n\nTimers should implement a retry policy to primarily cover the case of a loss of internet connectivity at the venue. **As each message contains entire timing information if a later message is available there is no need to retry an earlier message**. For reference you may also consult the [retries policy](https://developers.triathlon.org/docs/subscriptions-api-overview#retries) of the Subscription API.\n\n### Message Persistence\n\nTimers do not need to persist timing messages as this will be handled via the Triathlon API platform with specific messages available for historical analysis / replay via the [Live API](https://developers.triathlon.org/docs/live-api-overview).\n\n### Concurrent Races\n\nOften there will be more than one race occurring at the same time (defined by `prog_id`). Each race should be considered a single entity and formatted according to the specification. Logic should be present to handle instances when multiple athletes from different races cross a timing point at the same time.\n[block:api-header]\n{\n  \"title\": \"Timing Implementation\"\n}\n[/block]\n* An initial start list message will be published once the final start lists have been confirmed (which occurs at the race briefing). This will detail the `start_time`, the `event_id` and `prog_id` as well as containing the data for each athlete on the start list (you may use the athlete_id to get further information for each athlete from the Athletes API). Any athletes that withdraw between the briefing and the start of the race are considered `DNS` athletes.\n* Any changes to the published start times, condition information or any `DNS` (indicated in the `athlete.status field`) will be indicated by a new timing message. \n* Any messages sent prior to the start of the race will be indicated by a status of `prerace`.\n* As soon as the race begins the `start_time` containing the accurate start time will be published and the `status` will be updated to live indicating that the race is underway.\n* As soon as the first athlete crosses the first timing point the `latest` block will be updated to include the details of the segment (i.e. segment_id and segment_name) as well as how many athletes have crossed the timing point (which may be used to create leaderboards). Whilst timing messages are pushed whenever there is new data, on occasions timing messages will be combined into a single message e.g. a bike pack crossing a timing point will not have a message for each athlete. As each timing message always contains full timing information you should simply act on the latest message received.\n* This process continues through each segment of the race with the latest block always indicating the latest timing point. Any athlete that withdraws from the race, is disqualified or incurs a penalty should have their `status` [updated accordingly](https://developers.triathlon.org/v1/page/live-timing-standard-v11#other-timing-notes).\n* Once the race has finished and the results are confirmed a final message with a status of `official` will be published.\n[block:api-header]\n{\n  \"title\": \"Other Timing Notes\"\n}\n[/block]\n* If an athlete is disqualified during the race, the status of the athlete should be updated to `DSQ` and the athlete should be ordered at the bottom of the athlete array. The reason for disqualification should be added to the `incidents` key using the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). Athletes should only be set as `DSQ` on confirmation from the Chief Technology Officer. As disqualified athletes may continue on the course (in lieu of appealing the decision) all disqualified athlete times should continue to be delivered in the timing messages. If an athlete successfully protests the `DSQ` the athlete should be reinstated in the corresponding position in the athlete array once confirmed by the Chief Technology Officer.\n* If an athlete withdraws from the race, once confirmed by the Chief Technology Officer, the status of the athlete should be updated to `DNF`. If a `DNF` reason is available it should be added to the `incidents` key according to the format specified by the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). \n* If an athlete has a penalty confirmed by the Chief Technology Officer the `incidents` key of the athlete object should be updated to indicate the penalty to be served in accordance with the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). Once an athlete has served the penalty, and has been confirmed by the Chief Technology Officer, the `incidents` key should be updated by prepending the word `Served` e.g. `Served x second penalty for infringement name`.\n* If the timer does not send millisecond data but instead only delivers times as full seconds, the raw millisecond data should be truncated as opposed to numeric rounding or rounding to the next full second. As an example `01:01:34.752` should be presented as `01:01:34`.\n[block:api-header]\n{\n  \"title\": \"Standard Incident Guidelines\"\n}\n[/block]\nWhen adding penalty or disqualification information the following guidelines should be followed for reporting as notified by the Chief Technology Officer. The message should be updated to include when the penalty has been served.\n\n* x second penalty for infringement name\n* Served x second penalty for infringement name\n* DSQ for infringement name\n\nExamples:\n\n* 15 second penalty for cutting the swim course\n* Served 15 second penalty for cutting the swim course\n* DSQ for cutting the swim course\n* Withdrew from the race due to bike crash.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Mixed Relay Timing\"\n}\n[/block]\nFull details for mixed relay timing will be updated shortly but will follow a very similar syntax with an additional layer of information which comprises individual data.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Paratriathlon\"\n}\n[/block]\nWhere applicable a Paratriathlon object may be included in each athlete object to specify additional Paratriathlon information such as guide names and additional meta information.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{  \\n    \\\"athlete_id\\\": \\\"123456\\\",\\n    .....\\n  \\t\\\"paratriathlon\\\":{  \\n      \\\"subclass\\\":\\\"B2\\\",\\n      \\\"guide_name\\\":\\\"Guide Name\\\",\\n      \\\"guide_id\\\":\\\"654321\\\",\\n      \\\"delay\\\":\\\"00:03:46\\\"\\n   }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<athlete>\\n\\t<paratriathlon>\\n  \\t<subclass>B2</subclass>\\n  \\t<guide_name>Guide Name</guide_name>\\n    <guide_id>123456</guide_id>\\n    <delay>00:03:46<delay>\\n  </paratriathlon>\\n</athlete>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\nA breakdown of each parameter is listed below:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Parameter\",\n    \"h-1\": \"Example\",\n    \"h-2\": \"Description\",\n    \"h-3\": \"Format\",\n    \"0-0\": \"**paratriathlon** \",\n    \"0-2\": \"The paratriathlon object contains specific information regarding the paratriathlete and is only present for Paratriathlon events\",\n    \"0-3\": \"object\",\n    \"1-0\": \"paratriathlon.subclass\",\n    \"1-1\": \"B1\",\n    \"1-2\": \"Indicates a paratriathlon subclass if relevant\",\n    \"1-3\": \"string\",\n    \"2-0\": \"paratriathlon.guide_name\",\n    \"2-1\": \"Athlete Name\",\n    \"2-2\": \"The name of the paratriathlon guide for visual impairment categories\",\n    \"2-3\": \"string\",\n    \"3-0\": \"paratriathlon.guide_id\",\n    \"3-1\": \"123456\",\n    \"3-3\": \"integer\",\n    \"3-2\": \"The unique athlete_id corresponding to the athlete_id in the Athletes API\",\n    \"4-0\": \"delay\",\n    \"4-3\": \"string\",\n    \"4-1\": \"00:00:30\",\n    \"4-2\": \"An ISO 8601 formatted time of the start time offset\"\n  },\n  \"cols\": 4,\n  \"rows\": 5\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Timing Extension Objects\"\n}\n[/block]\nThe timing standard is designed to be flexible to incorporate additional information if and when it is available. For example in addition to the paratriathlon extension it would be possible to add support for GPS locations though the use of a location object. These additional extensions will be formalised where their usage becomes available and would require updates at periodic intervals.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<athlete>\\n\\t<location>\\n  \\t<latitude>51.5032520</latitude>\\n  \\t<longitude>-0.1278990</longitude>\\n    <elevation>4.69</elevation>\\n    <speed>45.7<speed>\\n  </location>\\n</athlete>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Distribution\"\n}\n[/block]\nTiming will be distributed by the Triathlon API platform to applications through the [Live REST API](https://developers.triathlon.org/docs/live-api-overview), [Subscriptions API](https://developers.triathlon.org/docs/subscriptions-api-overview) and [Streaming APIs](https://developers.triathlon.org/docs/streaming-api-overview) to all connected applications.","slug":"live-timing-standard-v11","title":"Live Timing Standard v1.1"}

Live Timing Standard v1.1


[block:callout] { "type": "success", "title": "Version 1.1 of the Live Timing Standard will be mandatory for all World Triathlon Series events", "body": "For World Cup and other events the implementation of the standard will be optional but implementing will enable live timing to be shown on Triathlon.org as well as other custom-built applications." } [/block] **Version 1.1** of the live timing standard builds upon the original [version 1](https://developers.triathlon.org/v1/page/live-timing-standard-v10) of the live timing standard with some notable changes in order to enhance the timing delivery. We have attempted to maintain as much consistency as possible with the prior version to ease the upgrade process. The most notable changes are: * All results are now provided in a single XML or JSON output rather than the separate leaderboard and splits files that were previously required. * All athletes (and corresponding split data) are now included in the timing output regardless of the position of the athlete. This differs in that, in the prior version, only athletes that had crossed the latest timing point were included in the output. * Timers now have the option of either hosting the XML or JSON file or making a POST request to ITU servers with the timing data if it is preferred to eliminate the requirement to host any files (see [delivery options](https://developers.triathlon.org/v1/page/live-timing-standard-v11#delivery-options) for an enhanced explanation). * Race incidents such as DNFs are now able to be included which may be publicly viewable on a race incidents page. * This timing standard removes the requirement for timers to upload intermediate results to Triathlon.org for ranking generation purposes. * Timers have the option of sending JSON data rather than only XML as before. * Live timing is now available to all ITU events that support the live timing standard. [block:api-header] { "type": "basic", "title": "Overview" } [/block] The aim of **Version 1.1** of the Triathlon.org Live Timing Standard is to produce a higher quality of real-time timing data directly from races which may be delivered via the Triathlon.org API platform to subscribers. The improvements in the standard greatly increase the potential for displaying timing data and developing feature-rich timing applications when used in conjunction with other [available APIs](https://developers.triathlon.org/docs). The standard also removes the requirement for timers to host any web-facing files as timing may be pushed to the Triathlon.org API platform which will handle the delivery of timing messages to all connected clients. This push method of delivery is entirely optional as the standard also allows for a single timing file hosted by the timers to be accessed solely by ITU's servers and is not public facing (see [delivery options](https://developers.triathlon.org/v1/page/live-timing-standard-v11#delivery-options)). ## Timing Message Format **Each timing message should contain complete timing information** such that a user may be able to retrieve all information by receiving the latest timing message. **All message characters should be UTF-8 formatted**. All times and dates should be formatted according to the [ISO 8601 standard](https://en.wikipedia.org/wiki/ISO_8601) and millisecond data should be included if available. Data should only be included if available e.g. segment values should only be included once an athlete has completed the segment. [block:api-header] { "title": "Example Messages" } [/block] The following messages only contain 2 athletes for brevity and you should refer to the extended examples below for full timing messages. [block:code] { "codes": [ { "code": "{\n \"date\":\"2017-03-04 18:25:11+04:00\",\n \"start_time\":\"2017-03-04 15:55:00+04:00\",\n \"event_id\":\"107158\",\n \"event_name\":\"2017 ITU World Triathlon Abu Dhabi\",\n \"prog_id\":\"307158\",\n \"prog_name\":\"Elite Men\",\n \"wetsuit\":\"false\",\n \"sandbox\":\"false\",\n \"num_athletes\":\"2\",\n \"status\":\"live\",\n \"latest\":{\n \"segment_id\":\"2\",\n \"segment_name\":\"Swim Exit\",\n \"num_athletes\":\"1\"\n },\n \"conditions\":{\n \"air_temp\":\"28.8\",\n \"water_temp\":\"23.2\"\n },\n \"athletes\":[\n {\n \"id\":\"5695\",\n \"start_num\":\"26\",\n \"name\":\"Javier Gomez Noya\",\n \"country\":\"ESP\",\n \"segment_id\":\"18\",\n \"time\":\"00:18:37.911\",\n \"difference\":\"00:00:00.000\",\n \"position\":\"1\",\n \"status\":null,\n \"incidents\":null,\n \"splits\":[\n {\n \"id\":\"1\",\n \"name\":\"Swim Lap 1\",\n \"total_time\":\"00:10:54.799\",\n \"time\":\"00:10:54.799\",\n \"difference\":\"00:00:11.001\",\n \"position\":\"10\"\n },\n {\n \"id\":\"2\",\n \"name\":\"Swim Exit\",\n \"total_time\":\"00:18:37.911\",\n \"time\":\"00:07:43.112\",\n \"difference\":\"00:00:11.320\",\n \"position\":\"14\"\n }\n ]\n },\n {\n \"id\":\"18719\",\n \"start_num\":\"22\",\n \"name\":\"Thomas Bishop\",\n \"country\":\"GBR\",\n \"segment_id\":\"1\",\n \"time\":\"00:10:53.996\",\n \"difference\":\"00:00:10.198\",\n \"position\":\"2\",\n \"status\":null,\n \"incidents\":null,\n \"splits\":[\n {\n \"id\":\"1\",\n \"name\":\"Swim Lap 1\",\n \"total_time\":\"00:10:53.996\",\n \"time\":\"00:10:53.996\",\n \"difference\":\"00:00:10.198\",\n \"position\":\"9\"\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block] [block:code] { "codes": [ { "code": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<timing>\n <date>2017-01-01T13:34:59.123Z</date>\n <start_time>2017-01-01T13:30:59.123Z</start_time>\n <event_id>123456</event_id>\n <event_name>ITU World Triathlon Series Yokohama</event_name>\n <prog_id>123456</prog_id>\n <prog_name>Elite Women</prog_name>\n <wetsuit>false</wetsuit>\n <sandbox>false</sandbox>\n <num_athletes>2</num_athletes>\n <status>live</status>\n <latest>\n <segment_id>2</segment_id>\n <segment_name>Swim Exit</segment_name>\n <num_athletes>1</num_athletes>\n </latest>\n <conditions>\n <air_temp>16.5</air_temp>\n <water_temp>18.4</water_temp>\n </conditions>\n <athletes>\n <athlete>\n <id>40887</id>\n <start_num>2</start_num>\n <name>Gwen Jorgensen</name>\n <country>USA</country>\n <segment_id>2</segment_id>\n <time>00:18:12</time>\n <difference>00:00:00</difference>\n <position>1</position>\n <status></status>\n <incidents></incidents>\n <splits>\n <segment>\n <id>1</id>\n <name>Swim Lap 1</name>\n <time>00:09:00</time>\n <total_time>00:09:00</total_time>\n <difference>00:00:11</difference>\n <position>2</position>\n </segment>\n <segment>\n <id>2</id>\n <name>Swim Exit</name>\n <time>00:09:12</time>\n <total_time>00:18:12</total_time>\n <difference>00:00:00</difference>\n <position>1</position>\n </segment>\n </splits>\n </athlete>\n <athlete>\n <id>31438</id>\n <start_num>1</start_num>\n <name>Non Stanford</name>\n <country>GBR</country>\n <segment_id>1</segment_id>\n <time>00:08:57</time>\n <difference>00:00:00</difference>\n <position>1</position>\n <status></status>\n <incidents></incidents>\n <splits>\n <segment>\n <id>1</id>\n <name>Swim Lap 1</name>\n <time>00:08:57</time>\n <total_time>00:08:57</total_time>\n <difference>00:00:00</difference>\n <position>1</position>\n </segment>\n </splits>\n </athlete>\n </athletes>\n</timing>", "language": "xml" } ] } [/block] [block:callout] { "type": "success", "title": "Complete Timing Examples", "body": "A full timing example in JSON is available [here](https://gist.githubusercontent.com/garethtdavies/fe58f5085b6e474884b93852a43c8058/raw/ca92c21f64a0fe56cbede113db3826f19c0c9c95/yokohama-ew-official.json)." } [/block] ## Demonstration Links A very basic front-end implementation of an XML [sample file](https://gist.github.com/garethtdavies/1f47cd7c7133593b0137963f0a72c0d9) is available at the following links: * [Leaderboard](https://data.triathlon.org/timing/281501) * [Segment Splits](https://data.triathlon.org/timing/281501/splits/2) * [Race Incidents](https://data.triathlon.org/timing/281501/incidents) [block:api-header] { "title": "Timing Parameters" } [/block] A breakdown of each parameter is listed below ( a penalty field will be added shortly). [block:parameters] { "data": { "h-0": "Parameter", "h-1": "Example", "h-2": "Description", "0-0": "date", "0-1": "2017-01-01T13:34:59.123Z", "0-2": "An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) of the time the message was published", "5-0": "prog_name", "5-1": "Elite Men", "5-2": "A descriptive name for the race corresponding to the [Events API](https://developers.triathlon.org/docs/events-api-overview)", "h-3": "Format", "0-3": "string", "5-3": "string", "8-0": "num_athletes", "10-0": "**latest** ", "10-3": "object", "10-2": "The latest object contains information regarding the latest timing point data (may be *null* if no timing data)", "11-0": "latest.segment_id", "12-0": "latest.segment_name", "13-0": "latest.num_athletes", "11-2": "The segment_id containing the latest result", "11-1": "1", "11-3": "integer", "12-2": "The segment name containing the latest results", "12-1": "Swim Exit", "12-3": "string", "13-1": "12", "13-2": "The number of athletes that have passed through the timing point", "13-3": "number", "8-2": "The number of athletes in the race (which must correspond to the number of items in the athletes array)", "8-1": "12", "8-3": "integer", "17-0": "**athletes** ", "17-2": "An object containing an array of all athlete objects in the race", "17-3": "object", "19-0": "athlete.id", "20-0": "athlete.start_num", "21-0": "athlete.name", "22-0": "athlete.country", "24-0": "athlete.position", "29-0": "**athletes.splits** ", "25-0": "athlete.time", "22-2": "The three letter [IOC country code](https://en.wikipedia.org/wiki/List_of_IOC_country_codes)", "22-3": "string", "22-1": "GBR", "19-2": "The unique athlete_id corresponding to the athlete_id in the [Athletes API](https://developers.triathlon.org/docs/athletes-api-overview)", "19-1": "123456", "19-3": "integer", "20-1": "12", "20-2": "The start number of the athlete", "20-3": "integer", "21-1": "Alistair Brownlee", "21-2": "The name of the athlete", "21-3": "string", "24-1": "12", "24-2": "The position of the athlete (may be *null* if no data) at the latest timing point", "24-3": "number", "25-1": "00:17:16.145", "25-2": "An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of the athlete's latest timing point", "25-3": "string", "29-1": "", "29-2": "An array of split objects containing data for each segment completed by the athlete (may be *null *if no data)", "29-3": "object", "31-0": "segment.id", "32-0": "segment.name", "33-0": "segment.time", "34-0": "segment.total_time", "35-0": "segment.position", "36-0": "segment.difference", "31-2": "The segment_id of the split", "32-2": "The name of the timing segment", "33-2": "The time to complete this segment", "34-2": "The cumulative time of all segments to this point", "34-3": "string", "35-2": "The position of the athlete at this timing point", "35-3": "integer", "36-2": "An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of difference of the athlete to the leader at this timing point", "36-3": "string", "36-1": "00:01:07.123", "35-1": "12", "34-1": "00:14:12.345", "33-1": "00:08:16.345", "32-1": "Swim Exit", "31-1": "3", "31-3": "integer", "32-3": "string", "33-3": "string", "7-0": "sandbox", "7-1": "true", "7-3": "boolean", "7-2": "Boolean to indicate whether to use the sandbox environment for development (defaults to false)", "1-0": "start_time", "1-1": "2017-01-01T13:34:59.123Z", "1-2": "An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the start time of the race", "1-3": "string", "2-0": "event_id", "3-0": "event_name", "2-1": "123456", "3-1": "2016 ITU World Triathlon Abu Dhabi", "2-2": "The unique event_id corresponding to the event_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)", "3-2": "A descriptive name for the event corresponding to the [Events API](https://developers.triathlon.org/docs/events-api-overview)", "4-0": "prog_id", "4-1": "123456", "4-2": "The unique prog_id corresponding to the prog_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)", "4-3": "integer", "3-3": "string", "2-3": "integer", "18-0": "**athletes.athlete**", "18-2": "An object containing the timing data for an individual athlete", "18-3": "object", "26-0": "athlete.difference", "26-1": "00:01:13.134", "26-2": "An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the difference at the latest timing point", "26-3": "string", "23-0": "athlete.segment_id", "23-3": "integer", "23-1": "1", "23-2": "The latest segment_id of the athlete", "27-0": "athlete.status", "27-1": "DNF", "27-2": "An optional field to include additional information regarding the race status of the athlete which should be one of DNS, DNF, DSQ, LAP or NC", "27-3": "string", "30-0": "**athletes.splits.segment**", "30-2": "A segment object containing athlete timing data for each individual segment.", "30-3": "object", "9-0": "status", "9-1": "live", "9-2": "The status of the results (one of prerace, live, official). Once confirmed by race referee the status should be updated to official. Prior to the race a status of prerace should be used and once timing has started changed to live.", "9-3": "string", "6-0": "wetsuit", "6-1": "true", "6-2": "Boolean to indicate whether it is a wetsuit swim", "6-3": "boolean", "14-0": "**conditions**", "14-2": "An object containing the latest course conditions", "14-3": "object", "15-0": "air_temp", "15-1": "12.5", "15-3": "float", "16-0": "water_temp", "16-1": "18.4", "16-3": "float", "15-2": "The official air temperature in degrees Celsius", "16-2": "The official water temperature in degrees Celsius", "28-0": "athlete.incidents", "28-1": "10 second penalty for bike infringement", "28-2": "An optional field to include additional information regarding any incidents such as penalties that an athlete has incurred formatted according to the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines).", "28-3": "string" }, "cols": 4, "rows": 37 } [/block] [block:callout] { "type": "success", "title": "Sending JSON or XML data", "body": "You may send JSON or XML data. To send JSON you must include a header of `Content-Type` set to `application/json`. For XML data the `Content-Type` must be set to `application/xml`." } [/block] ## Athlete Ordering Athletes should be ordered in the **athletes** array according to the position at the respective timing points. Naturally, athletes who have passed the latest timing point will be ordered first followed by previous timing points. At the start of the race or where ordering is not possible due to non-completion of segments athletes should by default be ordered by start number. [block:callout] { "type": "warning", "title": "Default to ordering by start_num where no further ordering is possible" } [/block] [block:api-header] { "type": "basic", "title": "Timing Points" } [/block] Segment IDs should be named according to the convention below and increase sequentially for each segment. The first timing segment will always be 1. **Example Standard Distance Race** [block:parameters] { "data": { "h-0": "Segment ID", "h-1": "Segment Name", "0-0": "0", "14-0": "14", "1-0": "1", "2-0": "2", "3-0": "3", "4-0": "4", "5-0": "5", "6-0": "6", "7-0": "7", "8-0": "8", "9-0": "9", "10-0": "10", "11-0": "11", "12-0": "12", "13-0": "13", "15-0": "15", "16-0": "16", "0-1": "Start", "1-1": "Swim Lap 1", "2-1": "Swim Exit", "3-1": "Transition 1", "4-1": "Bike Lap 1", "5-1": "Bike Lap 2", "6-1": "Bike Lap 3", "7-1": "Bike Lap 4", "8-1": "Bike Lap 5", "9-1": "Bike Lap 6", "10-1": "Bike Lap 7", "11-1": "Bike End", "12-1": "Transition 2", "13-1": "Run Lap 1", "14-1": "Run Lap 2", "15-1": "Run Lap 3", "16-1": "Finish" }, "cols": 2, "rows": 17 } [/block] **Example Sprint Distance Race** [block:parameters] { "data": { "h-0": "Segment ID", "h-1": "Segment Name", "0-0": "0", "1-0": "1", "2-0": "2", "3-0": "3", "4-0": "4", "5-0": "5", "6-0": "6", "7-0": "7", "8-0": "8", "9-0": "9", "0-1": "Start", "1-1": "Swim Exit", "2-1": "Transition 1", "3-1": "Bike Lap 1", "4-1": "Bike Lap 2", "5-1": "Bike Lap 3", "6-1": "Bike End", "7-1": "Transition 2", "8-1": "Run Lap 1", "9-1": "Finish" }, "cols": 2, "rows": 10 } [/block] [block:api-header] { "type": "basic", "title": "Timing Delivery" } [/block] There are two options for timing delivery namely a hosting of a static file and a POST method. Choice of timing delivery is up to the individual timer. [block:callout] { "type": "warning", "title": "Option #2 is preferred", "body": "Whilst we offer static file hosting to support existing timers the POST method of delivery is much preferred and should be chosen where it is an option." } [/block] ## 1 - Static File Hosting This method replicates the prior version of the timing standard where a timer hosts a single JSON or XML file and this is polled by the Triathlon.org servers (note this is not a public facing application and only accessed by Triathlon.org which acts as a proxy). **The URL format is completely discretionary** as long as it is accessible on the internet (you may protect the file if required such as using basic authentication or a token). Timing updates should be provided as quickly as possible whilst maintaining consistency. Updates to the file should preferably only be made when new timing information is available. Whilst the lower latency the better any update frequency under **10,000ms** (10 seconds) will be deemed acceptable. ## 2 - POST JSON or XML Data This method removes the requirement for a timer to host any files as the XML is simply POSTed to the Triathlon API ([https://api.triathlon.org/live/timing](https://api.triathlon.org/live/timing)) on any change of data i.e. an athlete crossing a timing mat. Timing messages should be delivered as soon as feasible. Data messages should be sent as soon as an athlete crosses a timing point. For occasions when there would be an overwhelming number of updates e.g. a large bike pack crossing a timing point, messages should be combined into a single message such that push frequency do not exceed one push every 1000ms. If POSTing data, **messages should only be pushed when there is a change of information in the message** and messages should not be sent according to a fixed time schedule. Messages should be sent with a `Content-Type` set to `application/xml` with the XML forming the body of the request or `application/json` for JSON data. ### Authentication Timers will use the [standard API authentication](https://developers.triathlon.org/docs/authentication) method adding authentication parameters to the header of all requests sent. **Each timer will be provided a unique API key to use specific to their timing application**. ### Response Codes The Triathlon.org API will respond with a 2xx response on successful receipt of the message. All other response codes should be considered a failure. Badly formatted or unauthenticated messages will result in a 4xx code. For reference, our general response codes are available [here](https://developers.triathlon.org/docs/responses-and-status-codes). ### Retry Policy Timers should implement a retry policy to primarily cover the case of a loss of internet connectivity at the venue. **As each message contains entire timing information if a later message is available there is no need to retry an earlier message**. For reference you may also consult the [retries policy](https://developers.triathlon.org/docs/subscriptions-api-overview#retries) of the Subscription API. ### Message Persistence Timers do not need to persist timing messages as this will be handled via the Triathlon API platform with specific messages available for historical analysis / replay via the [Live API](https://developers.triathlon.org/docs/live-api-overview). ### Concurrent Races Often there will be more than one race occurring at the same time (defined by `prog_id`). Each race should be considered a single entity and formatted according to the specification. Logic should be present to handle instances when multiple athletes from different races cross a timing point at the same time. [block:api-header] { "title": "Timing Implementation" } [/block] * An initial start list message will be published once the final start lists have been confirmed (which occurs at the race briefing). This will detail the `start_time`, the `event_id` and `prog_id` as well as containing the data for each athlete on the start list (you may use the athlete_id to get further information for each athlete from the Athletes API). Any athletes that withdraw between the briefing and the start of the race are considered `DNS` athletes. * Any changes to the published start times, condition information or any `DNS` (indicated in the `athlete.status field`) will be indicated by a new timing message. * Any messages sent prior to the start of the race will be indicated by a status of `prerace`. * As soon as the race begins the `start_time` containing the accurate start time will be published and the `status` will be updated to live indicating that the race is underway. * As soon as the first athlete crosses the first timing point the `latest` block will be updated to include the details of the segment (i.e. segment_id and segment_name) as well as how many athletes have crossed the timing point (which may be used to create leaderboards). Whilst timing messages are pushed whenever there is new data, on occasions timing messages will be combined into a single message e.g. a bike pack crossing a timing point will not have a message for each athlete. As each timing message always contains full timing information you should simply act on the latest message received. * This process continues through each segment of the race with the latest block always indicating the latest timing point. Any athlete that withdraws from the race, is disqualified or incurs a penalty should have their `status` [updated accordingly](https://developers.triathlon.org/v1/page/live-timing-standard-v11#other-timing-notes). * Once the race has finished and the results are confirmed a final message with a status of `official` will be published. [block:api-header] { "title": "Other Timing Notes" } [/block] * If an athlete is disqualified during the race, the status of the athlete should be updated to `DSQ` and the athlete should be ordered at the bottom of the athlete array. The reason for disqualification should be added to the `incidents` key using the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). Athletes should only be set as `DSQ` on confirmation from the Chief Technology Officer. As disqualified athletes may continue on the course (in lieu of appealing the decision) all disqualified athlete times should continue to be delivered in the timing messages. If an athlete successfully protests the `DSQ` the athlete should be reinstated in the corresponding position in the athlete array once confirmed by the Chief Technology Officer. * If an athlete withdraws from the race, once confirmed by the Chief Technology Officer, the status of the athlete should be updated to `DNF`. If a `DNF` reason is available it should be added to the `incidents` key according to the format specified by the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). * If an athlete has a penalty confirmed by the Chief Technology Officer the `incidents` key of the athlete object should be updated to indicate the penalty to be served in accordance with the [standard incident guidelines](https://developers.triathlon.org/v1/page/live-timing-standard-v11#standard-incident-guidelines). Once an athlete has served the penalty, and has been confirmed by the Chief Technology Officer, the `incidents` key should be updated by prepending the word `Served` e.g. `Served x second penalty for infringement name`. * If the timer does not send millisecond data but instead only delivers times as full seconds, the raw millisecond data should be truncated as opposed to numeric rounding or rounding to the next full second. As an example `01:01:34.752` should be presented as `01:01:34`. [block:api-header] { "title": "Standard Incident Guidelines" } [/block] When adding penalty or disqualification information the following guidelines should be followed for reporting as notified by the Chief Technology Officer. The message should be updated to include when the penalty has been served. * x second penalty for infringement name * Served x second penalty for infringement name * DSQ for infringement name Examples: * 15 second penalty for cutting the swim course * Served 15 second penalty for cutting the swim course * DSQ for cutting the swim course * Withdrew from the race due to bike crash. [block:api-header] { "type": "basic", "title": "Mixed Relay Timing" } [/block] Full details for mixed relay timing will be updated shortly but will follow a very similar syntax with an additional layer of information which comprises individual data. [block:api-header] { "type": "basic", "title": "Paratriathlon" } [/block] Where applicable a Paratriathlon object may be included in each athlete object to specify additional Paratriathlon information such as guide names and additional meta information. [block:code] { "codes": [ { "code": "{ \n \"athlete_id\": \"123456\",\n .....\n \t\"paratriathlon\":{ \n \"subclass\":\"B2\",\n \"guide_name\":\"Guide Name\",\n \"guide_id\":\"654321\",\n \"delay\":\"00:03:46\"\n }\n}", "language": "json" } ] } [/block] [block:code] { "codes": [ { "code": "<athlete>\n\t<paratriathlon>\n \t<subclass>B2</subclass>\n \t<guide_name>Guide Name</guide_name>\n <guide_id>123456</guide_id>\n <delay>00:03:46<delay>\n </paratriathlon>\n</athlete>", "language": "xml" } ] } [/block] A breakdown of each parameter is listed below: [block:parameters] { "data": { "h-0": "Parameter", "h-1": "Example", "h-2": "Description", "h-3": "Format", "0-0": "**paratriathlon** ", "0-2": "The paratriathlon object contains specific information regarding the paratriathlete and is only present for Paratriathlon events", "0-3": "object", "1-0": "paratriathlon.subclass", "1-1": "B1", "1-2": "Indicates a paratriathlon subclass if relevant", "1-3": "string", "2-0": "paratriathlon.guide_name", "2-1": "Athlete Name", "2-2": "The name of the paratriathlon guide for visual impairment categories", "2-3": "string", "3-0": "paratriathlon.guide_id", "3-1": "123456", "3-3": "integer", "3-2": "The unique athlete_id corresponding to the athlete_id in the Athletes API", "4-0": "delay", "4-3": "string", "4-1": "00:00:30", "4-2": "An ISO 8601 formatted time of the start time offset" }, "cols": 4, "rows": 5 } [/block] [block:api-header] { "type": "basic", "title": "Timing Extension Objects" } [/block] The timing standard is designed to be flexible to incorporate additional information if and when it is available. For example in addition to the paratriathlon extension it would be possible to add support for GPS locations though the use of a location object. These additional extensions will be formalised where their usage becomes available and would require updates at periodic intervals. [block:code] { "codes": [ { "code": "<athlete>\n\t<location>\n \t<latitude>51.5032520</latitude>\n \t<longitude>-0.1278990</longitude>\n <elevation>4.69</elevation>\n <speed>45.7<speed>\n </location>\n</athlete>", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Distribution" } [/block] Timing will be distributed by the Triathlon API platform to applications through the [Live REST API](https://developers.triathlon.org/docs/live-api-overview), [Subscriptions API](https://developers.triathlon.org/docs/subscriptions-api-overview) and [Streaming APIs](https://developers.triathlon.org/docs/streaming-api-overview) to all connected applications.