Skip to content

Repository files navigation

statbotics_client

A typed Dart client for the Statbotics API v3: EPA statistics, events, event team lists, and match schedules for FRC. Pure Dart, so it works in Flutter apps, CLIs, and servers alike.

import 'package:statbotics_client/statbotics_client.dart';

final client = StatboticsClient();
try {
  final events = await client.getEvents(2026);
  final teams = await client.getEventTeams('2026txhou');
} finally {
  client.close();
}

No API key needed. Transient server errors are retried with a pluggable sleep (inject a no-op in tests); non-transient failures throw StatboticsApiException with the status code.

API reference

StatboticsClient targets https://api.statbotics.io/v3. It needs no auth key. Single-object endpoints return null on 404; list endpoints return an empty list. Anything else outside 2xx throws StatboticsApiException. Remember to call close() when you are done so the underlying HTTP client is released.

Method Endpoint Returns
getEvent(eventKey) GET /event/{eventKey} StatboticsEvent?
getEvents(year) GET /events?year={year} List<StatboticsEvent>
getEventTeams(eventKey) GET /team_events?event={eventKey} List<StatboticsTeamEvent>
getTeamEvents(team, {year}) GET /team_events?team={team}[&year={year}] List<StatboticsTeamEvent>
getTeamYears(team) GET /team_years?team={team} List<StatboticsTeamYear>
getEventTeamsBasic(eventKey) GET /teams?event={eventKey} List<StatboticsTeamBasic>
getEventMatches(eventKey) GET /matches?event={eventKey} List<StatboticsMatch>
  • getEventTeams sorts results by rank ascending.
  • getTeamEvents sorts results newest season first, then by event key, so a team's most recent results lead. Pass year to narrow to one season.
  • getTeamYears sorts results newest season first, one row per season the team competed in. Compare seasons on epa.unitless or epa.norm, not epa.totalPoints: point values belong to a season's game, so a 2002 total of 16.6 and a 2025 total of 92.77 say nothing about which robot was better.
  • getEvents sorts results by week then name.
  • getEventMatches sorts results by comp level (qm, ef, qf, sf, f) then match number.
  • getEventTeamsBasic returns basic team info (number + nickname) and returns an empty list if the endpoint is unavailable.

The API is public and read-only, so models only decode the fields each endpoint exposes (EPA and the per-phase breakdown on StatboticsTeamEvent and StatboticsTeamYear, alliance teams on StatboticsMatch, dates and location on StatboticsEvent). Each model also round-trips through toJson for caching.

StatboticsEpa.totalPoints is the point estimate the API reports at epa.total_points, not an average over matches. The per-phase measures (autoPoints, teleopPoints, endgamePoints) come from epa.breakdown and are null for seasons predating that game's scoring split, so treat every EPA field as nullable.

Model tests assert against captured live response bodies in test/fixtures/, not only hand-written maps, so a change to the API's shape fails a test rather than reaching a consumer. Refresh a fixture by re-running the curl in the comment above _fixture in the test file.

Retries and backoff

The Statbotics API returns occasional 500s under load. StatboticsClient retries transient responses (HTTP 429 and any 5xx) up to maxAttempts times (default 3) with exponential backoff (300 * attempt^2 ms) before surfacing the error. 404 and other 4xx are returned or thrown immediately, with no retry.

final client = StatboticsClient(
  maxAttempts: 5,
  sleep: (duration) async {
    // use your own sleeper (e.g. a fake clock in tests)
  },
);

License

AGPL-3.0

About

Typed Dart client for the Statbotics API v3 (FRC EPA statistics, events, matches)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages