SETTO API

Autenticación

Cómo funcionan los tokens de API de SETTO — tokens personales y de organización, la cabecera bearer, los prefijos live y test, los seis permisos, qué alcanza cada token, expiración, rotación y revocación, y la diferencia entre 401 y 403.

Cada petición a la API externa lleva una sola credencial: un token de API de SETTO, enviado en la cabecera Authorization como bearer token. Un token es personal — te pertenece y alcanza todos los torneos que administras — o de una organización — le pertenece a una organización y solo alcanza sus torneos. Los tokens se crean en el panel de organizador de SETTO, por defecto solo leen y se muestran completos exactamente una vez. Esta página cubre los dos tipos de token, el formato de la cabecera, los dos prefijos de token, qué puede y qué no puede ver un token, los seis permisos que puede llevar, y cómo rotarlo o revocarlo.

¿Vas a conectar un asistente de IA?

claude.ai, ChatGPT, Codex y Claude Code pueden saltarse el token: inician sesión con tu cuenta de SETTO y obtienen su propio token de acceso, que también es un token de API (misma cabecera, mismo prefijo) y actúa como tú. Consulta Entrar con tu cuenta de SETTO.

La cabecera

GET /v1/external/tournaments HTTP/1.1
Host: api.setto.io
Authorization: Bearer setto_live_YOUR_TOKEN_HERE

No hay alternativa. La API no acepta un token en la query string, en una cookie ni en una cabecera X-Api-Key — solo Authorization: Bearer. Una cabecera ausente o mal formada es un 401, nunca una lectura anónima silenciosa.

Formato del token

Un token es un prefijo más un secreto. Los primeros 16 caracteres son el prefijo, que SETTO guarda en claro para que el panel pueda mostrarte cuál token es cuál; el resto es el secreto, que SETTO guarda solo como hash.

PrefijoSignificado
setto_live_…Token de producción. Funciona contra la API de producción.
setto_test_…Token no productivo. La API de producción lo rechaza.

Usa tokens setto_test_ cuando apuntes una integración a una API de SETTO de staging o local; usa setto_live_ para cualquier cosa real. Ambos llevan los mismos scopes.

El prefix es lo que ves en todos los lugares donde el token se muestra — en la lista del panel y en el campo token.prefix de GET /v1/external/me. Registra el prefijo cuando necesites distinguir dos tokens. Nunca registres el token completo.

Dos tipos de token

Token personal («Token personal»)Token de organización («Token de la organización»)
DueñoTúUna organización
Dónde se creaConfiguración → Tokens de API, con Personal en el selectorConfiguración → Tokens de API con la organización en el selector, o la página de la organización, pestaña API
Quién puede crearloCualquier usuario de SETTO, para sí mismoEl creador de la organización o un miembro con el rol ADMIN
Qué leeTodos los torneos que administras hoy: los que creaste (incluidos los personales), los que aceptaste administrar por invitación y los de cada organización a la que perteneces, incluidos los compartidos con ellaLos torneos de la organización, incluidos los compartidos con ella
Límite10 tokens activos por usuario10 tokens activos por organización
Cuando cambia el accesoSi dejas una organización o pierdes una invitación, la siguiente petición a esos torneos es un 404Sigue leyendo; cada permiso aparte de read deja de funcionar en cuanto quien lo creó ya no es ADMIN de la organización
GET /v1/external/meowner.type: "user", organization: nullowner.type: "organization", organization lleno

Cuál usar

  • Un token de organización para sistemas que son de la organización: la web del club, una sincronización, un asistente que comparten varias personas. No alcanza nada fuera de la organización y sigue leyendo aunque la gente entre y salga.
  • Un token personal para tu propio asistente (Claude Code, Codex, Cursor, VS Code — mira el servidor MCP) o un script que corres tú. Alcanza todo lo que administras y sigue tu acceso cuando cambia.
  • Ningún token para claude.ai, ChatGPT, Codex o Claude Code: pueden entrar con tu cuenta de SETTO y actuar como tú, con los permisos que apruebes.

Crear un token

En app.setto.io abre Configuración → Tokens de API. El selector de cuenta u organización, arriba de Configuración, decide de quién es el token: déjalo en Personal para un token personal, o elige una organización para un token de organización. Luego elige Crear token.

  • Cualquiera puede crear tokens personales para sí mismo, y solo esa persona los ve — ni siquiera los ADMIN de sus organizaciones.
  • Solo el creador de la organización o un miembro con el rol ADMIN puede crear, listar o revocar los tokens de una organización. Los demás miembros reciben un 403 de los endpoints de gestión; el panel se los indica. La página de la organización, pestaña API, muestra los mismos tokens.
  • El nombre es obligatorio. Nombra los tokens según quién los consume (Club website, Claude Desktop), no según una persona.
  • En Permisos, «Leer» siempre va marcado; marca cualquier otro permiso que necesite quien lo consume (mira Qué puede cambiar un token).
  • La expiración es opcional: nunca, 30, 90 o 365 días. Un token expirado devuelve 401 con EXPIRED_API_TOKEN.
  • Un usuario puede tener como máximo 10 tokens personales activos, y una organización como máximo 10 tokens de organización activos; son límites separados. Revoca uno antes de crear el número once.

