Teams and players are the core entities of the Futsal League Manager. Teams persist across seasons, while player enrollments are season-specific. This separation lets the same player wear a different jersey number or play for a different club each season without losing historical records.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Danielsl4/TFG_DAM_2526_Consulta2/llms.txt
Use this file to discover all available pages before exploring further.
A player can appear in different teams across different seasons. The
team_players junction table stores one enrollment record per player per season, so a player’s history is fully preserved even after a transfer.Teams
Every team record holds the following fields:| Field | Type | Description |
|---|---|---|
name | string | Team name (required) |
kit_color | string | Primary kit colour, used for display purposes |
logo_url | text | Cloudinary URL of the team’s crest |
delegate | string | Name of the team delegate or contact person |
coach | string | Name of the head coach |
phone | string | Contact phone number |
is_active | boolean | true for active teams; false for soft-deleted teams |
POST /teams requires name. All other fields are optional. Pass a season_id to immediately register the team in a season (creates the team_stats record).
Editing a team — PUT /teams/:id accepts all fields. If logo_url changes and the Cloudinary public IDs differ, the old image is automatically deleted from Cloudinary.
Team detail — GET /teams/:id returns the full team record together with the current season’s roster, standings stats, and match schedule. Pass ?season_id= to retrieve data for a specific season instead of the active one.
Registering in a season — POST /teams/:id/register with a season_id body parameter enrolls an existing team in a season. Use this when promoting a team that already exists in the database into a new edition.
Players
Each player record stores:| Field | Type | Description |
|---|---|---|
name | string | Full name (required) |
birth_date | date | Date of birth |
photo_url | text | Cloudinary URL of the player’s photo |
is_active | boolean | true for active players; false for soft-deleted ones |
POST /players requires name. Optionally pass season_id and team_id to enroll the player immediately upon creation.
Editing a player — PUT /players/:id accepts name, birth_date, and photo_url. The old photo is removed from Cloudinary if the URL changes and the public IDs differ.
Removing from a season — DELETE /players/:id/season/:seasonId removes the player’s enrollment and season stats for that specific season without affecting other seasons.
Assigning players to teams
Player-to-team assignments are managed through theteam_players junction table. Each record links a player to a team for a single season:
| Column | Description |
|---|---|
player_id | References players.id |
team_id | References teams.id |
season_id | References seasons.id |
jersey_number | The player’s shirt number for this season |
POST /players/:id/register with team_id, season_id, and optionally jersey_number in the request body. Any previous enrollment in the same season is replaced, making this also the transfer endpoint. Jersey numbers must be unique within a team and season.
Removing from a team — DELETE /players/:id/unregister with team_id and season_id in the request body removes a specific team assignment without deleting the player record.
Players without a team assignment (enrolled in the season but not yet assigned to a club) are handled by omitting team_id when calling the enroll endpoint.
Uploading logos and photos
All images are stored in Cloudinary. The upload flow works as follows:- Send a
POST /admin/uploadrequest asmultipart/form-datawith the file in theimagefield. - Optionally pass
?folder=teamsor?folder=playersas a query parameter to organise files in Cloudinary. Pass?filename=to control the public ID. - The server compresses the image with Sharp before uploading. The response contains the Cloudinary URL:
- Save the returned URL into the
logo_url(teams) orphoto_url(players) field when creating or editing the record.
Soft deletion and recovery
Both teams and players use soft deletion (is_active = false) rather than immediate removal. This preserves match history and statistics.
Soft-deleting a team — DELETE /teams/:id sets is_active = false. The team disappears from public listings but its match records remain intact.
Restoring a team — POST /teams/:id/restore sets is_active = true.
Permanently deleting a team — DELETE /teams/:id/permanent performs a hard delete. This is blocked if the team has any match history or season enrollments.
The same pattern applies to players and fields:
- Soft-delete:
DELETE /players/:id - Restore:
POST /players/:id/restore - Permanent delete:
DELETE /players/:id/permanent(blocked if the player has match events or team enrollments)
GET /teams/admin/trash, GET /players/admin/trash) and can be recovered from there.