Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Danielsl4/TFG_DAM_2526/llms.txt

Use this file to discover all available pages before exploring further.

Seasons are the top-level containers that organize every competition in FutsalLeague Manager. A season holds groups, which hold teams, which have registered players. Matches are always tied to a season, and all statistics — player goals, team standings, user prediction points — are scoped per season. This page walks through the full lifecycle from creation to closing a competition, including the time-saving import system for recurring leagues.

Season lifecycle

Create season → Add groups → Register teams → Assign teams to groups → Add players → Schedule matches → Run competition → Finish
Only one season can be active at a time. The active season drives the public-facing calendar, the default standings, and the prediction game.

Full setup workflow

1

Create the season

Call POST /seasons with a name, optional start and end dates, and an is_active flag. Setting is_active: true automatically deactivates all other seasons.
POST /seasons
{
  "name": "Liga Futsal 2026-27",
  "start_date": "2026-09-01",
  "end_date": "2027-05-31",
  "is_active": true
}
The response returns the full season object including its generated id.
2

Create groups

Groups define the competition divisions within a season (for example, Group A and Group B in a group stage). Call POST /groups for each group:
POST /groups
{
  "name": "Grupo A",
  "season_id": 4
}
Groups can be renamed (PUT /groups/:id) or deleted (DELETE /groups/:id) as long as they have no matches associated.
3

Register teams in the season

An existing team must be explicitly enrolled in a season before it can participate. Use POST /teams/:id/register with the target season_id:
POST /teams/7/register
{ "season_id": 4 }
This creates a team_stats row for the team in that season with all counters set to zero. You can also create a brand-new team and enroll it in the same request by passing season_id to POST /teams.
4

Assign teams to groups

Once teams are registered in the season, place them in competition groups via POST /groups/:id/teams:
POST /groups/11/teams
{
  "team_id": 7,
  "season_id": 4
}
This creates the team’s group-specific stats entry. To remove a team from a group without removing it from the season entirely, call DELETE /groups/:id/teams/:teamId?season_id=4.
5

Register players

Players are linked to a team for a specific season through the team_players table. Enroll a player with POST /players/:id/register:
POST /players/55/register
{
  "team_id": 7,
  "season_id": 4,
  "jersey_number": "10"
}
If a player already has a registration in this season it is replaced, preventing duplicate entries. Jersey numbers are validated for uniqueness within the same team and season.
6

Schedule matches

With teams and groups in place, create matches via POST /matches. See Match management for the full field reference and the referee workflow.
7

Run the competition

Referees lock, score, and finalize matches. Each finalized match atomically updates team standings in team_stats and individual stats in player_stats.
8

Close the season

When all matches are finished, set is_active: false on the season via PUT /seasons/:id. The season’s data remains fully queryable by passing season_id to any endpoint; it simply stops being the default.

Activating a season

Sending is_active: true when creating or updating a season triggers a global deactivation of all other seasons in a single transaction before the target season is updated. This ensures exactly one active season at all times:
PUT /seasons/4
{
  "name": "Liga Futsal 2026-27",
  "start_date": "2026-09-01",
  "end_date": "2027-05-31",
  "is_active": true
}

Importing structure from a previous season

When running a recurring edition of the same league you can clone groups, teams, and player squads from an existing season instead of rebuilding everything from scratch. Stats are reset to zero for all cloned entries.

Option 1 — Import during season creation

Pass import_from in the POST /seasons body:
{
  "name": "Liga Futsal 2027-28",
  "start_date": "2027-09-01",
  "end_date": "2028-05-31",
  "is_active": false,
  "import_from": 4
}
The entire import (groups → team stats → player squads) runs inside the same database transaction as the season creation. If any step fails the whole operation is rolled back.

Option 2 — Import into an existing season

If you created the season first and want to import structure later, call POST /seasons/:id/import-structure:
POST /seasons/5/import-structure
{ "fromSeasonId": 4 }
The response confirms how many groups were imported:
{
  "message": "Grupos y plantillas importados. Los equipos están listos para ser asignados a grupos.",
  "groupsImported": 2
}
What gets cloned:
  • All group names from the source season (assigned to the new season)
  • A fresh team_stats row (all zeros) for every team that participated in the source season
  • All team_players rows from the source season, preserving jersey numbers
What is not cloned:
  • Match history and events
  • Any statistics (goals, cards, points — all start at zero)
  • Group assignments for teams (you reassign teams to groups after import)
Use import-structure at the start of each new edition to avoid manually re-entering every team and player. After importing, simply review the squads, update any player transfers, and then assign teams to their groups for the new season.

Removing a team from a season

To withdraw a team from a specific season without deleting the team from the system, call DELETE /teams/:id/season/:seasonId:
DELETE /teams/7/season/4
This removes the team’s team_stats rows for that season and unlinks all its players from the team within that season (the players themselves remain active in the system). The team entity is untouched and can be registered in future seasons.

Group management reference

ActionEndpointNotes
List groupsGET /groups?season_id=4Returns group name and season name
Create groupPOST /groupsRequires name and season_id
Rename groupPUT /groups/:id
Delete groupDELETE /groups/:idFails if group has associated matches
List teams in groupGET /groups/:id/teamsReturns standings sorted by points
Add team to groupPOST /groups/:id/teamsCreates stats row; fails if team already in group
Remove team from groupDELETE /groups/:id/teams/:teamId?season_id=XRemoves stats row only

Season deletion

DELETE /seasons/:id permanently removes the season and all its direct dependencies. This will fail if the season has groups or matches attached; remove those first or use a dedicated season deactivation workflow instead of deletion when you need to preserve historical data.

Build docs developers (and LLMs) love