SETTO API

Registro de cambios

Historial de versiones de la API externa de SETTO — qué salió, qué cambió y qué cuenta como un cambio rompedor.

Cada cambio de la API externa queda registrado aquí, del más reciente al más antiguo. La API se versiona en su ruta (/v1/): los cambios aditivos salen dentro de v1, y cualquier cosa que rompiera una integración existente saldría con un nuevo prefijo de ruta.

Qué cuenta como un cambio

Cambio¿Rompe?
Un endpoint, campo o ruta de populate nuevoNo — es aditivo
Un miembro nuevo en un enum existente (un status, sport o type nuevo)No — trata los enums como abiertos
Un code de error nuevo para un estado que ya manejasNo
Eliminar o renombrar un campo, endpoint o ruta de populateSí
Cambiar el tipo de un campo, o el orden por defecto de una listaSí
Endurecer la validación de un parámetro que antes se aceptabaSí

Construye para los casos aditivos: ignora los campos que no reconozcas y deja pasar los valores de enum que no hayas visto. Así una versión del tipo "las ligas individuales de pickleball ahora exponen un type de torneo nuevo" nunca llega a tu guardia.

2026-11 — Cuadros y resultados con IA

Aditivo. Los tokens, las lecturas, las escrituras de configuración y la de programación existentes siguen funcionando igual.

  • Once operaciones nuevas, 38 en total, en las categorías de pádel, tenis y pickleball de un torneo regular. Con el permiso manage («Gestionar torneos»): fijar el formato de una categoría, fase de grupos, eliminatorias o ambas (previewDivisionFormat, applyDivisionFormat); agregar las eliminatorias después de la fase de grupos (appendEliminationRound); armar los grupos («Configurar grupos», previewPools, applyPools) y el cuadro («Configurar eliminatorias», previewDraw, applyDraw; de 2 a 256 equipos); acomodar el cuadro con la clasificación final de los grupos («Confirmar cuadro», confirmDraw; el mismo cuerpo enviado otra vez contesta changed: false); y fijar quién juega un partido (setGameTeams). Con results («Cargar resultados»), las primeras rutas que lo usan: cargar el resultado de un partido (recordGameResult: sus sets, un W.O., un retiro o un «Doble W.O.») y borrarlo («Borrar resultado», clearGameResult). Las tres vistas previas solo requieren read. Consulta la referencia de la API.
  • Un formato, unos grupos o un cuadro se previsualizan y luego se confirman, como una baja: la vista previa contesta el plan y un confirmationToken válido 15 minutos; la aplicación escribe exactamente ese plan, o contesta 409 PREVIEW_STALE si la categoría cambió en medio. El sorteo de los grupos se puede repetir (rngSeed), y pins pone a un equipo en un grupo dado.
  • Lo jugado nunca se reconstruye. Un formato, unos grupos o un cuadro sobre resultados se rechazan (FORMAT_HAS_PLAYED_GAMES, ROUND_HAS_PLAYED_GAMES, KNOCKOUT_HAS_PLAYED_GAMES), y la confirmación nunca acomoda a un equipo dado de baja: replace le da su lugar a otro equipo de la categoría o a un BYE.
  • Un resultado mueve lo que sigue: la clasificación de los grupos y, en eliminatorias, al ganador (advanced lista los lugares que llenó); borrarlo regresa cada lugar a «Ganador del juego N». Un resultado guardado solo se reemplaza con overwrite: true. Una respuesta exitosa puede traer warnings: SET_COUNT_UNUSUAL, BRACKET_ALREADY_CONFIRMED, STANDINGS_NOT_COUNTED.
  • Códigos de rechazo nuevos (INVALID_FORMAT, INVALID_POOL_PIN, INVALID_DRAW_SIZE, ROUND_ROBIN_INCOMPLETE, DRAW_SEATS_WITHDRAWN_TEAM, GAME_HAS_RESULT, INVALID_RESULT, …), cada uno con details. Cada escritura de aquí acepta un encabezado opcional Idempotency-Key, y cada escritura, y cada rechazo, queda en la «Actividad». Consulta Errores.
  • El servidor MCP (1.5.0) suma las once herramientas, 38 en total, y sus instrucciones enseñan vista previa → el sí del organizador → aplicar para un formato, unos grupos o un cuadro, y leer el partido → cargar → mostrar qué cambió para un resultado. El Agent Skill setto-api (1.6.0, con «Armar grupos / cuadro» y «Cargar resultados» en references/workflows.md) y el plugin de Claude Code (1.5.0) lo acompañan. Consulta Servidor MCP.

2026-11 — Configura torneos con IA

