Referees manage the live state of a match: they acquire an exclusive lock before making any changes, record match events as play progresses, and finalize the result when the final whistle blows. The system updates team standings, player statistics, and porra (prediction) points automatically on finalization.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.
How match locking works
To prevent two referees from editing the same match simultaneously, FutsalManager uses a database-level lock. A lock is valid for two minutes and must be renewed by the client. If a lock expires, another referee can acquire it.All endpoints that modify match state — status changes, event recording, observations, and finalization — require the caller to hold the current lock. Requests without a valid lock return a 403.
Typical referee workflow
Acquire the match lock
Before touching anything, call the lock endpoint. A successful lock means no one else can edit the match until you release it or it expires.Successful response:If someone else holds the lock you receive a 409 with the other referee’s username:
Set status to en_curso
Move the match from Valid status values are
pendiente to en_curso to signal that play has started.pendiente, en_curso, and finalizado. Transitions are not enforced by the API — you can move between any valid status, but the expected flow is pendiente → en_curso → finalizado.Record match events
Add a goal, card, or penalty shootout event as it happens.Event types:
type | Effect on match record |
|---|---|
gol | Increments home_goals or away_goals depending on teamSide. |
tarjeta_amarilla | Records a yellow card; increments player and team yellow card stats. |
tarjeta_roja | Records a red card; increments player and team red card stats. |
penalti_tanda_marcado | Increments home_penalty_goals or away_penalty_goals. No effect on regular stats. |
penalti_tanda_fallado | Records the miss; no score counters are changed. |
playerId and teamSide ("home" or "away") are required for every event type.All three fields — type, playerId, teamSide — are required. The operation runs in a transaction: the event row and the stat updates are committed together or rolled back entirely.Correct a mistake — delete an event
If an event was recorded in error, delete it. All stat changes from that event are reversed atomically.The reversal logic mirrors the addition logic:
- A deleted
goldecrements the appropriate goal counter (floor of 0). - A deleted
penalti_tanda_marcadodecrements the penalty goal counter. - A deleted
tarjeta_amarillaortarjeta_rojadecrements the card counters on both the player and the team.
Add observations (optional)
Record any notes about the match — incidents, suspensions, or clarifications — before finalizing.Send
null to clear existing observations.Finalize the match
Finalizing triggers a cascade of automatic updates in a single database transaction:Successful response:
- Match
statusis set tofinalizado. - The lock (
locked_by,locked_at) is cleared. - Observations are saved.
matches_playedis incremented for every player who appears in an event.- Team standings (
played,won,drawn,lost,goals_for,goals_against,points) are updated for both teams. - Porra (prediction) votes are evaluated: users who predicted the correct result each receive one point.
Standings calculation reference
WhenPUT /matches/:id/finish is called, points are awarded as follows:
| Result | Home team | Away team |
|---|---|---|
Home win (home_goals > away_goals) | 3 points, 1 win | 1 loss |
Away win (home_goals < away_goals) | 1 loss | 3 points, 1 win |
Draw (home_goals == away_goals) | 1 point, 1 draw | 1 point, 1 draw |
home_team_id and an away_team_id, and belongs to a group (group_id is not null). Penalty shootout goals do not affect regular standings — they are stored separately in home_penalty_goals / away_penalty_goals for display purposes only.