Docs/API y webhooks/Progreso

Progreso

Lee el progreso de formación de un usuario: práctica (por reto), aprendizaje (por escenario) y asignaciones activas. Todos los endpoints son de solo lectura y requieren el scope progress:read. La granularidad es intencionadamente fina: la mayoría de pipelines de sincronización con LMS y BI solo necesitan hacer polling sobre estos tres endpoints por usuario.

Endpoints

MétodoRutaScopePropósito
GET/users/{'{'}userId{'}'}/practice-progressprogress:readRetos de práctica completados con puntuación y marcas de tiempo.
GET/users/{'{'}userId{'}'}/learn-progressprogress:readEscenarios en modo aprendizaje con estado.
GET/users/{'{'}userId{'}'}/assignmentsprogress:readAsignaciones activas del usuario con porcentaje de progreso.

Ten en cuenta que estas rutas están en el nivel raíz de la API: /api/public/v1/users/{'{'}userId{'}'}/…, no bajo /progress/. {'{'}userId{'}'} es el id de usuario de SecureCodingHub, devuelto por la API de usuarios y por los payloads de webhook.

Progreso de práctica

Una fila por reto que el usuario haya completado. Los temas de práctica constan de varios retos (indexados desde 0), y cada reto pasa por dos fases —identificación de la vulnerabilidad y selección del parche— puntuadas de forma independiente.

GET /api/public/v1/users/{userId}/practice-progress
Authorization: Bearer scs_live_…

Respuesta

[
  {
    "topicId": "sql-injection",
    "challengeIndex": 0,
    "language": "python",
    "score": 100,
    "phase1Score": 50,
    "phase2Score": 50,
    "phase1HintUsed": false,
    "phase2HintUsed": false,
    "completedAt": "2026-05-20T14:32:08Z"
  },
  {
    "topicId": "sql-injection",
    "challengeIndex": 1,
    "language": "python",
    "score": 80,
    "phase1Score": 30,
    "phase2Score": 50,
    "phase1HintUsed": true,
    "phase2HintUsed": false,
    "completedAt": "2026-05-21T09:14:55Z"
  },
  {
    "topicId": "xss",
    "challengeIndex": 0,
    "language": "javascript",
    "score": 100,
    "phase1Score": 50,
    "phase2Score": 50,
    "phase1HintUsed": false,
    "phase2HintUsed": false,
    "completedAt": "2026-05-22T11:48:31Z"
  }
]
  • topicId: id del catálogo del tema de práctica (por ejemplo sql-injection, xss o ssrf).
  • challengeIndex: índice del reto dentro del tema, en base cero.
  • language: lenguaje en el que el usuario resolvió el reto.
  • score: total sobre 100. phase1Score y phase2Score suman score; cada uno sobre 50.
  • phase1HintUsed / phase2HintUsed: booleanos; el cliente decide cuánto cuesta usar pistas, el servidor solo registra el flag y la puntuación resultante.
  • completedAt: marca de tiempo ISO 8601 en UTC de la finalización más reciente.

Solo aparecen en esta lista los retos completados. Los intentos en curso no se exponen.

Ejemplo

curl -sS \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/users/1a2b3c4d-5e6f-7081-9203-4d5e6f708192/practice-progress

Progreso de aprendizaje

Una fila por escenario en modo aprendizaje que el usuario haya abierto. Los escenarios de aprendizaje son recorridos guiados, registrados por número de pasos y un campo status de grano grueso.

GET /api/public/v1/users/{userId}/learn-progress
Authorization: Bearer scs_live_…

Respuesta

[
  {
    "scenarioId": "auth-bypass-walkthrough",
    "currentStep": 8,
    "totalSteps": 8,
    "status": "completed",
    "startedAt": "2026-05-18T13:02:11Z",
    "completedAt": "2026-05-18T13:41:07Z",
    "lastAccessAt": "2026-05-18T13:41:07Z"
  },
  {
    "scenarioId": "jwt-tampering",
    "currentStep": 3,
    "totalSteps": 7,
    "status": "started",
    "startedAt": "2026-05-23T16:20:00Z",
    "completedAt": null,
    "lastAccessAt": "2026-05-24T10:08:42Z"
  }
]
  • scenarioId: id del catálogo del escenario.
  • currentStep / totalSteps: progreso dentro del escenario. Cuando son iguales, el escenario está terminado.
  • status: uno de started o completed.
  • completedAt: null hasta que el escenario se termina.
  • lastAccessAt: última vez que el usuario abrió el escenario, independientemente de si avanzó.

Ejemplo

curl -sS \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/users/1a2b3c4d-5e6f-7081-9203-4d5e6f708192/learn-progress

Asignaciones

Asignaciones activas del usuario, con un porcentaje de finalización precalculado para que no tengas que unir tú mismo el progreso de práctica y de aprendizaje. Incluye asignaciones a nivel de usuario, equipo y organización resueltas hasta este individuo.

GET /api/public/v1/users/{userId}/assignments
Authorization: Bearer scs_live_…

Respuesta

[
  {
    "id": "f1a2b3c4-d5e6-4708-8192-03405e6f7081",
    "contentArea": "practice",
    "targetType": "topic",
    "targetId": "sql-injection",
    "targetTitle": "SQL Injection",
    "deadline": "2026-06-15T00:00:00Z",
    "isMandatory": true,
    "isOverdue": false,
    "isCompleted": false,
    "totalItems": 5,
    "completedItems": 2,
    "progressPercent": 40.0,
    "note": "Assigned after CodeQL finding in payments-api."
  },
  {
    "id": "a2b3c4d5-e6f7-4081-9203-405e6f708192",
    "contentArea": "learn",
    "targetType": "scenario",
    "targetId": "auth-bypass-walkthrough",
    "targetTitle": "Auth Bypass Walkthrough",
    "deadline": "2026-05-31T00:00:00Z",
    "isMandatory": false,
    "isOverdue": false,
    "isCompleted": true,
    "totalItems": 1,
    "completedItems": 1,
    "progressPercent": 100.0,
    "note": null
  }
]
  • contentArea: practice o learn.
  • targetType: para práctica: category, module, topic o custom-course. Para aprendizaje: course, scenario o custom-course.
  • isOverdue: true si el plazo ha pasado y la asignación aún no se ha completado.
  • progressPercent: ratio de finalización escalado a 0–100.

Ejemplo

curl -sS \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/users/1a2b3c4d-5e6f-7081-9203-4d5e6f708192/assignments

Patrones de polling

Para pipelines de LMS o BI suele bastar con un polling por lotes una vez por hora: el progreso de práctica y aprendizaje solo cambia cuando un usuario termina algo. Para paneles en vivo más ajustados en el lado de asignaciones, suscríbete al webhook assignment.completed en lugar de hacer polling; consulta Webhooks. En v1 no existen eventos practice.completed ni learn.completed: para eso, haz polling sobre estos endpoints.