Aditivo. Los tokens, las lecturas y la escritura de programación existentes siguen funcionando igual.

  • Diecisiete operaciones nuevas, 27 en total. Con el permiso manage («Gestionar torneos»): crear un torneo en borrador con el plan gratis, con sus categorías (createTournament); editarlo, publicarlo, regresarlo a borrador, archivarlo o restaurarlo (updateTournament, publishTournament, setTournamentLifecycle); agregar, editar y borrar categorías y fijar sus cabezas de serie (createDivision, updateDivision, deleteDivision, setDivisionSeeds); inscribir un equipo o hasta 50 sin enviar correos (registerTeam, registerTeams); editar o borrar un equipo y editar un jugador (updateTeam, deleteTeam, updatePlayer); sustituir a un jugador («Sustitución», substitutePlayer); y dar de baja a un equipo («Baja», withdrawTeam). Con read: encontrar categorías, rondas, grupos, equipos y jugadores por nombre (searchTournament) y ver la vista previa de una baja partido por partido (previewTeamWithdrawal, que no escribe nada). Consulta la referencia de la API.
  • Una baja se previsualiza y luego se confirma. La vista previa contesta un confirmationToken válido 15 minutos para ese equipo y ese plan; withdrawTeam aplica exactamente ese plan, o contesta 409 PREVIEW_STALE si el torneo cambió en medio.
  • Un reintento nunca escribe dos veces. Las creaciones y las operaciones de equipo aceptan un encabezado opcional Idempotency-Key: la misma llave con el mismo cuerpo contesta el primer resultado durante 24 horas.
  • listTournaments busca por nombre con q (sin importar acentos ni mayúsculas) y contesta la consulta normalizada en query. Las rondas llevan un label en español e inglés, los lugares del cuadro un labelEs en español, y un equipo withdrawn.
  • Códigos de rechazo nuevos para las escrituras de configuración (DIVISION_LIMIT_REACHED, DIVISION_FULL, TEAM_HAS_GAMES, PREVIEW_STALE, TOURNAMENT_BUSY, TOURNAMENT_CREATE_DAILY_CAP, …), cada uno con details. Un organizador crea a lo mucho 20 torneos al día por la API. Ninguna escritura cambia ningún precio, marca de pago, registro de pago ni reembolso (una baja cierra los enlaces de pago sin pagar del equipo); cada escritura, y cada rechazo, queda en la «Actividad». Consulta Errores.
  • El servidor MCP (1.4.0) suma search_tournament y las dieciséis herramientas de configuración, explica en español cada advertencia y cada partido de una baja (mensaje), y sus instrucciones enseñan vista previa → el sí del organizador → aplicar. El Agent Skill setto-api (1.5.0, con un references/workflows.md nuevo) y el plugin de Claude Code (1.4.0) lo acompañan. Consulta Servidor MCP.

2026-11 — Inicio de sesión con OAuth, permisos y «Actividad»

Aditivo. Los tokens y las integraciones existentes siguen funcionando igual.

  • Entrar con tu cuenta de SETTO. La api de SETTO ahora es su propio servidor de autorización OAuth 2.1, así que claude.ai, ChatGPT, Codex y Claude Code se conectan al servidor MCP sin token: el organizador aprueba la aplicación en una pantalla de consentimiento en app.setto.io. El token de acceso de la aplicación es un token de API (setto_live_…) que actúa como ese organizador, así que esta API también lo acepta. Nunca aparece en «Tokens de API»; «Conexiones» muestra la aplicación y la desconecta. Consulta Entrar con tu cuenta de SETTO.
  • Seis permisos («Permisos»). A read y schedule se suman manage, results, landing y communications, que ya se pueden dar y quedan reservados para las próximas escrituras: ninguna ruta los usa todavía. Un token de organización conserva cualquier permiso además de read solo mientras el ADMIN que lo creó siga siéndolo (hasta ahora esa regla solo cubría schedule). Consulta Qué puede cambiar un token.
  • GET /v1/external/activity (listActivity, etiqueta Activity, basta con read) — la «Actividad»: las escrituras que las aplicaciones y los tokens hicieron en los torneos que alcanza el token, de la más reciente a la más antigua, con quién actuó, con qué aplicación o token, y el resultado. Se pagina con cursor y nextCursor (limit de 1 a 50, 20 por defecto); un cursor que no se puede decodificar es 400 INVALID_CURSOR.
  • GET /v1/external/me suma actingAs (el organizador como el que actúa cada llamada), app (la aplicación conectada, null para un token de API) y token.origin (manual u oauth).
  • El servidor MCP (1.3.0) acepta el inicio de sesión, declara las cuatro pistas en cada herramienta, nombra el «Permiso» que falta para cada tipo de credencial y suma list_activity. El Agent Skill setto-api (1.4.0) y el plugin de Claude Code (1.3.0) lo acompañan. Consulta Servidor MCP.

