RTRT.me - Real Time Race Tracking

Real-Time Race Tracking for World-Class Events

Admin API Reference ( Updated 2023-07-10 ) CHANGELOG
  • 2023-07-10
    - Managing Events > Profiles > Add or Update: Introduced 'nocreate' parameter to prevent roster creation.
  • 2022-04-08
    - Added explaination of how to clear a value in a field that is already set.
  • 2020-10-11
    - Added import_key_field and import_key_val to response object for easier reference when uploading/updating profiles.
  • 2019-4-1
    - Managing Events > Profiles: Added clarification between Listing profiles vs Add/Update.
  • 2018-12-31
    - Access > Calls to /admin/events/profiles/mapping: Removed unnecessary 'standards' section.
  • 2018-12-17
    - Access > Calls to /admin/events that do not perform admin functions will now pass through to the Web API /events namespace.
  • 2018-05-14
    - Access > Use domain 'admin-api.rtrt.me' for admin requests.
  • 2014-09-08
    - Managing Events > Profiles > Add or Update: List can now be sent as JSON content type.
  • 2013-11-12
    - Managing Events > Profiles > Add or Update: Changed default behavoir to always 'extend' roster ( excluded fields are not removed unless forced by 'extend=0' ).

The RTRT.me Admin API allows developers to manage event data and perform other tasks via a private, secure JSON+REST interface.

Access

Your Admin appid and token can be found in the RTRT.me Web Console in your Account page under Preferences->ADMIN API CREDENTIALS.

Provide your appid and token in the querystring of the URL. When accessing the API, only HTTPS requests will be accepted.

https://admin-api.rtrt.me?appid=[YOUR ADMIN APP ID]&token=[YOUR TOKEN]

IMPORTANT: THE APPID AND TOKEN FROM YOUR ACCOUNT ARE YOUR PERSONAL CREDENTAILS AND SHOULD BE PROTECTED IN THE SAME MANNER AS YOU PROTECT YOUR PASSWORDS. THE ADMIN API AT admin-api.rtrt.me AND YOUR CREDENTIALS ARE FOR YOUR PERSONAL INTERNAL USE ONLY. THE ADMIN API AND CREDENTIALS MUST NEVER BE SAVED AND PACKAGED IN ANY DISTRIBUTED APPLICATIONS OR USED IN ANY IMPLEMENTATIONS WHERE URLS, APPID OR TOKEN COULD BE EXPOSED OR CAPTURED SUCH AS A SHARED WEB OR MOBILE APP.

WARNING: PLEASE DO NOT SHARE OR SEND YOUR APPID AND TOKEN OVER A NON-SECURE METHOD OF COMMUNICATION. EMAILS ARE NOT SECURE!

Tokens remain available and do not expire unless reset by you via the Account Preferences page.

Your Admin credentials and admin-api.rtrt.me may also be used to perform requests on the /events namespace as documented in the Web API. Since admin credentials are still used, the response may contain more information than is avialable in the public rest interface.

Calls to /admin/events that are not admin operations will pass through to /events in the Web API and the 'info' section will include the following 'note'.

note: "Returning results for /path/requested from the Web API but with elevated permissions. See https://rtrt.me/docs/api/rest."

Managing Events

You can perform a number of tasks on your events by requesting a URL in the '/admin' API path while and passing various options.

Below is a list of currently available requests.

Profiles - Listing https://rtrt.me/docs/api/admin#profiles-listing

/admin/events/[EVENT SYSTEM NAME]/profiles

Make the '/profiles' call on your event (without passing a list parameter) to retreive profiles as documented in the Web API, but with admin credentials. Your admin credentials will allow you to view internal fields and hidden participants.

Profiles - Add or Update https://rtrt.me/docs/api/admin#profiles-addupdate

/admin/events/[EVENT SYSTEM NAME]/profiles?list=[submit participants as JSON]

Make the '/profiles' call on your event while passing a list parameter to add, update or delete participants in the roster. The list parameter should consist of one or more roster records (participants) represeted as a JSON string. For example:

list=[{ "reg_id" :'406279',"fname": "Thomas","lname": "Holloway","birthdate": "1944-07-12","city": "Torrington","country": "USA","race": "Half Marathon","sex": "M","state": "NY","tag": "1331"}]

NOTE: The field names passed to this call will be translated to our standards a explained in Profile Fields. Also see Profile Mapping below.

If the profile is new, it will be created. If the profile exists, it will be updated.