Copia el secreto de inmediato

El token completo aparece una sola vez, en el diálogo posterior a la creación. SETTO conserva solo un hash, así que nadie — ni tú, ni el soporte de SETTO — puede recuperarlo después. Si se pierde, revoca y vuelve a crear.

Qué puede cambiar un token

Un token lleva uno o más de seis permisos, sus scopes. Todo token lleva read, y es todo lo que la mayoría necesita. Los demás los marcas en Permisos al crear el token; la lista de tokens muestra una insignia por cada uno que lleva (schedule dice «Programa partidos»).

PermisoScopeQué permiteRutas de la API hoy
«Leer»readVer torneos, categorías, equipos, resultados, horarios y la actividad. Siempre incluidoTodos los GET, la propuesta de programación y las vistas previas (no escriben nada)
«Programar partidos»scheduleAsignar y mover el día, la hora y la cancha de los partidos que no se han jugadoPOST /v1/external/tournaments/{idx}/schedule/placements
«Gestionar torneos»manageCrear y editar torneos, categorías, cabezas de serie, equipos y jugadores; inscribir equipos; sustituir a un jugador («Sustitución») o dar de baja a un equipo («Baja»); fijar el formato de una categoría, sus grupos y su cuadroPOST /v1/external/tournaments y las demás escrituras de configuración y de cuadros (referencia)
«Cargar resultados»resultsRegistrar, corregir y borrar resultados de partidosPOST y DELETE /v1/external/tournaments/{idx}/games/{gameIdx}/result
«Página pública»landingCambiar el diseño, las secciones, los patrocinadores y la visibilidad de la página públicaNinguna todavía
«Enviar comunicaciones»communicationsEnviar correos a los participantes de tus torneosNinguna todavía

Hoy la API escribe tres tipos de cosas: la configuración de torneos (crear y editar torneos y sus categorías, inscribir y editar equipos y jugadores, «Sustitución», «Baja») y sus cuadros (el formato de una categoría, sus grupos, sus eliminatorias y «Confirmar cuadro»), que requieren manage; los resultados de los partidos, que requieren results; y la hora de inicio, la cancha y la duración de los partidos de un torneo, que requiere schedule. Los otros dos permisos ya se pueden otorgar y están reservados para las escrituras que vienen; un token que solo lleva esos no puede hacer más que leer. Ningún permiso cambia ningún precio, marca de pago, registro de pago ni reembolso; una baja cierra los enlaces de pago sin pagar del equipo. Un token sin el permiso que una ruta necesita recibe 403 INSUFFICIENT_SCOPE. GET /v1/external/me lista los scopes de un token.

Además, cada permiso está limitado por lo que la persona detrás del token puede hacer en el panel, y quién es esa persona depende del tipo de token:

  • un token personal escribe en cualquier torneo que su dueño administre en el momento de la petición;
  • un token de organización con cualquier permiso aparte de read solo lo puede crear un ADMIN de la organización, y escribe solo mientras esa persona siga siendo ADMIN de la organización. Cuando deja de serlo, la escritura es 403 INSUFFICIENT_SCOPE, y un ADMIN actual crea un token nuevo;
  • un token de acceso de OAuth — el que obtienen claude.ai, ChatGPT, Codex o Claude Code cuando entras con tu cuenta de SETTO — actúa como tú, con los permisos que aprobaste en la pantalla de consentimiento.

Qué puede ver un token

Qué torneos alcanza un token depende de su tipo:

  • un token personal alcanza todos los torneos que su dueño administra en el momento de la petición — los que creó (incluidos los personales), los que aceptó administrar por invitación y los de cada organización a la que pertenece, incluidos los compartidos con ella. Se calcula de nuevo en cada petición: si dejas una organización, sus torneos responden 404 en la siguiente llamada;
  • un token de organización alcanza los torneos cuya organización principal es esa organización, más los compartidos con ella.

De cada torneo que alcanza, un token lee:

  • el torneo — incluidos los que están en DRAFT y ARCHIVED, y los torneos cuya página pública está apagada (isPublic: false);
  • las categorías, equipos, rondas, grupos, cuadros, partidos, marcadores y clasificaciones que cuelgan de esos torneos — incluidos los marcados con isVisible: false.

La organization de un torneo dice dónde vive. Con un token de organización es siempre la organización del token. Con un token personal es la organización principal del torneo, o null para un torneo personal.

Ningún token lee:

  • datos de otras organizaciones con un token de organización, aunque quien lo creó sea miembro de ambas. Un token de organización, una organización;
  • datos personales de contacto — correos, teléfonos, redes sociales y similares se eliminan de todas las respuestas;
  • datos de pago o facturación — cuotas de inscripción pagadas, métodos de pago, identificadores de Stripe y notas del organizador no forman parte del contrato.

Como el material oculto y en borrador sí se devuelve, trata el payload como interno hasta que lo filtres. Si estás renderizando una página pública, filtra tú mismo por status y por isVisible.