2026-11 — Tokens de API personales

Aditivo para los tokens existentes. Los tokens de organización funcionan exactamente igual que antes; todo lo de abajo es nuevo.

  • Tokens personales («Token personal»). Cualquier usuario de SETTO puede tener hasta 10 tokens personales activos, creados en app.setto.io → Configuración → Tokens de API con el alcance en Personal. Un token personal alcanza todos los torneos que su dueño administra en el momento de cada petición — incluidos los personales — y puede llevar schedule, que entonces escribe la programación de cualquiera de esos torneos. Consulta Dos tipos de token.
  • Los tokens de organización («Token de la organización») ahora se crean en el mismo lugar, con la organización como alcance; la página de la organización, pestaña API, los sigue mostrando. Su alcance, sus scopes y la revisión de ADMIN no cambian.
  • GET /v1/external/me suma owner (type, idx, name): type es user para un token personal y organization para uno de organización. organization es null solo para un token personal.
  • La organization de un torneo no cambia con un token de organización (la organización del token). Con un token personal es la organización principal del torneo, o null para un torneo personal: maneja null antes de apuntar una integración a un token personal.
  • El servidor MCP (1.2.0) acepta tokens personales, indica la solución de INSUFFICIENT_SCOPE para cada tipo de token y suma una configuración para Claude Desktop con mcp-remote. Consulta Servidor MCP.

2026-11 — Programación: la primera escritura

Aditivo. Tres operaciones bajo una etiqueta nueva, Scheduling, y un segundo scope de token:

  • GET /v1/external/tournaments/{idx}/schedule (getTournamentSchedule) — canchas, categorías, todos los partidos con su inicio, duración, cancha y la marca locked, y las peticiones de horario aprobadas de los equipos.
  • POST /v1/external/tournaments/{idx}/schedule/proposals (proposePoolPerCourtSchedule) — planea un día «un grupo por cancha» y devuelve los partidos colocados, los que no se pudieron colocar y las peticiones no cumplidas. No guarda nada; basta con read.
  • POST /v1/external/tournaments/{idx}/schedule/placements (applySchedulePlacements) — escribe el inicio, la cancha y la duración de los partidos indicados, todo o nada. Un rechazo lista cada partido en conflicto en details (409 SCHEDULE_CONFLICT, 409 GAME_LOCKED, …).
  • Los tokens ahora pueden llevar schedule además de read: un token de organización que crea un ADMIN de la organización marcando «Permitir programar partidos» (y, desde los tokens personales, un token personal creado con ese permiso). Los tokens existentes conservan solo read. Sin schedule, la ruta de placements responde 403 INSUFFICIENT_SCOPE.
  • El servidor MCP suma get_schedule, propose_pool_per_court_schedule y apply_schedule_placements, y se instala desde un plugin de Claude Code, un enlace «Agregar a Cursor» o uno «Agregar a VS Code». Consulta Servidor MCP.

2026-10-02 — whoCanSubmit: ANYONE

Aditivo. tournament.whoCanSubmit suma un tercer miembro, ANYONE, junto a ADMINS_ONLY y PLAYERS: el organizador permite que cualquier persona con el link público del torneo cargue resultados, haya iniciado sesión o no. Los resultados siguen resultApprovalMode (ADMIN retiene cada uno para que el organizador lo revise). Una integración que deja pasar los valores de enum que no ha visto no necesita cambios.

1.1.0 — 2026-09-19

