diff --git a/API-Documentation.md b/API-Documentation.md new file mode 100644 index 0000000..5018312 --- /dev/null +++ b/API-Documentation.md @@ -0,0 +1,844 @@ +## Overview +FTCLive provides a public API that 3rd party developers can use to create applications using the data +stored by the FTCLive server. The intent is to provide an officially supported interface for services such +as ftcscores.com. + +## Guidelines +Applications may run on any computer that is on the same network as the scoring system. Applications +that are co-hosted on the scoring computer should not attempt to reach into the scoring system's +databases directly. +It's assumed that the primary purpose of a 3rd party application is to publish match data to a cloud +server. Care should be taken to ensure that the scorekeeping computer is on a secure network. If using +live scoring an isolated 5Ghz network for the scoring server and tablet trackers is preferred. Event +participants must not have access to this network even as the computer running the 3rd party +application has access to the broader internet. +Applications should be sensitive to how often they poll for data. Please remember that third party +applications are by their very nature accessories to the critical functions of scoring an event. No 3rd +party application should ever be the source of performance issues with FTCLive. To that end, when +polling for match results, it's not going to matter if the application gets the results many multiples of +seconds after they've been committed to the database. Poll too fast and FTCLive reserves the right to +blackball an application by returning HTTP Status 429 for all requests. +Applications must not generate their own rankings from match data.without explicitly labelling them as +not event official. The easiest to reach rankings, if not the only rankings available, should only be +populated from the rankings resource described below + +## API Syntax +The FTCLive API uses a RESTful architecture to define a set of URIs operating over the GET method. +POST, PUT, and DELETE are not supported. 3rd party applications may not modify the FTClive +database. 3rd party applications should be sensitive to how often they query the server. +To keep the API surface as simple as possible a “Nouns are good; verbs are bad” approach is defined. +Given that access to the underlying database is read only, GET is implied. For any given resource the +resource without parameters returns an array of all elements, the resource with a parameter returns a +detailed description of the element. To reduce the total number of resources, all resources that operate +over a collection of data are defined as plural even when selecting only one element in a collection. +All public api resources paths begin with ‘apiv1’ . All paths must have a trailing forward slash. +All query responses are json formatted text. + +## Examples +To query all teams globally + +`http://localhost/apiv1/teams/` + +To query a specific team + +`http://localhost/apiv1/teams/42/` + +To query a list of all teams participating in an event with event code "nychamps" + +`http://localhost/apiv1/events/nychamps/teams/` + +## Errors +Any given resource may return an error given by the following JSON schema. +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Error", + "definitions": { + "Error": { + "type": "object", + "additionalProperties": false, + "properties": { + "errorCode": { + "type": "string" + } + }, + "required": [ + "errorCode" + ], + "title": "Error" + } + } +} +``` + +`errorCode` is one of `REJECT_REQUEST`, `NOT_READY`, `NO_PERMS`, `NO_SUCH_EVENT`, +`NO_SUCH_MATCH`, `NO_SUCH_TEAM`. + +`NO_PERMS` is reserved for future use. + +Additionally an HTTP Response error is set as described in the individual resource sections below. + +## Resources +The following lists all resources supported by FTCLive. The resource name is given, followed by a JSON +schema that describes the object returned. + +### `apiv1/teams/` +Returns all team numbers that have registered with FIRST as of the last sync to the FIRST registration +database for this release of FTCLive. This is a very long list. Applications that want this data should +query once upon startup and then never again. +Errors: None. The packaged team list will always be returned. +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + $ref": "#/definitions/Teams", + "definitions": { + "Teams": { + "type": "object", + "additionalProperties": false, + "properties": { + "teamNumbers": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "teamNumbers" + ], + "title": "Teams" + } + } +} +``` +### `apiv1/teams//` +A detailed description of a team for any given team number. + +Errors: NO_SUCH_TEAM + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/TeamDetail", + "definitions": { + "TeamDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "number": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "school": { + "type": "string" + }, + "city": { + "type": "string" + }, + "state": { + "type": "string" + }, + "country": { + "type": "string" + }, + "rookie": { + "type": "integer" + } + }, + "required": [ + "city", + "country", + "name", + "number", + "rookie", + "school", + "state" + ], + "title": "TeamDetail" + } + } +} +``` + +### `apiv1/events/` +A list of all event codes that this instance of the FTCLive server knows about. + +Errors: None, if no events exist then the output will be an empty list. +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Events", + "definitions": { + "Events": { + "type": "object", + "additionalProperties": false, + "properties": { + "eventCodes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "eventCodes" + ], + "title": "Events" + } + } +} +``` + +### `apiv1/events//` +A detailed description of an event for any given event code. + +Errors: NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/EventsDetail", + "definitions": { + "EventsDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "eventCode": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "status": { + "type": "string" + }, + "finals": { + "type": "boolean" + }, + "division": { + "type": "integer" + }, + "start": { + "type": "integer" + }, + "end": { + "type": "integer" + } + }, + "required": [ + "division", + "end", + "eventCode", + "finals", + "name", + "start", + "status", + "type" + ], + "title": "EventsDetail" + } + } +} +``` +### `apiv1/events//teams/` +A list of teams defined by team numbers participating in any given event. + +Errors: NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Apiv1Teams/events", + "definitions": { + "Teams": { + "type": "object", + "additionalProperties": false, + "properties": { + "teamNumbers": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "teamNumbers" + ], + "title": "Teams" + } + } +} +``` +### `apiv1/events//matches/` +The match list for a given event. If matchmaker has not been run when this is requested the match list +will be empty. + +Errors: NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/MatchLise", + "definitions": { + "MatchList": { + "type": "object", + "additionalProperties": false, + "properties": { + "matches": { + "type": "array", + "items": { + "$ref": "#/definitions/Match" + } + } + }, + "required": [ + "MatchList" + ], + "title": "Empty" + }, + "Match": { + "type": "object", + "additionalProperties": false, + "properties": { + "matchNumber": { + "type": "integer" + }, + "red": { + "$ref": "#/definitions/Blue" + }, + "blue": { + "$ref": "#/definitions/Blue" + } + }, + "required": [ + "blue", + "matchNumber", + "red" + ], + "title": "Match" + }, + "Blue": { + "type": "object", + "additionalProperties": false, + "properties": { + "team1": { + "type": "integer" + }, + "team2": { + "type": "integer" + }, + "isTeam1Surrogate": { + "type": "boolean" + }, + "isTeam2Surrogate": { + "type": "boolean" + } + }, + "required": [ + "isTeam1Surrogate", + "isTeam2Surrogate", + "team1", + "team2" + ], + "title": "Blue" + } + } +} +``` +### `apiv1/events//matches//` +Results for a match that has been played. NO_SUCH_MATCH indicates either an invalid match number +or the match has not been played yet. + +Errors: NO_SUCH_EVENT, NO_SUCH_MATCH + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/MatchesDetail", + "definitions": { + "MatchesDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "finished": { + "type": "boolean" + }, + "redScore": { + "type": "integer" + }, + "blueScore": { + "type": "integer" + }, + "red": { + "$ref": "#/definitions/Blue" + }, + "blue": { + "$ref": "#/definitions/Blue" + } + }, + "required": [ + "blue", + "blueScore", + "finished", + "red", + "redScore" + ], + "title": "MatchesDetail" + }, + "Blue": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto": { + "type": "integer" + }, + "teleop": { + "type": "integer" + }, + "end": { + "type": "integer" + }, + "penalty": { + "type": "integer" + } + }, + "required": [ + "auto", + "end", + "penalty", + "teleop" + ], + "title": "Blue" + } + } +} +``` +### `apiv1/events//elim/alliances/` +The elimination alliances. + +Errors: NOT_READY, NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Alliances", + "definitions": { + "Alliances": { + "type": "object", + "additionalProperties": false, + "properties": { + "alliances": { + "type": "array", + "items": { + "$ref": "#/definitions/Alliance" + } + } + }, + "required": [ + "alliances" + ], + "title": "Alliances" + }, + "Alliance": { + "type": "object", + "additionalProperties": false, + "properties": { + "seed": { + "type": "integer" + }, + "captain": { + "type": "integer" + }, + "pick1": { + "type": "integer" + }, + "pick2": { + "type": "integer" + } + }, + "required": [ + "captain", + "pick1", + "pick2", + "seed" + ], + "title": "Alliance" + } + } +} +``` +### `apiv1/events//elim/sf//` +Returns an array of matches that have been played in the given semifinal along with the teams that +played in the matches. should be 1 or 2. The team that sits out any given match is +represented by a team number of -1. + +Errors: NOT_READY, NO_SUCH_EVENT, NO_SUCH_MATCH + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/SemifinalMatchList", + "definitions": { + "SemifinalMatchList": { + "type": "object", + "additionalProperties": false, + "properties": { + "matchList": { + "type": "array", + "items": { + "$ref": "#/definitions/MatchList" + } + } + }, + "required": [ + "matchList" + ], + "title": "SemifinalMatchList" + }, + "MatchList": { + "type": "object", + "additionalProperties": false, + "properties": { + "match": { + "type": "string" + }, + "red": { + "$ref": "#/definitions/Alliance" + }, + "blue": { + "$ref": "#/definitions/Alliance" + } + }, + "required": [ + "blue", + "match", + "red" + ], + "title": "MatchList" + }, + "Alliance": { + "type": "object", + "additionalProperties": false, + "properties": { + "seed": { + "type": "integer" + }, + "captain": { + "type": "integer" + }, + "pick1": { + "type": "integer" + }, + "pick2": { + "type": "integer" + } + }, + "required": [ + "captain", + "pick1", + "pick2", + "seed" + ], + "title": "Alliance" + } + } +} +``` +### `apiv1/events//elim/sf///` +Detailed results for a single match within a semifinal. + +Errors: NOT_READY, NO_SUCH_EVENT, NO_SUCH_MATCH + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/SemifinalMatchDetail", + "definitions": { + "SemifinalMatchDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "finished": { + "type": "boolean" + }, + "redScore": { + "type": "integer" + }, + "blueScore": { + "type": "integer" + }, + "red": { + "$ref": "#/definitions/Score" + }, + "blue": { + "$ref": "#/definitions/Score" + } + }, + "required": [ + "blue", + "blueScore", + "finished", + "red", + "redScore" + ], + "title": "SemifinalMatchDetail" + }, + "Score": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto": { + "type": "integer" + }, + "teleop": { + "type": "integer" + }, + "end": { + "type": "integer" + }, + "penalty": { + "type": "integer" + } + }, + "required": [ + "auto", + "end", + "penalty", + "teleop" + ], + "title": "Score" + } + } +} +``` +### `apiv1/events//elim/finals/` +Returns an array of matches that have been played along with the teams that played in the matches. +The team that sits out any given match is represented by a team number of -1. + +Errors: NOT_READY, NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/FinalsMatchList", + "definitions": { + "FinalsMatchList": { + "type": "object", + "additionalProperties": false, + "properties": { + "matchList": { + "type": "array", + "items": { + "$ref": "#/definitions/MatchList" + } + } + }, + "required": [ + "matchList" + ], + "title": "FinalsMatchList" + }, + "MatchList": { + "type": "object", + "additionalProperties": false, + "properties": { + "match": { + "type": "string" + }, + "red": { + "$ref": "#/definitions/Blue" + }, + "blue": { + "$ref": "#/definitions/Blue" + } + }, + "required": [ + "blue", + "match", + "red" + ], + "title": "MatchList" + }, + "Blue": { + "type": "object", + "additionalProperties": false, + "properties": { + "seed": { + "type": "integer" + }, + "captain": { + "type": "integer" + }, + "pick1": { + "type": "integer" + }, + "pick2": { + "type": "integer" + } + }, + "required": [ + "captain", + "pick1", + "pick2", + "seed" + ], + "title": "Blue" + } + } +} +``` +### `apiv1/events//elim/finals//` +Detailed results for a single match within a final. + +Errors: NOT_READY, NO_SUCH_EVENT, NO_SUCH_MATCH + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/FinalsMatchDetail", + "definitions": { + "FinalsMatchDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "finished": { + "type": "boolean" + }, + "redScore": { + "type": "integer" + }, + "blueScore": { + "type": "integer" + }, + "red": { + "$ref": "#/definitions/Score" + }, + "blue": { + "$ref": "#/definitions/Score" + } + }, + "required": [ + "blue", + "blueScore", + "finished", + "red", + "redScore" + ], + "title": "FinalsMatchDetail" + }, + "Score": { + "type": "object", + "additionalProperties": false, + "properties": { + "auto": { + "type": "integer" + }, + "teleop": { + "type": "integer" + }, + "end": { + "type": "integer" + }, + "penalty": { + "type": "integer" + } + }, + "required": [ + "auto", + "end", + "penalty", + "teleop" + ], + "title": "Score" + } + } +} +``` + +### `apiv1/events//rankings/` +A list of rankings for the event. Clients should understand that rankings are rather static and schedule +their polling appropriately. + +Errors: NO_SUCH_EVENT + +HTTP Status: 404 +``` +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Rankings", + "definitions": { + "Rankings": { + "type": "object", + "additionalProperties": false, + "properties": { + "rankingList": { + "type": "array", + "items": { + "$ref": "#/definitions/RankingList" + } + } + }, + "required": [ + "rankingList" + ], + "title": "Rankings" + }, + "RankingList": { + "type": "object", + "additionalProperties": false, + "properties": { + "team": { + "type": "integer" + }, + "teamName": { + "type": "string" + }, + "ranking": { + "type": "integer" + }, + "rankingPoints": { + "type": "integer" + }, + "tieBreakerPoints": { + "type": "integer" + }, + "matchesPlayed": { + "type": "integer" + } + }, + "required": [ + "matchesPlayed", + "ranking", + "rankingPoints", + "team", + "teamName", + "tieBreakerPoints" + ], + "title": "RankingList" + } + } +} +``` +### `apiv1/events//awards/` +List of award winners. The list is not available until all awards have been presented. A client that asks +for this resource too early will receive a REJECT_REQUEST error. +Errors: REJECT_REQUEST +HTTP Status: 403 +``` +TBD +```