Mantén los tokens del lado del servidor

Un token setto_live_ da acceso de lectura a todo lo que alcanza: una organización entera o — si es personal — todos los torneos que administras. Su lugar es una variable de entorno del servidor, un gestor de secretos o una función serverless — nunca un bundle del navegador, una app móvil, un repositorio público o una URL.

Si necesitas datos de torneo en el navegador, pon una pequeña ruta de servidor delante de la API:

app/api/standings/route.ts
export async function GET() {
  const res = await fetch(
    'https://api.setto.io/v1/external/rounds/9d3c6a84-7e15-4b02-8f6d-1c4a9e7b53f2',
    {
      // SETTO_API_TOKEN es solo de servidor. Nunca le pongas el prefijo NEXT_PUBLIC_.
      headers: { Authorization: `Bearer ${process.env.SETTO_API_TOKEN}` },
      next: { revalidate: 60 },
    },
  );

  // Revisa el STATUS antes que el cuerpo. Un payload de error no trae
  // `isVisible` ni `pools`, así que proyectarlo respondería 200 con un
  // resultado vacío y escondería un token expirado detrás de "esta ronda no
  // tiene clasificaciones".
  if (res.status === 404) {
    return new Response('Not found', { status: 404 });
  }

  if (!res.ok) {
    // El problema de tu credencial no es el de tu visitante. Registra el
    // detalle y devuelve un fallo genérico — nunca reenvíes el cuerpo ni el
    // status de arriba.
    console.error(`SETTO API ${res.status} al cargar la clasificación`);
    return Response.json(
      { error: 'upstream_unavailable' },
      { status: 502 },
    );
  }

  const round = await res.json();

  // Tu token ve material oculto y en borrador; esta ruta no pide ninguno, así
  // que todo lo que devuelvas aquí es público. Una ronda oculta responde 404
  // igual que una inexistente — nunca confirmes que existe.
  if (round.isVisible === false) {
    return new Response('Not found', { status: 404 });
  }

  // ...y luego publica una proyección explícita en lugar del payload de arriba,
  // para que un campo que la API agregue después no se filtre por defecto.
  return Response.json({
    name: round.name,
    pools: (round.pools ?? []).map((pool) => ({
      name: pool.name,
      standings: (pool.standings ?? []).map((row) => ({
        rank: row.rank,
        team: row.team?.name,
        points: row.awardedPoints,
      })),
    })),
  });
}

Cachea la proyección, nunca la respuesta de arriba — un payload completo cacheado es una filtración esperando a la siguiente persona que lo reutilice.

La misma regla aplica al panel Try it de la referencia: dispara la petición desde tu propio navegador, así que pega un token desechable o que vayas a rotar pronto en lugar del de producción.

Rotación y revocación

Los tokens no se rotan solos. Para rotar:

  1. Crea un segundo token con la misma intención (Website widget (new)).
  2. Despliega el nuevo valor en el consumidor.
  3. Confirma que el tráfico se movió — token.lastUsedAt del token nuevo empieza a avanzar.
  4. Revoca el token viejo en Configuración → Tokens de API, con el selector en la cuenta u organización donde lo creaste.

La revocación surte efecto de inmediato: la siguiente petición con ese token es un 401 con INVALID_API_TOKEN. Si un token se filtra, revoca primero y pregunta después — nada de la API tiene estado, así que un token revocado y reemplazado no te cuesta más que un redeploy.

Rota con calendario si puedes, y siempre que alguien con acceso se vaya.

401 contra 403

Significan cosas distintas y piden respuestas distintas.

EstadoCódigosQué pasóQué hacer
401MISSING_API_TOKENNo hay cabecera Authorization, o no era Bearer setto_…Corrige la petición
401INVALID_API_TOKENToken desconocido, revocado o de otro entorno (un setto_test_ en producción)Vuelve a emitir el token
401EXPIRED_API_TOKENEl expiresAt del token ya pasóCrea un token nuevo
403INSUFFICIENT_SCOPEEl token es válido pero no lleva el permiso que la ruta necesita (o, en un token de organización, quien lo creó ya no es ADMIN)No reintentes

En corto: 401 significa no sabemos quién eres — detente y consigue una credencial que funcione. 403 significa sabemos exactamente quién eres y la respuesta sigue siendo no — reintentar con el mismo token nunca va a funcionar.

Un token de acceso de OAuth responde 401 en cuanto su aplicación se desconecta en Configuración → Conexiones o se cumplen sus 30 días; la aplicación lo renueva o te pide iniciar sesión otra vez. Su 403 INSUFFICIENT_SCOPE se arregla conectando la aplicación otra vez y marcando el permiso que faltaba.

Un recurso que este token no alcanza — de otra organización, o un torneo que ya no administras — no es un 403. Es un 404 (TOURNAMENT_NOT_FOUND / ROUND_NOT_FOUND), idéntico a la respuesta para un id que no existe en ningún lado — la API nunca confirma la existencia de datos que no tienes permitido leer. Consulta Errores.

En esta página