Documentación de la API de Vestigio

API REST para acceder a rankings de rutas y datos de atletas de Vestigio

v1.0 URL base: https://vestigio.app

Descripción general

La API de Vestigio ofrece acceso programático a rankings de rutas, datos de intentos e información de atletas. Todos los endpoints devuelven respuestas JSON y siguen convenciones REST.

Autenticación

Por ahora los endpoints de la API son de acceso público. Versiones futuras podrían requerir claves de API o autenticación OAuth.

GET /api/ranking

Devuelve el ranking completo de una ruta específica, con el detalle de todos los intentos y la información del atleta.

Parámetros de consulta

Parámetro Tipo Obligatorio Descripción
id string El GUID de la ruta (no el ID numérico)

Ejemplo de solicitud

GET /api/ranking?id=abc123-def456-ghi789

Respuesta

Devuelve un objeto JSON con la información de la ruta y un arreglo de entradas del ranking.

Respuesta exitosa (200 OK)
{
  "route": {
    "id": 1,
    "name": "Cerro San Cristóbal",
    "description": "Ruta desde Plaza Italia hasta la cumbre",
    "meters": 3500,
    "minutes": 45,
    "city": "Santiago",
    "country": "Chile",
    "guid": "abc123-def456-ghi789"
  },
  "ranking": [
    {
      "trialId": 123,
      "seconds": 1845,
      "timeFormatted": "00:30:45",
      "startMillis": 1704067200000,
      "endMillis": 1704069045000,
      "daysOld": 5,
      "valid": true,
      "suspicious": false,
      "discipline": "Running",
      "user": {
        "id": 45,
        "guid": "user-guid-123",
        "email": "athlete@example.com",
        "publicName": "John Doe",
        "alias": "SpeedRunner",
        "gender": 1,
        "age": 28,
        "city": "Santiago",
        "country": "Chile",
        "instagram": "@speedrunner"
      },
      "startLocation": {
        "id": 10,
        "name": "Plaza Italia",
        "latLong": "-33.4378,-70.6504",
        "city": "Santiago",
        "country": "Chile"
      },
      "endLocation": {
        "id": 11,
        "name": "Cerro San Cristóbal",
        "latLong": "-33.4245,-70.6389",
        "city": "Santiago",
        "country": "Chile"
      }
    }
  ]
}
Respuestas de error
400 Bad Request

Falta un parámetro obligatorio

{
  "error": "Missing routeId parameter"
}
404 Not Found

Ruta no encontrada

{
  "error": "Route not found for id=abc123-def456-ghi789"
}

Esquema de respuesta

Objeto raíz
  • route (object) - Información de la ruta
  • ranking (array) - Arreglo de entradas de intento/ranking, ordenadas por tiempo (el más rápido primero)
Objeto Route
  • id (number) - ID numérico de la ruta
  • name (string) - Nombre de la ruta
  • description (string) - Descripción de la ruta
  • meters (number) - Distancia de la ruta en metros
  • minutes (number) - Tiempo estimado en minutos
  • city (string) - Ciudad donde está la ruta
  • country (string) - País donde está la ruta
  • guid (string) - Identificador único de la ruta (úsalo en las llamadas a la API)
Objeto de entrada del ranking
  • trialId (number) - ID del intento
  • seconds (number) - Tiempo transcurrido en segundos
  • timeFormatted (string) - Tiempo formateado (HH:MM:SS)
  • startMillis (number) - Marca de tiempo de inicio en milisegundos
  • endMillis (number) - Marca de tiempo de fin en milisegundos
  • daysOld (number) - Días desde que se completó el intento
  • valid (boolean) - Si el intento es válido
  • suspicious (boolean) - Si el intento está marcado como sospechoso
  • discipline (string|null) - Nombre de la disciplina (p. ej., "Running", "Cycling")
  • user (object|null) - Información del atleta/usuario
  • startLocation (object|null) - Detalles del punto de inicio
  • endLocation (object|null) - Detalles del punto de meta
Objeto User
  • id (number) - ID numérico del usuario
  • guid (string) - Identificador único del usuario
  • email (string) - Correo electrónico del usuario
  • publicName (string) - Nombre público (alias o prefijo del email)
  • alias (string|null) - Alias/nombre de usuario
  • gender (number) - Género (0 = mujer, 1 = hombre)
  • age (number) - Edad del usuario
  • city (string|null) - Ciudad del usuario
  • country (string|null) - País del usuario
  • instagram (string|null) - Usuario de Instagram
Objeto Location
  • id (number) - ID numérico de la ubicación
  • name (string) - Nombre de la ubicación
  • latLong (string) - Coordenadas en formato "lat,lng"
  • city (string|null) - Ciudad
  • country (string|null) - País

Notas

  • El ranking está ordenado por tiempo (el más rápido primero)
  • Solo se incluyen intentos de los últimos 10 años
  • Se devuelven como máximo 1000 resultados
  • Usa el guid de la ruta (no el id numérico) en las llamadas a la API
  • Las marcas de tiempo están en milisegundos desde el epoch Unix