NOTE: By default, any records with unknown unique ids will create new roster entries. To prevent the API from creating new roster entries for unknown ids, pass 'nocreate=1' as a parameter in GET or POST.

You can send the list parameter as JSON (application/json), a form POST (application/x-www-form-urlencoded), or a GET. If you use GET, you must properly URL Encode the JSON object. Make sure to set charset=UTF-8.

Sample using curl and JSON:

curl \
  --header "Content-type: application/json; charset=UTF-8" \
  --request POST \
  --data '{ "list":[{ "reg_id" :'406279',"fname": "Thomas","lname": "Holloway","birthdate": "1944-07-12","city": "Torrington","country": "USA","race": "Half Marathon","sex": "M","state": "NY","tag": "1331"}]}' \
  'https://admin-api.rtrt.me/admin/events/EVENTDEMO/profiles?appid=51003740aad3e3d63ca5a7b1&token=96b411a6418132f3dd6179d7897af9e9'

Sample using curl and -F to send list as POST:

curl -F 'list=[{ "reg_id" :"406279","fname": "Thomas","lname": "Holloway","birthdate": "1944-07-12","city": "Torrington","country": "USA","race": "Half Marathon","sex": "M","state": "NY","tag": "1331"}]' \
     'https://admin-api.rtrt.me/admin/events/EVENTDEMO/profiles?appid=51003740aad3e3d63ca5a7b1&token=96b411a6418132f3dd6179d7897af9e9'

Same example as a GET request (list object is URL Encoded):

https://admin-api.rtrt.me/admin/events/EVENTDEMO/profiles?appid=51003740aad3e3d63ca5a7b1&token=96b411a6418132f3dd6179d7897af9e9&list=%5B%7B%20%22reg_id%22%20%3A%22406279%22%2C%22fname%22%3A%20%22Thomas%22%2C%22lname%22%3A%20%22Holloway%22%2C%22birthdate%22%3A%20%221944-07-12%22%2C%22city%22%3A%20%22Torrington%22%2C%22country%22%3A%20%22USA%22%2C%22race%22%3A%20%22Half%20Marathon%22%2C%22sex%22%3A%20%22M%22%2C%22state%22%3A%20%22NY%22%2C%22tag%22%3A%20%221331%22%7D%5D

If successful, the response will return with a 'success' object and the 'info' section will include 'stats' and 'records_affected'. For example:

{

    "success": {
        "type": "ok",
        "msg": "Successfully completed your request."
    },
    "info": {
        "stats": {
            "processed": "2",
            "inserts": "0",
            "skipped": "0",
            "duplicates": "0",
            "unchanged": "1",
            "updates": "1",
            "reclaimed": "2",
            "removed": "0"
        },
        "records_affected": [
            {
                "key_field": "pid",
                "key_val": "R7W6UNSE",
                "import_key_field": "reg_id",
                "import_key_val": "5342344",
                "version": "3",
                "status": {
                    "success": {
                        "type": "updated",
                        "msg": "Profile Updated. PID reclaimed using pid eq R7W6UNSE."
                    }
                },
                "updated": {
                    "fname": "Tom",
                    "birthdate": "1944-07-14",
                    "name": "Tom Holloway"
                }
            },
            {
                "key_field": "pid",
                "key_val": "RSF56NBR",
                "import_key_field": "reg_id",
                "import_key_val": "5332342",
                "version": "20",
                "status": {
                    "success": {
                        "type": "unchanged",
                        "msg": "No Changes. PID reclaimed using pid eq RSF56NBR."
                    }
                }
            }
        ]
    }

}

Number of records in this request that were:

processed = valid records (rows)
inserts = newly created
skipped = ignored, failed because of some issue with a row
duplicates = detected to be identical (or nearly identical)
unchanged = not changed
updates = updated ( one or more fields )
reclaimed = imported previously and would receive an 'update' rather than 'insert' a new record. Reclaimed is good to see on subsequent imports because this means that profile tracking will continue to be linked up to original record as subcribed to
removed = deleted during in this request
What do the stats mean?

For each record in the batch, we return an object in the 'records_affected' in the order submitted in your request. This object includes:

 
'key_field' - This will be always be 'pid', the RTRT internal unique identifier
'key_val' - RTRT.me roster PID (Participant ID) value
'import_key_field' - Your supplied unique key field as used for import (e.g. "reg_id")
'import_key_val' - The unique key value you supplied
'version' - Version number of the record.  When first inserted, is '1'.  
            Upon each change to the record, this advances by 1.
