---
updatedAt: 2025-06-25T14:56:45.000Z
agentTools:
  projectIndex: https://developers.triathlon.org/llms.txt
---

# Live Timing Standard v1.1

> ❗️ **Version 2 of Live Timing!**
>
> Version 2 of the Live Timing API is now available.\
> This builds on the documentation below.
> We highly recommend using this to benefit from better validation and error responses. Click [here](https://developers.triathlon.org/page/live-timing-standard-v2) for more details.
>
> The previous version will remain available and you may use this as a fallback in case of any issues with v2.

## Set up and Test

1. The first step is to register for an account and an application here: <Anchor label="Register & Manage Your App" target="_blank" href="https://apps-api.triathlon.org">Register & Manage Your App</Anchor> .
2. Then email us webmaster\[at]triathlon.org to upgrade your application for timing privileges.
3. You can now start sending us messages! See examples and detailed information below.
4. To view the data sent to us, please use our viewer: [https://data.triathlon.org/timing/v2/`{progId}`](https://data.triathlon.org/timing/v2/\{progId}) where progId is the program id.

## Overview

## 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.

**Program ids, event ids and athlete ids?**\
These are the ids we use in our database. A program ID is the equivalent of a race ID in our database.
You can find them here: <https://entries.triathlon.org/event-lookup>

## Example Messages

The following messages only contain 2 athletes for brevity and you should refer to the extended examples below for full timing messages.

```json
{
   "date":"2017-03-04T18:25:11+04:00",
   "start_time":"2017-03-04T15:55:00+04:00",
   "event_id":"107158",
   "event_name":"2017 ITU World Triathlon Abu Dhabi",
   "prog_id":"307158",
   "prog_name":"Elite Men",
   "wetsuit":false,
   "sandbox":false,
   "num_athletes":"2",
   "status":"live",
   "latest":{
      "segment_id":"2",
      "segment_name":"Swim Exit",
      "num_athletes":"1"
   },
   "conditions":{
      "air_temp":"28.8",
      "water_temp":"23.2"
   },
   "athletes":[
      {
         "id":"5695",
         "start_num":"26",
         "name":"Javier Gomez Noya",
         "country":"ESP",
         "segment_id":"18",
         "time":"00:18:37.911",
         "difference":"00:00:00.000",
         "position":"1",
         "status":null,
         "incidents":null,
         "splits":[
            {
               "id":"1",
               "name":"Swim Lap 1",
               "total_time":"00:10:54.799",
               "time":"00:10:54.799",
               "difference":"00:00:11.001",
               "position":"10"
            },
            {
               "id":"2",
               "name":"Swim Exit",
               "total_time":"00:18:37.911",
               "time":"00:07:43.112",
               "difference":"00:00:11.320",
               "position":"14"
            }
         ]
      },
      {
         "id":"18719",
         "start_num":"22",
         "name":"Thomas Bishop",
         "country":"GBR",
         "segment_id":"1",
         "time":"00:10:53.996",
         "difference":"00:00:10.198",
         "position":"2",
         "status":null,
         "incidents":null,
         "splits":[
            {
               "id":"1",
               "name":"Swim Lap 1",
               "total_time":"00:10:53.996",
               "time":"00:10:53.996",
               "difference":"00:00:10.198",
               "position":"9"
            }
         ]
      }
   ]
}
```

> 👍 **Complete Timing Examples**
>
> A full timing example in JSON is available [here](https://gist.githubusercontent.com/garethtdavies/fe58f5085b6e474884b93852a43c8058/raw/ca92c21f64a0fe56cbede113db3826f19c0c9c95/yokohama-ew-official.json).

## Timing Parameters

A breakdown of each parameter is listed below.

| Parameter                   | Example                                 | Description                                                                                                                                                                                                                                                                           | Format  |
| :-------------------------- | :-------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------ |
| date                        | 2017-01-01T13:34:59.123+00:00           | An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) of the time the message was published                                                                                                                                                                            | string  |
| start\_time                 | 2017-01-01T13:34:59.123+00:00           | An [ISO 8601 formatted date](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the start time of the race                                                                                                                                                                      | string  |
| event\_id                   | 123456                                  | The unique event\_id corresponding to the event\_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)                                                                                                                                                    | integer |
| event\_name                 | 2016 ITU World Triathlon Abu Dhabi      | A descriptive name for the event corresponding to the [Events API](https://developers.triathlon.org/docs/events-api-overview)                                                                                                                                                         | string  |
| prog\_id                    | 123456                                  | The unique prog\_id corresponding to the prog\_id in the [Events API](https://developers.triathlon.org/docs/events-api-overview)                                                                                                                                                      | integer |
| prog\_name                  | Elite Men                               | A descriptive name for the race corresponding to the [Events API](https://developers.triathlon.org/docs/events-api-overview)                                                                                                                                                          | string  |
| wetsuit                     | true                                    | Boolean to indicate whether it is a wetsuit swim                                                                                                                                                                                                                                      | boolean |
| sandbox                     | true                                    | Boolean to indicate whether to use the sandbox environment for development (defaults to true)                                                                                                                                                                                         | boolean |
| num\_athletes               | 12                                      | The number of athletes in the race (which must correspond to the number of items in the athletes array)                                                                                                                                                                               | integer |
| status                      | live                                    | 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.                                                | string  |
| **latest**                  |                                         | The latest object contains information regarding the latest timing point data (may be *null* if no timing data)                                                                                                                                                                       | object  |
| latest.segment\_id          | 1                                       | The segment\_id containing the latest result                                                                                                                                                                                                                                          | integer |
| latest.segment\_name        | Swim Exit                               | The segment name containing the latest results                                                                                                                                                                                                                                        | string  |
| latest.num\_athletes        | 12                                      | The number of athletes that have passed through the timing point                                                                                                                                                                                                                      | number  |
| **conditions**              |                                         | An object containing the latest course conditions                                                                                                                                                                                                                                     | object  |
| air\_temp                   | 12.5                                    | The official air temperature in degrees Celsius                                                                                                                                                                                                                                       | float   |
| water\_temp                 | 18.4                                    | The official water temperature in degrees Celsius                                                                                                                                                                                                                                     | float   |
| **athletes**                |                                         | An object containing an array of all athlete objects in the race                                                                                                                                                                                                                      | object  |
| **athletes.athlete**        |                                         | An object containing the timing data for an individual athlete                                                                                                                                                                                                                        | object  |
| athlete.id                  | 123456                                  | The unique athlete\_id corresponding to the athlete\_id in the [Athletes API](https://developers.triathlon.org/docs/athletes-api-overview)                                                                                                                                            | integer |
| athlete.start\_num          | 12                                      | The start number of the athlete                                                                                                                                                                                                                                                       | integer |
| athlete.name                | Alistair Brownlee                       | The name of the athlete                                                                                                                                                                                                                                                               | string  |
| athlete.country             | GBR                                     | The three letter [IOC country code](https://en.wikipedia.org/wiki/List_of_IOC_country_codes)                                                                                                                                                                                          | string  |
| athlete.segment\_id         | 1                                       | The latest (current) segment\_id of the athlete                                                                                                                                                                                                                                       | integer |
| athlete.position            | 12                                      | The position of the athlete (may be *null* if no data) at the latest timing point                                                                                                                                                                                                     | number  |
| athlete.time                | 00:17:16.145                            | An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of the athlete's latest timing point. Provides actual time. For TV or other displays (e.g finish gantry), please round up as soon as crosses 0.001 seconds. See Display Rounding section for more details.       | string  |
| athlete.difference          | 00:01:13.134                            | An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) corresponding to the difference at the latest timing point                                                                                                                                                       | string  |
| athlete.status              | DNF                                     | 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                                                                                                                                          | string  |
| athlete.incidents           | 10 second penalty for bike infringement | 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). | string  |
| **athletes.splits**         |                                         | An array of split objects containing data for each segment completed by the athlete (may be *null* if no data)                                                                                                                                                                        | object  |
| **athletes.splits.segment** |                                         | A segment object containing athlete timing data for each individual segment.                                                                                                                                                                                                          | object  |
| segment.id                  | 3                                       | The segment\_id of the split                                                                                                                                                                                                                                                          | integer |
| segment.name                | Swim Exit                               | The name of the timing segment                                                                                                                                                                                                                                                        | string  |
| segment.time                | 00:08:16.345                            | The time to complete this segment                                                                                                                                                                                                                                                     | string  |
| segment.total\_time         | 00:14:12.345                            | The cumulative time of all segments to this point                                                                                                                                                                                                                                     | string  |
| segment.position            | 12                                      | The position of the athlete at this timing point                                                                                                                                                                                                                                      | integer |
| segment.difference          | 00:01:07.123                            | An [ISO 8601 formatted time](https://en.wikipedia.org/wiki/ISO_8601) of difference of the athlete to the leader at this timing point                                                                                                                                                  | string  |

> 👍 **Sending JSON data**
>
> From 2018 onwards you may only send JSON formatted data and you must include a header of `Content-Type` set to `application/json`.

## 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.

> 🚧 **Default to ordering by start\_num where no further ordering is possible**

## Timing Points

Segment IDs should be named according to the example below.

1. You can add/remove segments based on the timing points you have for a race. If you have more timing points, e.g Swim Lap 2, please provide these
2. **Important: Segment ids should increase sequentially for each segment.**
3. The first timing segment can either be the start or the first swim times.

**Example Standard Distance Race**

| Segment ID | Segment Name |
| :--------- | :----------- |
| 0          | Start        |
| 1          | Swim Lap 1   |
| 2          | Swim Exit    |
| 3          | Transition 1 |
| 4          | Bike Lap 1   |
| 5          | Bike Lap 2   |
| 6          | Bike Lap 3   |
| 7          | Bike Lap 4   |
| 8          | Bike Lap 5   |
| 9          | Bike Lap 6   |
| 10         | Bike Lap 7   |
| 11         | Bike End     |
| 12         | Transition 2 |
| 13         | Run Lap 1    |
| 14         | Run Lap 2    |
| 15         | Run Lap 3    |
| 16         | Finish       |

**Example Sprint Distance Race**

| Segment ID | Segment Name |
| :--------- | :----------- |
| 0          | Start        |
| 1          | Swim Exit    |
| 2          | Transition 1 |
| 3          | Bike Lap 1   |
| 4          | Bike Lap 2   |
| 5          | Bike Lap 3   |
| 6          | Bike End     |
| 7          | Transition 2 |
| 8          | Run Lap 1    |
| 9          | Finish       |

## Timing Delivery

Timing must be sending via a HTTP Post Request.

Timing messages should be delivered as soon as feasible. Data messages should be sent as soon as an athlete crosses a timing point or when an external event occurs (such as the race start or a penalty is awarded). 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 does not exceed one push every 1000ms. If POSTing data, **messages should only be pushed when there is a change of information in the message**. If that is not possible, messages can be sent every 2 to 3 seconds.

Messages should be sent with a `Content-Type` of `application/json`.

### 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**. This API key may also be used to access all other public endpoints of the API such as start lists.

### 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.

## Timing Implementation

* 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.

## Other Timing Notes

* 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`.

## Display rounding

For TV, finish gantry or other displays where the milliseconds component of time does not need to be shown, please display times with the raw millisecond data rounded up to the next full second.

For example:\
00:09:14.000 -> 00:09:14
00:09:14.001 -> 00:09:15
00:09:14.500 -> 00:09:15
00:09:14.999 -> 00:09:15
00:09:15.000 -> 00:09:15

## Standard Incident Guidelines

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.

In the event where there are multiple incidents for an athlete in an individual program, multiple incidents should be included and delimited by a comma.

## Mixed Relay Timing

Mixed Relay timing follows a very similar syntax as individual timing with an additional layer of information which comprises team member data. As with the individual data, all athletes and teams should be included in all timing messages.

The following example shows a curtailed response of a single team with, in this example, the second athlete on the team to have exited the swim portion of the race.

For the segment/split naming you can use prepend Leg \{x} where x is the leg raced (from 1 to 4 typically).

```json
{
   "date":"2017-06-11T17:03:12+0000",
   "start_time":"2017-06-11T14:39:00+0000",
   "event_id":"107161",
   "event_name":"2017 ITU World Triathlon Hamburg",
   "prog_id":"307248",
   "prog_name":"Elite Mixed Relay",
   "wetsuit":true,
   "sandbox":false,
   "num_teams":1,
   "status":"live",
   "latest":{
      "segment_id":"8",
      "segment_name":"Leg 2 Swim Finish",
      "num_teams":1
   },
   "conditions":{
      "air_temp":"17.1",
      "water_temp":"16.6"
   },
   "teams":[
      {
         "id":"1234",
         "start_num":"1",
         "name":"Team GBR I",
         "country":"GBR",
         "segment_id":"8",
         "time":"00:49:51.000",
         "difference":"00:00:00.000",
         "position":1,
         "status":null,
         "incidents":null,
         "athletes":[
            {
               "id":"9876",
               "team_order":"1",
               "name":"Non Stanford",
               "country":"GBR",
               "splits":[
                  {
                     "id":1,
                     "name":"Leg 1 Swim Exit",
                     "total_time":"00:16:38.000",
                     "time":"00:08:20.000",
                     "difference":"00:00:05.000",
                     "position":7
                  },
                  {
                     "id":2,
                     "name":"Leg 1 Bike Start",
                     "total_time":"00:17:41.000",
                     "time":"00:01:04.000",
                     "difference":"00:00:02.000",
                     "position":4
                  },
                  {
                     "id":3,
                     "name":"Leg 1 Bike Lap 1 Start",
                     "total_time":"00:35:05.000",
                     "time":"00:17:24.000",
                     "difference":"00:00:00.000",
                     "position":1
                  },
                  {
                     "id":4,
                     "name":"Leg 1 Bike Finish",
                     "total_time":"01:15:04.000",
                     "time":"00:05:55.000",
                     "difference":"00:00:00.000",
                     "position":2
                  },
                  {
                     "id":5,
                     "name":"Leg 1 Run Lap 1 Start",
                     "total_time":"01:15:28.000",
                     "time":"00:25.000",
                     "difference":"00:00:00.000",
                     "position":2
                  },
                  {
                     "id":6,
                     "name":"Leg 1 Run Lap 1 Finish",
                     "total_time":"01:22:58.000",
                     "time":"00:07:31.000",
                     "difference":"00:00:00.000",
                     "position":1
                  },
                  {
                     "id":7,
                     "name":"Leg 1 Finish",
                     "total_time":"01:46:51.000",
                     "time":"00:08:10.000",
                     "difference":"00:00:00.000",
                     "position":1
                  }
               ]
            },
            {
               "id":"7788",
               "team_order":"2",
               "name":"Alistair Brownlee",
               "country":"GBR",
               "splits":[
                  {
                     "id":8,
                     "name":"Leg 2 Swim Exit",
                     "total_time":"00:16:38.000",
                     "time":"00:08:20.000",
                     "difference":"00:00:00.000",
                     "position":1
                  }
               ]
            },
            {
               "id":"5586",
               "team_order":"3",
               "name":"Vicky Holland",
               "country":"GBR",
               "splits": null
            },
            {
               "id":"11378",
               "team_order":"4",
               "name":"Jonathan Brownlee",
               "country":"GBR",
               "splits": null
            }
         ]
      }
   ]
}
```

**Mixed Relay Notes**

* `segment_ids` should be consecutive and unique being indexed from 1 i.e. Leg 1 Swim Finish and Leg 2 Swim Finish are unique `segment_ids`.
* Timing point names should follow the suggested format as indicated [here](https://developers.triathlon.org/v1/page/live-timing-standard-v11#timing-points) but prefixed with the corresponding leg number i.e. Leg 3 Swim Exit
* In the `latest` block `num_teams` is used as opposed to `num_athletes`
* As with individual races messages, all teams and all athletes should be included in every message. If the athlete has not yet competed their splits value will be `null`

## Paratriathlon

Where applicable a Paratriathlon object should be included within each athlete object to specify additional Paratriathlon-specific information such as guide names and additional meta information.

```json
{  
    "athlete_id": "123456",
    .....
  	"paratriathlon":{  
      "class":"PTWC1",
      "guide_name":"Guide Name",
      "guide_id":"654321",
      "compensation_time":"00:03:46"
   }
}
```

A breakdown of each parameter is listed below:

| Parameter                 | Example      | Description                                                                                                                      | Format  |
| :------------------------ | :----------- | :------------------------------------------------------------------------------------------------------------------------------- | :------ |
| **paratriathlon**         |              | The paratriathlon object contains specific information regarding the paratriathlete and is only present for Paratriathlon events | object  |
| paratriathlon.class       | PTWC1        | Indicates the Paratriathlon class as multiple classes may compete in a single program                                            | string  |
| paratriathlon.guide\_name | Athlete Name | The name of the paratriathlon guide for visual impairment categories                                                             | string  |
| paratriathlon.guide\_id   | 123456       | The unique athlete\_id corresponding to the athlete\_id in the Athletes API                                                      | integer |
| compensation\_time        | 00:00:30     | An ISO 8601 formatted time of the start time offset. May be set to `null` if not applicable.                                     | string  |

## Distribution

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.