Skip to main content

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.

Referees and administrators manage live match data through a set of dedicated endpoints. The workflow is linear: lock the match to prevent concurrent edits, start it, record every event as it happens, then finalize to commit standings and prediction points. The system enforces this order and protects data integrity at every step.
Locking prevents concurrent edits. The lock is per-referee and must be explicitly released via POST /matches/:id/unlock, or it expires automatically after 2 minutes of inactivity. Admins can force-release any lock by passing ?force=true.

Match locking

Before any edit — changing status, adding events, or finalizing — a referee must acquire a lock on the match. This is a mutual-exclusion mechanism backed by two database columns: locked_by (the user ID holding the lock) and locked_at (the timestamp of the last lock renewal). Acquiring a lockPOST /matches/:id/lock
  • If the match is unlocked or was locked more than 2 minutes ago, the lock is granted to the calling referee.
  • If the same referee already holds the lock, the locked_at timestamp is renewed.
  • If another referee holds an unexpired lock, the response returns HTTP 409 with the locking referee’s username.
{
  "message": "El partido está siendo editado por árbitro2",
  "success": false,
  "owner": "árbitro2"
}
Releasing a lockPOST /matches/:id/unlock releases the lock held by the calling user. Admins can add ?force=true to release any lock regardless of ownership.

Updating match status

A match moves through three statuses in sequence:
StatusMeaning
pendienteScheduled, not yet started
en_cursoMatch is in progress
finalizadoMatch is over; standings are committed
Change the status via PUT /matches/:id/status with { "status": "en_curso" } in the request body. The match must be locked by the calling referee before this endpoint accepts the request. Only the three values above are valid; any other value returns HTTP 400.

Recording events

Events are added one at a time via POST /matches/:id/events. Each request requires:
FieldDescription
typeOne of the event types listed below
playerIdID of the player who performed the action
teamSide"home" or "away" — which side the player belongs to
Supported event types:
TypeEffect
golIncrements home_goals or away_goals; adds to player_stats.goals
tarjeta_amarillaAdds to player_stats.yellow_cards and team_stats.yellow_cards
tarjeta_rojaAdds to player_stats.red_cards and team_stats.red_cards
penalti_tanda_marcadoIncrements home_penalty_goals or away_penalty_goals
penalti_tanda_falladoRecorded in the event log only; no score changes
All stat updates are wrapped in a database transaction. If any part of the insert fails, the entire operation is rolled back.

Finalizing a match

PUT /matches/:id/finish transitions the match to finalizado and triggers several cascading updates in a single atomic transaction:
  1. Sets status = 'finalizado' and clears the lock.
  2. Optionally saves observations text passed in the request body.
  3. Increments matches_played in player_stats for every player with at least one event in the match.
  4. Calculates win/draw/loss and updates team_stats for both teams (goals for, goals against, points).
  5. Determines the correct prediction outcome (local, empate, or visitante) and awards 1 point to each user who voted correctly, updating user_points for the season.
  6. Clears the Redis cache entries for the match and the global match list.
Once finalized, a match cannot be re-opened. The finish endpoint explicitly checks for status = 'finalizado' and throws an error if you attempt to finalize again. Ensure all events are recorded and the score is correct before calling this endpoint.

Removing events

Individual events can be deleted via DELETE /matches/:matchId/events/:eventId. The match must be locked by the calling referee. Removing an event automatically reverses all stat changes that were applied when the event was first recorded:
  • A deleted gol decrements the team’s goal tally (minimum 0).
  • A deleted tarjeta_amarilla or tarjeta_roja decrements the player’s and team’s card counts.
  • A deleted penalti_tanda_marcado decrements the penalty shootout score.
  • Player stats are decremented in player_stats for all regular event types.
The reversal is atomic — if any part of the undo fails, the deletion is rolled back.

Referee workflow

1

Lock the match

Call POST /matches/:id/lock. If the response returns success: true, you hold the lock. If another referee is editing, wait or ask them to release it.
2

Set status to en_curso

Call PUT /matches/:id/status with { "status": "en_curso" } to signal that the match has started. The lock must be held.
3

Record goals and cards

For each event during the match, call POST /matches/:id/events with the event type, player ID, and team side. Review the running score in the match detail view to catch mistakes early.
4

Finalize the match

When the final whistle blows, call PUT /matches/:id/finish (optionally with observations). Standings, player stats, and prediction points are all updated atomically. The lock is released automatically.

Build docs developers (and LLMs) love