GET /api/trials

Devuelve los últimos 1000 intentos de un usuario/atleta específico, con el detalle de cada intento y la información de la ruta.

Parámetros de consulta

Parámetro Tipo Obligatorio Descripción
id string El GUID del usuario/atleta

Ejemplo de solicitud

GET /api/trials?id=user-guid-123-456-789

Respuesta

Devuelve un objeto JSON con la información del usuario y un arreglo de sus intentos.

Respuesta exitosa (200 OK)
{
  "user": {
    "id": 45,
    "guid": "user-guid-123-456-789",
    "email": "athlete@example.com",
    "publicName": "John Doe",
    "alias": "SpeedRunner",
    "gender": 1,
    "age": 28,
    "city": "Santiago",
    "country": "Chile",
    "instagram": "@speedrunner"
  },
  "trials": [
    {
      "trialId": 123,
      "seconds": 1845,
      "timeFormatted": "00:30:45",
      "startMillis": 1704067200000,
      "endMillis": 1704069045000,
      "daysOld": 5,
      "valid": true,
      "suspicious": false,
      "discipline": "Running",
      "comments": "Great run today!",
      "route": {
        "id": 1,
        "guid": "route-guid-abc-123",
        "name": "Cerro San Cristóbal",
        "description": "Ruta desde Plaza Italia hasta la cumbre",
        "meters": 3500,
        "minutes": 45,
        "city": "Santiago",
        "country": "Chile"
      },
      "startLocation": {
        "id": 10,
        "name": "Plaza Italia",
        "latLong": "-33.4378,-70.6504",
        "city": "Santiago",
        "country": "Chile"
      },
      "endLocation": {
        "id": 11,
        "name": "Cerro San Cristóbal",
        "latLong": "-33.4245,-70.6389",
        "city": "Santiago",
        "country": "Chile"
      }
    }
  ]
}
Respuestas de error
400 Bad Request

Falta un parámetro obligatorio

{
  "error": "Missing user id parameter"
}
404 Not Found

Usuario no encontrado

{
  "error": "User not found for id=user-guid-123-456-789"
}

Esquema de respuesta

Objeto raíz
  • user (object) - Información del usuario/atleta
  • trials (array) - Arreglo de entradas de intento, ordenadas de más reciente a más antiguo
Objeto User
  • id (number) - ID numérico del usuario
  • guid (string) - Identificador único del usuario
  • email (string) - Correo electrónico del usuario
  • publicName (string) - Nombre público (alias o prefijo del email)
  • alias (string|null) - Alias/nombre de usuario
  • gender (number) - Género (0 = mujer, 1 = hombre)
  • age (number) - Edad del usuario
  • city (string|null) - Ciudad del usuario
  • country (string|null) - País del usuario
  • instagram (string|null) - Usuario de Instagram
Objeto de entrada de intento
  • trialId (number) - ID del intento
  • seconds (number) - Tiempo transcurrido en segundos
  • timeFormatted (string) - Tiempo formateado (HH:MM:SS)
  • startMillis (number) - Marca de tiempo de inicio en milisegundos
  • endMillis (number) - Marca de tiempo de fin en milisegundos
  • daysOld (number) - Días desde que se completó el intento
  • valid (boolean) - Si el intento es válido
  • suspicious (boolean) - Si el intento está marcado como sospechoso
  • discipline (string|null) - Nombre de la disciplina (p. ej., "Running", "Cycling")
  • comments (string|null) - Comentarios del usuario sobre el intento
  • route (object|null) - Información de la ruta
  • startLocation (object|null) - Detalles del punto de inicio
  • endLocation (object|null) - Detalles del punto de meta
Objeto Route
  • id (number) - ID numérico de la ruta
  • guid (string) - Identificador único de la ruta
  • name (string) - Nombre de la ruta
  • description (string) - Descripción de la ruta
  • meters (number) - Distancia de la ruta en metros
  • minutes (number) - Tiempo estimado en minutos
  • city (string|null) - Ciudad donde está la ruta
  • country (string|null) - País donde está la ruta
Objeto Location
  • id (number) - ID numérico de la ubicación
  • name (string) - Nombre de la ubicación
  • latLong (string) - Coordenadas en formato "lat,lng"
  • city (string|null) - Ciudad
  • country (string|null) - País

Notas

  • Los intentos están ordenados por hora de fin (el más reciente primero)
  • Solo se incluyen intentos completados (con hora de fin)
  • Se devuelven como máximo 1000 resultados
  • Usa el guid del usuario (no el id numérico) en las llamadas a la API
  • Las marcas de tiempo están en milisegundos desde el epoch Unix
GET /api/routeStats

Devuelve estadísticas completas de una ruta específica, incluyendo análisis de tiempos, percentiles, desglose por género y más.

Parámetros de consulta

Parámetro Tipo Obligatorio Descripción
id string El GUID de la ruta (no el ID numérico)

Ejemplo de solicitud

GET /api/routeStats?id=abc123-def456-ghi789

Respuesta

Devuelve un objeto JSON con la información de la ruta y estadísticas completas.

