The XC Log data contract
XC Log v1, maintained by XC Athletes, is /v1/: a versioned,
stack-neutral HTTP+JSON API over athlete training data, covering reads, writes, a change
feed, and the identity and grant surface a team needs to hold a roster. Any system, not just
this one, can adopt it as a training log standard. Athletes own their own record. A team that
originates a session or check-in keeps read and export access to what it wrote. That access
survives the end of a grant and lasts as long as the platform holds the data.
Tiers
A tier is earned by passing the published black-box conformance suite for it (xclog-conformance), not by holding a token at that tier. The three tiers are named reader (1), writer (2), and
roster-aware (3); each is a strict superset of the one before it.
| Tier | Adds | Conformance covers |
|---|---|---|
| 1 · reader | GET /v1/token, people, training-sessions, checkins, rollups, changes | Reads, following every replaced_by link and tombstone type in the change
feed. Bulk export is not implemented; GET /v1/capabilities reports features.export as false (EXP-01..04) |
| 2 · writer | Tier 1, plus POST/PATCH/DELETE on training-sessions and checkins, and the by-ref upsert | WR-01..09: idempotency keys, If-Match, by-ref upsert, block replacement |
| 3 · roster-aware | POST /v1/people, join-codes/redeem, dob-assertion, person-links, grants | ID-01, ID-02, GR-01..02: create with attestation, join-code redemption, grant lifecycle |
A conformant integration may state that it passes the xclog-conformance suite at a given tier, for example "passes the xclog-conformance suite, writer tier," and use the matching brand set. The claim is earned by passing the conformance suite for that tier.
Versioning
Within /v1/ the platform only adds optional fields and enum values; it never
removes or repurposes one (PRIN-02). A conforming consumer already tolerates this by design
(PRIN-03): ignore unknown fields, map an unrecognized modality code to other, and
map any other unrecognized enum value to the fallback its own schema description names. A
breaking change never lands inside /v1/; it ships as a separate /v2/ beside it, announced with an RFC 9745 Deprecation header and an
RFC 8594 Sunset header, and /v1/ keeps running for at least 12 months
of overlap after that.
Staying in sync
Poll GET /v1/changes?cursor= every 5 minutes. That is the conformant sync
mechanism (SYNC-01). The ?updated_since= filters are a convenience only (SYNC-06).
The mirror-sync how-to walks the loop end to end.
Artifacts
- GET /v1/capabilities: which tiers and features this deployment implements, public, no token needed
- OpenAPI description (JSON): generation-grade, every operation this repo serves.
info.titlereads "XC Log", renamed from "xcathletes.org contract"; a generator that keyed off the old title should re-pull it. - JSON Schemas, one per entity: person, training_session, training_block, checkin, grant, change_entry, rollup_row, and the problem shape every error answers in
- Rate limits (JSON): LIM-01, LIM-03, and the DOB-assertion budget, with windows, thresholds, and each rule's failure posture
- Error index: every catalogue code, what triggers it, and what to do next
Start here
- Quickstart: Tier 1 (reader)
- Quickstart: Tier 2 (writer)
- Quickstart: Tier 3 (roster-aware)
- How to: keep a mirror in sync
- How to: handle a revoked token
- How to: a shared training log
- What the log records, and why
- Security and data governance
- The brand set
A token comes from your team's operator, who signs in and creates one at /team/tokens. The three how-to guides above (mirror-sync, revoked-token,
shared-log) are the spec for writing your own sync loop against it.