Enrollment and check-in
Teams and rosters, enrollments and the waitlist, check-in and its close, free-agent requests, and marking a match ready.
Your integration enrolls players (or teams), confirms them, checks them in and marks them ready for
their matches. Every route on this page needs tournaments:mutate, except match readiness, which
acts for an entrant and needs participants:mutate. All of them require an Idempotency-Key.
Entrant identity
Wherever a route takes an identity (or a team owner), it is an object:
| Field | Meaning |
|---|---|
mode | saas for a player known to Tanitar, opaque for a player you identify yourself. Must be one of the tournament's identityModes. |
principalId | The Tanitar player id, for saas. |
externalId | Your stable identifier, for opaque (up to 128 characters). |
displayName | Optional, up to 120 characters. |
seed, metadata | Optional. |
Teams
Team tournaments enroll teams. A team belongs to an organization and has an owner and members.
| Route | What it does |
|---|---|
POST /teams | Creates a team: organizationId, name, slug (lowercase, hyphens), owner identity. |
GET /teams/:teamId | Reads a team (tournaments:read). |
PATCH /teams/:teamId | Changes name or slug. |
POST /teams/:teamId/members | Adds a member: identity. The same identity cannot be added twice (TEAM_MEMBER_DUPLICATE). |
DELETE /teams/:teamId | Archives the team. Refused with TEAM_HAS_ACTIVE_ENROLLMENTS while it has a pending, confirmed or waitlisted enrollment. |
There is no route that lists teams; keep the teamId you get back from POST /teams.
Enroll
POST /enrollments enrolls one entrant in a published tournament while its registration window is
open.
| Field | Meaning |
|---|---|
tournamentId | The tournament. |
entrantType | solo or team; must match the tournament's participantMode. |
identity | The player, for solo. |
teamId | The team, for team. It must belong to the tournament's organization and have between capacity.teamSize and teamSize + maxSubstitutes members. |
attributes | Optional string map, checked against the tournament's eligibility rules. |
curl -X POST "$TOURNAMENT_API_URL/enrollments" \
-H "Authorization: Bearer $TANITAR_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"tournamentId":"trn_0190f1c2-7a3b-7c4d-8e5f-6a7b8c9d0e1f","entrantType":"solo","identity":{"mode":"opaque","externalId":"player-8812","displayName":"Nova"},"attributes":{"country":"FR"}}'Eligibility
A tournament's eligibility object can restrict who enrolls:
whitelistOnlywith awhitelistof identities;allowedCountries, matched against the enrollment'sattributes.country;requirements, a list of attribute names that must be present.
An enrollment that fails a rule is refused with 422 ENROLLMENT_INELIGIBLE.
Enrollment states
| State | Meaning |
|---|---|
pending | Enrolled, not yet confirmed. |
confirmed | Counts toward the tournament and is seeded into stages. |
waitlisted | The tournament was full and the waitlist had room; carries a waitlistPosition. |
withdrawn | Withdrawn by you. |
no_show | Did not check in before check-in closed. |
rejected | Refused. |
| Route | What it does |
|---|---|
POST /enrollments/:enrollmentId/confirm | pending to confirmed. |
POST /enrollments/:enrollmentId/withdraw | pending or confirmed to withdrawn. |
DELETE /enrollments/:enrollmentId | Same as withdraw. |
PATCH /enrollments/:enrollmentId | Replaces attributes. |
GET /tournaments/:slug/entrants | Lists the tournament's entrants with their status, seed and check-in state (tournaments:read; cursor, limit). |
The waitlist
When a tournament with waitlist.enabled and a waitlist.maxSize is full, a new enrollment is
waitlisted instead of refused. Without a waitlist, or once the waitlist is also full, the request
is refused with 409 TOURNAMENT_CAPACITY_FULL (TOURNAMENT_TEAM_CAPACITY_FULL when a team
tournament has reached maxTeams).
Promotion is automatic. There is no promote call:
- when an active enrollment is withdrawn while registration is still open, the first waitlisted
entrant becomes
pending; - when check-in closes, waitlisted entrants fill the places left by no-shows, in waitlist order, with their check-in waived.
Each promotion publishes tournament.enrollment.promoted.
Team rosters
A team enrollment copies the team's members into a roster. The owner's place is accepted; every other member's invitation is pending until you record their answer while registration is open:
POST /enrollments/:enrollmentId/roster/:rosterMemberId/acceptPOST /enrollments/:enrollmentId/roster/:rosterMemberId/reject
Answering an invitation that is not pending is refused with ENROLLMENT_STATE_INVALID. The roster
locks once every member has accepted.
Check-in
When the tournament has checkIn.enabled, each entrant checks in during the check-in window with
POST /enrollments/:enrollmentId/check-in. Checking in confirms a pending enrollment. Outside the
window the call is refused with TOURNAMENT_CHECK_IN_CLOSED. Reminders are published as
tournament.enrollment.check-in-reminder-requested at each lifecyclePolicy.checkInReminderOffsetsMinutes
before check-in closes, so you can notify your players.
Close check-in
Check-in closes on its own at checkIn.closesAt. To close it earlier, call
POST /tournaments/:slug/check-in/close; it answers with the tournament. Closing check-in:
- marks every
pendingorconfirmedentrant that has not checked in asno_show; - promotes waitlisted entrants into the freed places, in order;
- records that check-in close was processed: the tournament can now start, and registration can no longer be reopened.
Free agents
In a published team tournament, a player without a team can ask to be picked up.
| Route | What it does |
|---|---|
POST /free-agent-requests | Creates a request: tournamentId, identity. One per identity per tournament (FREE_AGENT_DUPLICATE). |
DELETE /free-agent-requests/:requestId | Withdraws a pending request. |
Requests publish tournament.free-agent.requested and tournament.free-agent.withdrawn, which your
own matchmaking can consume.
Match readiness
Once the tournament is in_progress, each entrant in a ready match signals that they are present
with POST /matches/:matchId/ready (participants:mutate):
| Field | Meaning |
|---|---|
enrollmentId | The entrant that is ready. It must occupy a slot in the match. |
expectedRevision | The match's current readiness revision (0 before anyone is ready). |
Marking an entrant ready twice is harmless. When every occupant is ready the match becomes
playing. A stale expectedRevision is refused with 409 MATCH_READINESS_STALE.
If the tournament sets lifecyclePolicy.matchForfeitTimeoutMinutes, a forfeit deadline starts when
the match becomes ready. See Forfeits.
You can also start a ready match yourself, without waiting for readiness, with
PATCH /matches/:matchId and "status": "playing". The same route edits label, scheduledAt,
notes and liveEntries (live scores) under an expectedRevision equal to the match's revision.
GET /matches/:matchId reads a match.
Errors you will see
errorCode | Meaning |
|---|---|
TOURNAMENT_REGISTRATION_CLOSED | The tournament is not published or the registration window is not open. |
ENROLLMENT_ENTRANT_TYPE_INVALID | entrantType does not match the tournament. |
ENROLLMENT_IDENTITY_INVALID | Missing identity, or a mode the tournament does not accept. |
ENROLLMENT_DUPLICATE | That entrant is already enrolled. |
TEAM_ROSTER_INVALID | The team size does not fit the tournament. |
ENROLLMENT_STATE_INVALID | The transition is not allowed from the current state. |
ENROLLMENT_CONCURRENT_MODIFICATION | Another write won; read again and retry. |
MATCH_NOT_READY | The tournament is not in progress or the match is not ready. |
MATCH_OCCUPANT_REQUIRED | The enrollment does not occupy the match. |
Tournament lifecycle
Create an organization and a tournament, publish it, close and reopen registration, generate stages, start, complete, cancel and archive.
Results and evidence
Report, correct and revert match results, read result history, handle forfeits, collect and review evidence, purge evidence media, and read standings.