Quickstart: Tier 2 (writer)

Tier 2 is everything Tier 1 reads, plus writing training sessions and check-ins your team originates. This assumes the Tier 1 quickstart's token and capability check are already done.

1. Get a Tier 2 token

Your team operator mints one at /team/tokens, same as Tier 1, choosing "Tier 2" from the tier picker.

2. Create a training session

A create is always observable as 201, distinct from the 200 an update to the same row would return later (WR-04). person_id names an athlete your team already has a write-access grant for:

curl -X POST https://xcathletes.org/v1/training-sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "person_id": "1a2b3c4d5e6f70819203a4b5c6d7e8f9",
    "date": "2026-08-20",
    "modality": [{ "system": "xca", "code": "skiing", "display": "Skiing" }],
    "technique": "classic",
    "duration_seconds": 3600,
    "blocks": [{ "reps": 1, "duration_seconds": 3600, "zone": "L2" }]
  }'
HTTP/1.1 201 Created
Location: /v1/training-sessions/aabbccdd11223344556677889900aabb
ETag: W/"1"

{
  "id": "aabbccdd11223344556677889900aabb",
  "person_id": "1a2b3c4d5e6f70819203a4b5c6d7e8f9",
  "date": "2026-08-20",
  "technique": "classic",
  "duration_seconds": 3600,
  "modality": [{ "system": "xca", "code": "skiing", "display": "Skiing" }],
  "blocks": [{ "position": 0, "reps": 1, "duration_seconds": 3600, "zone": "L2" }],
  "computed": { "block_seconds": 3600, "seconds_by_zone": { "L2": 3600 } },
  "duplicates": [],
  "origin_team_id": "01020304050607080910111213141516",
  "origin_person_id": "1a2b3c4d5e6f70819203a4b5c6d7e8f9",
  "version": 1
}

That 201, carrying version: 1 and an ETag, is the verified outcome: your team originated a row. The Idempotency-Key makes a retried request safe to resend (WR-01); a later change to this same row needs its current ETag back as If-Match (MW-02), or it answers precondition_required.