The API hews as closely as possible to the REST architectural style. The API is organized around a set of resources
that populate the world of endurance racing, like events, races, race entries, etc. With the API, your application can perform operations on these resources through the HTTP protocol. You can use the documentation below to learn about the API. In particular, you can test out API calls right here on this page to see exactly how API calls work and how to incorporate them into your application.
A resource
is some object of interest targeted by the API. In the world of endurance racing this includes events, races, athletes, timing devices, and others. We'll refer to a specific resource sometimes as a resource entity
to distinguish that specific entity from all entities of that resource type
. A resource collection
is a number of resource entities of the same type.
The ChronoTrack Live Open Platform API is comprised of operations
on these resources. All operations are executed by sending HTTP requests to one of our API endpoints. An API endpoint
is a URI to which a API request is directed.
All API requests should be sent to one of the following two endpoints:
Endpoint Type | Endpoint URL |
---|---|
Production | https://api.chronotrack.com/api |
Testing | https://qa-api.chronotrack.com/api |
The production endpoint should only be used in live, production code and never for testing. The production endpoint is backed by the ChronoTrack Live production database, which means all changes to data via the production API will be immediately visible to ChronoTrack Live users.
The testing endpoint is backed by a separate testing database that is refreshed every night with a copy of the production database. This means any API activity that changes data via the testing endpoint will have those changes disappear the next day. Please note the QA environment is not 100% guaranteed up at all times as it is a test environment.
https
(TLS/SSL) protocol. Any requests sent via the non-secure http
protocol will be redirected to the secure endpoint. All requests to our production API must be through the secure HTTPS protocol. Any requests that come in on a non-secure port will be redirected to our TLS/SSL secured service.
All requests must also be authenticated. First, a request must originate from an application that is registered and approved by ChronoTrack. Second, the application must authenticate the ChronoTrack Live user on whose behalf it is making requests to our system.
We support four authentication methods, each suited for a different kind of application environment. For applications that have easy access to the user's browser, like a web or mobile application, we support the OAuth 2.0 Web Flow. For applications without browser access, like native desktop/laptop applications, we provide two alternatives. If the environment your application operates in has the capacity to securely store your users' ChronoTrack Live account credentials, then you can use HTTP Basic authentication. If you can't, or prefer not to, locally store your users' credentials, we support the OAuth 2.0 Password Flow.
Finally, for certain testing environments where data security requirements are minimal, we support a simple authentication scheme where you can pass a user id and password as parameters to the API call. All our methods are described in detail below.
Web applications can acquire an OAuth2 access token for a ChronoTrack Live user by following these steps:
Obtain a ChronoTrack Live developer account here. Creating a developer account will also register your client application.
Your application will be assigned a client_id
and a client_secret
. The client_id is public information, but you should take care to safeguard your client_secret. During the process of registering your application with us, you will be asked to provide a redirect_uri
, that is, a URL within your web application where users will be redirected after granting your application permission to access their ChronoTrack Live resources. An example redirect_uri is:
https://mywebapp.com/oauth2
When the user first invokes a function in your application requiring access to their ChronoTrack Live resources, you should redirect the user to our authorization end-point:
GET /oauth2/authorize?response_type=code
Authorization
header to this request using your client_id
and client_secret
as the username and password. This is required to verify the authorization request is coming from your application. See the specific instructions in the Authorization
header.This will redirect your user to our authentication service. They will have to login as they normally would to ChronoTrack Live. They then will be presented with a screen that allows them to grant your application permission to access their ChronoTrack Live resources.
Upon authorizing your application, the user will be redirected back to your application's specified redirect_uri:
https://mywebapp.com/oauth2?code=bef10603874b
The code
parameter appended to your redirect uri is a short-lived (10 minutes), single-use authorization code that your application can convert into a longer-lived access token.
To obtain an access token
, your application should make a GET API call to our token endpoint:
GET /oauth2/token?grant_type=authorization_code&code=bef10603874b
passing in the code parameter returned to your application in the last step and making sure to add an Authorization
header that provides Basic HTTP authentication for your client app (using your client_id
as the username and your client_secret
as the password).
This API token endpoint will return a json formatted object containing an OAuth 2.0 access token that allows your application to access the user's ChronoTrack Live resources for a lengthy period of time (usually 72 hours).
{ "access_token": "2YotnFZFEjr1zCsicMWpAA", "token_type": "Bearer", "expires": "1343309220", "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA" }
You also will receive a refresh token
that you can send to our token endpoint to receive another access token, good for another 72 hours of use. The refresh token is valid for one year or until the user revokes your application's access to their resources.
You send a refresh token request like this:
GET /oauth2/token?grant_type=refresh_token&refresh_token=597262138b23
making sure to again provide Basic HTTP authentication for your client app (using your client_id as the username and your client_secret as the password). This will send you another access token that you can use for another 72 hours. It will also return a new refresh token that you can use to extend your access.
Finally, with a fresh access token, you can make API requests, like getting a list of events the user has access to:
GET /api/event
making sure to pass in an Authorization
header with the access token like so:
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
For applications where the OAuth2 Web Flow cannot be used (for example, native applications without a browser layer), an OAuth access token can be acquired by making a single call to our token endpoint and passing the end-user’s ChronoTrack Live account credentials as the username
and password
parameters with a grant_type
of password
.
GET /oauth2/token?grant_type=password&username=joesmith%40someplace.com&password=some_password
Authorization
header using HTTP Basic Auth where the username is your client_id
and the password is your client_secret
. Follow the instructions under the "HTTP Basic Auth" tab for how to construct this header. This method involves passing in the resource owner's ChronoTrack Live account username and password directly, according to the HTTP Basic Authentication protocol. You simply construct an Authorization
header as follows:
zooba:tooba
.em9vYmE6dG9vYmE=
.Authorization: Basic em9vYmE6dG9vYmE=
WARNING! This method can be less secure than using one of the OAuth2 methods, and as such we do not recommend you use it. However, we still provide support for this authentication method because some applications may find it simpler to use.
There are two risks in using this method. The first risk lies in sending a request over a non-TLS/SSL connection. While we automatically redirect all non-secure requests to our TLS/SSL port, an initial non-secure request risks exposing your user's ChronoTrack Live account credentials to anyone sophisticated enough to be sniffing network packets, allowing man-in-the-middle attacks. This risk can be completely mitigated by sending all requests over TLS/SSL.
A second risk is that your application has to ask for and store the user's ChronoTrack Live credentials. You then become responsible for safeguarding their password and making sure it is not exposed via an insecure storage medium, which adds complexity to your application security aparatus. The only way to mitigate this risk is to not use this method and instead use one of the OAuth2 methods.
In certain situations, like when using our docs here to test the API, security requirements are minimal and using oauth or basic authentication is infeasible. For these special cases we support a simple method of passing in the ChronoTrack Live resource owner credentials via parameters. For instance, if you have a test account for a resource owner called test-user@myorg.com
with password 12345
, then you could make authenticated requests to our API on behalf of that test user:
GET /api/event?client_id=abcdefgh&user_id=test-user%40myorg.com&user_pass=12345
To prevent exposing the password, you should SHA1-encode the password:
GET /api/event?client_id=abcdefgh&user_id=test-user%40myorg.com&user_pass=8cb2237d0679ca88db6464eac60da96345513964
The following table describes the formats used for the content of API requests and responses. The first column contains a short format code
for each format, while the second column contains the standard Internet Assigned Numbers Authority MIME type for the format.
Format Code | MIME Type | Description |
---|---|---|
json | application/json | Javascript Object Notation. See http://www.json.org/ for details. |
xml | application/xml | Extensible Markup Language. See http://www.w3.org/XML/ for details. |
yaml | application/yaml | Yet Another Markup Language. See http://www.yaml.org/ for details. |
csv | text/csv | Comma Separated Values. A tabular plain-text format. Columns within each row are delimited by a comma character (","). Columns that contain literal commas are escaped by double quotes. Rows are delimited by a carriage-return/line-feed ("\r\n") sequence. See http://tools.ietf.org/html/rfc4180 for more details. |
tsv | text/tab-delimited-values | Tab Separated Values. A tabular plain-text format. Columns within each row are delimited by a tab character ("\t"). Rows are delimited by a carriage-return/line-feed ("\r\n") sequence. See http://www.iana.org/assignments/media-types/text/tab-separated-values for more details. |
API requests to our servers are just standard HTTP requests. As with all HTTP requests, a request to our API always contains a method which denotes the operation to be done, always has a URL (specifying the resource to operate on), usually has some parameters you send to qualify your request, and sometimes those parameters are specified in the URL itself, sometimes in the request headers and sometimes in the request body (formatted as JSON, XML, or CSV). We'll look at each of these request components in this section.
HTTP Method | Example Requests |
---|---|
GET |
This method is used to retrieve either a list of resource entities or a single resource entity.
|
PUT |
This method is used to update a single existing resource entity.
|
POST |
This method is used to create or update one or more resource entities.
|
DELETE |
This method is used to delete an existing resource entity.
|
The URL path specifies the resource or resource collection the request operates on.
/api/{resource-name}.{format}/{resource-id}/{sub-resource-name}?{url-params}
URL Component | Required | Meaning |
---|---|---|
/api/ | Yes | All API request URLs begin with this prefix. |
resource-name | Yes | All API request URLs must contain the name of the resource type to operate on. |
format | No | The format of the response that you prefer. May be one of format codes specified in the formats section. |
resource-id | No | The identifier for a specific resource. If you are interested in getting or setting the properties of a specific resource or getting a collection of sub-resources belonging to a specific resource, you must specify this URL component in your request to identify the resource. |
sub-resource-name | No | For requests where you want the collection of resources that belong to a specific resource (like all the entries in a given event, for instance), you use this URL component to name the type of sub-resource you want. |
url-params | No | Ampersand (&) separated list of request parameters, URL-encoded as per RFC 1738. |
Most API requests will have one or more parameters that define some context for the request. For instance, all requests must specify the client_id
parameter, which identifies the application the request originates from. The request parameters may be specified in several different places, including the URL path, the URL query, the request header and the request body. We'll consider each in turn.
Two optional, but significant, parameters are commonly specified in the path of a URL request. First, the resource_id
of the resource being operated on. Second, the desired format
of the response. The following example illustrates the use of both of the parameters to request a particular event's properties in xml format:
GET /api/event.xml/123
The query portion of a URL is the list of parameters that comes after the question mark following the URL path. If more than one parameter is specified, it must be separated from the others by an ampersand (&). The following URL requests the details for event 123 in xml format for the client application with id abcdef
:
GET /api/event.xml/123?client_id=abcdef
Instead of specifying the format of the request in the URL path, you could instead specify it as a query parameter:
GET /api/event/123?client_id=abcdef&format=xml
Request headers can also be used to specify context for a request. The following table provides a list of headers you can use with API requests.
Header | Meaning |
---|---|
Accept | This is an alternative to specifying the desired format of the response in the URL path or query. The value should be set to one of the MIME types specified in the formats section. Defaults to application/json. |
Accept-Encoding | If you have the capacity to uncompress gzipped or deflated content, set this header to either "gzip" or "default" to trigger automatic compression of the response content to save network bandwidth. |
Accept-Language | The languages you'd prefer the response to be sent back using. See RFC 1766 for more details. |
Authorization | Authorization for the request. The value here depends on what kind of authorization method you are using. See the security section for details on the setting. |
X-Http-Method-Override | Specify this header to override the value of the HTTP method for a request. This should only be used if your application wants to submit a PUT or DELETE request but your HTTP library only supports GET and POST. You can tell your library to use the POST method (instead of PUT) or the GET method (instead of DELETE) and set then this header to PUT or DELETE. |
Content-Type | The MIME type of the content body of your request. Must be set to one of the MIME types listed in the formats section. Defaults to application/json. |
Content-Length | The size (in bytes, not characters) of the request body. Usually this will be set by your HTTP library and does not need to be set manually. |
Date | The RFC 822 date-time on the client when the request is sent. This should be set by your HTTP library. |
Method | Expected Content |
---|---|
GET | No content sent with request. |
POST | One or more properly encoded entities containing the fields of each new resource to create or existing resource to update. In the case of updating resources, you must provide either the resource id or some other defined identifier to allow our server to find the existing resource. |
PUT | A properly encoded (possibly partial) entity containing the data items of the specified resource to be updated. You only need to provide those data items that require updating. The id of the resource being updated is specified as part of the URL path of the request. |
DELETE | No content sent with request. |
Content-Type
header appropriately so our API server can decode it.
The following table enumerates some commonly used request parameters and where they are usually included in the request.
Parameter | Placement | Comment |
---|---|---|
format | Path, Query | |
client_id | Query | |
page | Query | |
last_id | Query | |
modified_after | Query | |
modified_before | Query | |
columns | Query | |
user_id | Query | |
user_pass | Query |
When 1500 concurrent connections, from the same IP address, are reached within a 60 second time frame, the user will be blacklisted for the remaining duration of that time frame and will receive the 503 over rate error.
An API response from our servers has several salient characteristics worth drawing attention to. First, each response has a numeric HTTP code that indicates success or failure. Second, a response usually contains a body formatted as JSON, XML, or CSV that contains the data you requested. Third, for many requests that return multiple entities (like a list of all events your user has access to, for instance), there are headers in the response that contain useful information on the size of the total result set and what portion of that total result set the current body of the request contains. We'll elaborate on each of these in turn.
Code | Meaning |
---|---|
Success | |
200 | Success With Content. The request succeeded and content was returned. The content of the response body depends on the type of request. A GET on a single resource will return the entity corresponding to that resource. A GET on a resource collection will return one or more entities. A POST will return a data structure for each requested entity indicating either that the resource was created or updated. The responses will correspond one for one with the order of entities in the request. |
202 | Accepted. The request has been accepted for processing, but the processing has not been completed. The response to the initial request provides a url that can be used to get further information about the status of processing. This allows our server to accept a request that might take some time to complete without requiring your connection persist until that process is done. |
Client Errors | |
400 | Bad Request. The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. Details of the error are provided in the body of the response. |
401 | Unauthenticated. The request requires authentication (of the ChronoTrack Live user) and either the credentials provided are not a match, or no credentials were provided. Details of the error are provided in the body of the response. |
403 | Forbidden. The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. More details are in the body of the response. Usually this is caused by going over usage limits for a request type by an application. |
404 | Not Found. The server could not find any resources requested by the client. |
Server Errors | |
500 | Internal Server Error. The server encountered an unexpected condition which prevented it from fulfilling the request. |
501 | Not Implemented. The server does not support the functionality required to fulfill the request. |
503 |
Server Unavailable. The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay may be indicated in a Retry-After header. If no Retry-After is given, the client should handle the response as it would for a 500 response. |
503 over rate | This 'IP', 'IP range' or 'email address' has been blacklisted, please contact esupport@chronotrack.com or call (812) 759-7877 to work with our support staff to resolve this issue. |
For responses that return content (basically all responses except PUT and DELETE) the format of the response body can be set to one of several alternatives.
You may specify the response format you want in one of two ways. First, you can add an Accept
header to your request with the appropriate MIME type for your preferred format. Second, you can add an extension to the resource name in the URL (for example, to request a list of all accessible events in XML format, you could use GET /api/event.xml
. If neither of these methods is used, the response format defaults to JSON. The proper extension is just the lower-case form of the name in the table above.
Header | Meaning |
---|---|
Standard HTTP Headers | |
Content-Type | The MIME type of the response body. |
Content-Length | The size (in bytes, not characters) of the response body. |
Content-Encoding | If the request indicates it can accept compression via the Accept-Encoding header, our API server will compress the response body to save network bandwidth. In this case, the Content-Encoding response header contains the compression method used, either "gzip" (see RFC 1952) or "deflate" (see RFC 1951) depending on which algorithm was requested. |
Transfer-Encoding | If set, it will be set to "chunked". The chunked encoding modifies the response body in order to transfer it as a series of chunks, each with its own size indicator, followed by an optional trailer containing entity-header fields. This allows dynamically produced content to be transferred along with the information necessary for the recipient to verify that it has received the full message. |
Content-Language | The language used in the response represented as in RFC 1766 using ISO-639 language abbreviations and, optionally, ISO-3166 country codes to construct the language-tag. |
Date | The date and time on the server when the response was sent. This is in RFC 822 date-time format, for example: "Tue, 04 Dec 2012 05:44:04 GMT." |
WWW-Authenticate | The WWW-Authenticate response header field is included only in 401 (Unauthorized) response messages. The field value consists of at least one challenge that indicates the authentication scheme and parameters applicable to the request URI. For more details see RFC 2617. |
Link | For resource collection requests, provides a list of links to first, last, previous and next pages for use in pagination interfaces in the client application. This various relation types (first, prev, next, last) are defined in RFC 5988. |
Custom ChronoTrack Live Headers | |
X-Ctlive-Api-Version | Provides the current version number of the API. |
X-Ctlive-Row-Count | For resource collection requests, provides the total number of entities in the collection (of which only a portion may be returned in the current response). |
X-Ctlive-Current-Rows | For resource collection requests, provides the current range of rows contained in the response body in the format min-max (so on page 1 of a response with a page size of 10, this header's value would be "1-10", page 2 would be "11-20", and so on). |
X-Ctlive-Page-Count | For resource collection requests, provides the total number of pages, given the current page size. |
X-Ctlive-Page-Size | For resource collection requests, provides the number of entities returned in a single "page" or results. |
X-Ctlive-Current-Page | For resource collection requests, provides the current page of results within the total number of pages contained in the collection, given the page size setting. |
We use UTF-8 encoding through and through to guarantee proper encoding of all international character sets. All data you send to an API endpoint is assumed to be, and therefore must be, encoded in UTF-8. All data transmitted from an API endpoint is encoded in UTF-8.
The API uses a pretty standard collection of types for all data that it processes, as described below.
Type | Description |
---|---|
resource_id | A non-semantic (numeric) identifier associated with a particular resource. This identifier is guaranteed to be unique within the collection of all resources of that resource type. Resource identifiers are assigned by ChronoTrack Live and will not change over the life cycle of a resource. Resources may also have one or more semantically significant identifiers assigned by event and timer related organizations. |
string | A UTF-8 encoded character string without any line breaks, and rarely longer than 250 characters. |
text | A UTF-8 encoded character string that may contain line breaks and is likely to be longer than 250 characters. |
boolean | May take either the value 0, meaning false, or 1, meaning true. |
integer | An integral number (a number without any fractional part). |
float | A floating point number (a number that may have a fractional part). |
enum | Several data items in the API may take on a value drawn from a small enumeration of possible strings. All enumerated values are represented as strings. |
date | Dates (without a time) are represented in ISO-8601 standard format, namely YYYY-MM-DD. |
epoch_time | Datetimes are represented as unix epoch times, namely the number of seconds since midnight January 1, 1970 UTC. Information on how to convert unix epoch times to other date/time formats can be found at http://epochconverter.com. |