'status' - Conventional 'success' or 'error' objects with type and msg. 

    Possible values for 'status.success.type' include: 
      'inserted', 'updated', 'conflicted', 'unchanged'
        
        If success.type is 'updated', the response will tell you what fields got changed 
        in the 'updated' object.
          
        If success.type is 'conflicted', the response will tell you what fields (if any) 
        got changed in the 'updated' object, and also which fields were not changed in 
        the 'locked' object.

    Possible values for 'status.error.type' include: 
      'skipped'
          

NOTE: By default, profiles fields passed are updated and fields that are excluded are not removed. To force removal fields not included, pass 'extend=0' as a parameter in GET or POST.

If not successful, the response will return with a 'error' object and a 'msg' explaining why the failure has occured. For example:

{
   "error":{
      "type":"failed",
      "msg":"No Changes were made. Sorry, Import failed. Could not find value for key field of (reg_id). Make sure Import Key Field is set properly in Event Settings->Roster Options. and make sure you have unique values populated in that field."
   },
   "info":{
      "cacheVer":"0~6"
   }
}

To handle more than one record at a time, add more than one to the list object.

list=[{ "reg_id" :"406279",... all fields for participant },{ "reg_id" :'3235125',... all fields for participant }]

Example: Add/Update 2 Demo Participants: /admin/events/EVENTDEMO/profiles?list=%5B%7B%20%22reg_id%22%20%3A%22406279%22...

NOTE: To unset and clear a value from a specific field, set the value to the string "_field_removed".

list=[{ "reg_id" :'406279',"tag": "_field_removed"}]

Profiles - Remove https://rtrt.me/docs/api/admin#profiles-removing

To remove (delete) a profile from your event, make the '/profiles' request, and include an extra field of "delete_record" with a value of "1" to the participant rows which you want to have removed. For example:

list=[{ "reg_id" :'406279',"fname": "Thomas","lname": "Holloway","birthdate": "1944-07-12","city": "Torrington","country": "USA","race": "Half Marathon","sex": "M","state": "NY","tag": "1331", "delete_record": "1"}]

If the profile is matched (reclaimed), it will be deleted. If the profile was not found, it will be skipped.

Example: Delete a Demo Participant: /admin/events/EVENTDEMO/profiles?list=%5B%7B%20%22reg_id%22%20%3A%22406279%22...

Profiles - Field Mapping https://rtrt.me/docs/api/admin#profiles-mapping

Sometimes it is useful to know what field translation will occur based on RTRT.me import standards ( see profile fields ). The following request accepts a list of fields and responds with the standardized RTRT field names that would be used on an import.

/admin/events/[EVENT SYSTEM NAME]/profiles/mapping

Make the '/profiles/mapping' call on your event while passing a GET (querystring) parameter of fields. The fields parameter should consist of one or more roster field names (sometimes called headings or keys) in a comma separated list. For example:

&fields=UserID,Bib,Chip,FirstName,LastName,Gender,Age,BirthDate,City,State,Country,TeamCode,TeamName

Example: Get Field Mapping: /admin/events/EVENTDEMO/profiles/mapping?fields=UserID,Bib,Chip,FirstName,LastName,Gender,Age,BirthDate,City,State,Country,TeamCode,TeamName

If successful, the response will return a 'list' object with original field to RTRT field mapping. For example:

{

    "list": {
        "UserID": "reg_id",
        "Bib": "bib",
        "Tag": "tag",
        "FirstName": "fname",
        "LastName": "lname",
        "Gender": "sex",
        "Age": "age",
        "BirthDate": "birthdate",
        "City": "city",
        "State": "state",
        "Country": "country",
        "TeamCode": "teamcode",
        "TeamName": "teamname"
    },
    "info": {
        "cacheVer": "14~2069"
    }
}

If successful, the response will return with a 'success' object and the 'info' section will include 'stats' and 'records_affected'. For example:

{

    "success": {
        "type": "ok",
        "msg": "Successfully completed your request."
    },
    "info": {
        "records_affected": [
            {
                "id": "MT3UV6WPDAT9", // unique id assigned to this manual time
                "request_id": "BASDFdslf",
                "pid": "R7W6UNSE",
                "tag": "00002",
                "name": "Bob Smith",
                "gender": "M",
                "bib": "2",
                "status": {
                    "success": {
                        "type": "updated",
                        "msg": "Set Time to at START-H to 09:21:20.21."
                    }
                }
            },
            {
                "request_id": "BASDF1233",
                "status": {
                    "error": {
                        "type": "no_results",
                        "msg": "Participant not found."
                    }
                }
            }
        ]
    }
}