El fútbol se suma al pádel, el tenis y el pickleball. Todo lo de esta versión es aditivo: ningún campo existente cambió de tipo ni de significado, y una integración que ya ignora los campos que no reconoce y deja pasar los valores de enum que no ha visto no necesita ningún cambio.

  • FUTBOL se suma al enum sport, junto a PADEL, TENNIS y PICKLEBALL. Un torneo de fútbol siempre inscribe equipos (un capitán registra al equipo), siempre es type: TOURNAMENT y nunca forma parte de un circuito.
  • tournament.sportSettings — un objeto nuevo, presente en los torneos FUTBOL y null en los deportes de raqueta: modality (F5, F7, F9, F11 o FUTSAL), extraTime, matchMinutes, h2hRequiresCompleteSubset, forfeitScore y fairPlayWeights.
  • Tres campos nuevos en score, todos null en los deportes de raqueta: extraTime ({ home, away } — goles marcados durante el tiempo extra, no acumulados: súmalos a score.home / score.away para el total tras el tiempo extra), penalties ({ home, away } — penales convertidos en la tanda; los penales nunca son goles ni entran en la tabla de posiciones) y decisionMethod (REGULATION, EXTRA_TIME, SHOOTOUT o WALKOVER, donde WALKOVER es una incomparecencia). En un juego de fútbol también se leen null hasta que el juego se haya ido a tiempo extra, a penales o tenga un resultado oficial — null es el caso normal, no un error.
  • En FUTBOL, score.sets lleva exactamente un elemento — el marcador al tiempo reglamentario, cuyos home y away son iguales a score.home y score.away, con isTieBreak siempre en false. Ese único set es lo que mantiene funcionando sin cambios a quien ya consume sets.
  • Un juego de fútbol puede terminar en empate. Los juegos de grupo y de liga se quedan sin ganador cuando terminan igualados. Un empate en eliminatorias se va a tiempo extra (una opción que el organizador activa por torneo) y luego a penales; el ganador se deriva en el servidor.
  • GOALS_FOR, GOALS_AGAINST y GOAL_DIFFERENCE se suman al enum standingColumns, para las tablas de fútbol. Los torneos de raqueta conservan exactamente las columnas que ya tenían.
  • H2HL, un criterio de desempate nuevo — la mini-liga entre empatados: puntos, luego diferencia de goles y luego goles a favor, contando solo los juegos entre los equipos empatados. Se omite cuando los equipos empatados no se han enfrentado todos entre sí, a menos que el organizador desactive sportSettings.h2hRequiresCompleteSubset. Te llega como un acronym dentro de rankedTiebreakRules.
  • En fútbol, teamStats cuenta goles. pointsFor, pointsAgainst y pointsDifference llevan goles a favor, goles en contra y diferencia de goles; setsPointsFor, setsPointsAgainst y setsPointsDifference no se escriben para FUTBOL y se quedan en 0. Su significado en los deportes de raqueta no cambia.

2026-09-17 — Host canónico api.setto.io

La API externa ahora responde en https://api.setto.io, que es la URL base que usan todos los ejemplos de esta documentación, el documento OpenAPI y el Agent Skill (1.0.1). El host generado por Railway al que reemplazó (https://api-production-ea80.up.railway.app) sigue respondiendo para las integraciones existentes, pero las nuevas deben usar api.setto.io. Las rutas, la autenticación y las respuestas no cambian — no es un cambio rompedor.

1.0.0 — 2026-09

Primera versión pública.

  • Seis endpoints de solo lectura, todos bajo /v1/external/: getMe, listTournaments, getTournament, listDivisions, listTeams, getRound.
  • Tokens de API de organización. Los crea el creador de la organización o un miembro ADMIN (hoy en app.setto.io → Configuración → Tokens de API). Se muestran una vez, son de solo lectura, revocables, con expiración opcional de 30/90/365 días y un máximo de 10 tokens activos por organización.
  • Autenticación bearer con los prefijos setto_live_ (producción) y setto_test_ (no productivo), y los códigos de error MISSING_API_TOKEN, INVALID_API_TOKEN, EXPIRED_API_TOKEN e INSUFFICIENT_SCOPE.
  • Alcance por organización. Un token lee únicamente los torneos que su organización posee; todo lo demás — incluidos los datos de otra organización y los torneos personales — responde 404, nunca 403, para que los ids no se puedan sondear. (Desde 2026-11, un token personal alcanza los torneos personales de su dueño.)
  • populate, una lista de relaciones separada por comas y con lista blanca por endpoint, con expansión implícita de los padres y valores por defecto por endpoint. Los valores desconocidos son un 400.
  • Paginación por offset en listTournaments: limit de 1..100 (por defecto 25), offset, y un sobre meta con limit, offset y total. Las filas se ordenan por startDate descendente.
  • Límite de uso de 120 peticiones por 60 segundos por token, con X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset en cada respuesta y Retry-After en un 429.
  • Peticiones condicionales. ETag fuerte más If-None-Match devuelve 304 Not Modified, así que sondear una ronda cuesta casi nada.
  • Una proyección segura para la privacidad. Sin correos, teléfonos ni redes sociales; sin datos de pago ni facturación. Los objetos de jugador llevan solo idx, firstName, lastName y avatar.
  • El material oculto y en borrador se devuelve marcado, no filtrado — isVisible: false en categorías y rondas, y torneos DRAFT/ARCHIVED en listTournaments.
  • Este sitio de documentación, con una referencia generada y un playground Try it, un /openapi.json publicado, una versión Markdown de cada página, /llms.txt y /llms-full.txt, un servidor MCP remoto y un Agent Skill.

En esta página