Respuesta exitosa (200 OK)
{
  "route": {
    "id": 1,
    "guid": "abc123-def456-ghi789",
    "name": "Cerro San Cristóbal",
    "description": "Ruta desde Plaza Italia hasta la cumbre",
    "meters": 3500,
    "city": "Santiago",
    "country": "Chile"
  },
  "statistics": {
    "totalTrials": 150,
    "uniqueAthletes": 85,
    "times": {
      "best": {
        "seconds": 1245,
        "formatted": "00:20:45"
      },
      "worst": {
        "seconds": 5400,
        "formatted": "01:30:00"
      },
      "mean": {
        "seconds": 2100,
        "formatted": "00:35:00"
      },
      "median": {
        "seconds": 1980,
        "formatted": "00:33:00"
      },
      "standardDeviation": 650.5
    },
    "percentiles": {
      "p10": {
        "seconds": 1350,
        "formatted": "00:22:30"
      },
      "p25": {
        "seconds": 1620,
        "formatted": "00:27:00"
      },
      "p50": {
        "seconds": 1980,
        "formatted": "00:33:00"
      },
      "p75": {
        "seconds": 2520,
        "formatted": "00:42:00"
      },
      "p90": {
        "seconds": 3240,
        "formatted": "00:54:00"
      }
    },
    "gender": {
      "male": {
        "count": 100,
        "uniqueAthletes": 60,
        "best": 1245,
        "mean": 2000,
        "median": 1900
      },
      "female": {
        "count": 50,
        "uniqueAthletes": 25,
        "best": 1380,
        "mean": 2300,
        "median": 2200
      }
    },
    "dateRange": {
      "firstTrial": "2023-01-15T10:30:00Z",
      "lastTrial": "2024-01-10T14:45:00Z"
    }
  }
}
Respuesta sin datos (200 OK)

Cuando la ruta existe pero no tiene intentos finalizados

{
  "route": {
    "id": 1,
    "guid": "abc123-def456-ghi789",
    "name": "Cerro San Cristóbal"
  },
  "message": "No finished trials for this route",
  "stats": null
}
Respuestas de error
400 Bad Request

Falta un parámetro obligatorio

{
  "error": "Missing route id parameter"
}
404 Not Found

Ruta no encontrada

{
  "error": "Route not found for id=abc123-def456-ghi789"
}

Esquema de respuesta

Objeto raíz
  • route (object) - Información de la ruta
  • statistics (object) - Estadísticas completas de la ruta
Objeto Route
  • id (number) - ID numérico de la ruta
  • guid (string) - Identificador único de la ruta
  • name (string) - Nombre de la ruta
  • description (string) - Descripción de la ruta
  • meters (number) - Distancia de la ruta en metros
  • city (string|null) - Ciudad donde está la ruta
  • country (string|null) - País donde está la ruta
Objeto Statistics
  • totalTrials (number) - Número total de intentos completados
  • uniqueAthletes (number) - Número de atletas únicos
  • times (object) - Estadísticas de tiempo (mejor, peor, media, mediana, desv. estándar)
  • percentiles (object) - Desglose de percentiles (p10, p25, p50, p75, p90)
  • gender (object) - Estadísticas agrupadas por género
  • dateRange (object) - Fechas del primer y último intento
Objeto Times
  • best (object) - Mejor (más rápido) tiempo, con segundos y cadena formateada
  • worst (object) - Peor (más lento) tiempo
  • mean (object) - Tiempo promedio
  • median (object) - Tiempo mediano (percentil 50)
  • standardDeviation (number) - Desviación estándar en segundos
Objeto Percentiles
  • p10 (object) - Percentil 10 (corte del 10% más rápido)
  • p25 (object) - Percentil 25 (corte del 25% más rápido)
  • p50 (object) - Percentil 50 (mediana)
  • p75 (object) - Percentil 75
  • p90 (object) - Percentil 90
Objeto Gender

Contiene las claves: male, female, other (si hay datos)

  • count (number) - Número de intentos de este género
  • uniqueAthletes (number) - Atletas únicos de este género
  • best (number) - Mejor tiempo en segundos
  • mean (number) - Tiempo promedio en segundos
  • median (number) - Tiempo mediano en segundos
Objeto DateRange
  • firstTrial (string|null) - Fecha ISO 8601 del primer intento
  • lastTrial (string|null) - Fecha ISO 8601 del intento más reciente

Notas

  • Las estadísticas se calculan con Apache Commons Math para mayor precisión
  • Solo se incluyen en las estadísticas los intentos válidos y completados
  • Los percentiles ayudan a entender la distribución del rendimiento (p. ej., P10 = 10% más rápido)
  • Las estadísticas por género solo aparecen si hay datos para ese género
  • Usa el guid de la ruta (no el id numérico) en las llamadas a la API
  • Los tiempos se entregan tanto en segundos (número) como en cadenas formateadas (HH:MM:SS)

Soporte

Para preguntas, problemas o solicitudes de funciones relacionadas con la API, por favor contáctanos.