Docs/API et Webhooks/Cours personnalisés

Cours personnalisés

Un cours personnalisé est une séquence curatée orientée apprenant de sujets et scénarios tirés du catalogue de contenu SecureCodingHub. Une fois créé, un cours personnalisé peut être attribué exactement comme un sujet ou une catégorie intégrée. Nécessite custom-courses:read ou custom-courses:write selon le verbe.

Points de terminaison

MéthodeCheminPortéeObjectif
GET/custom-coursescustom-courses:readLister tous les cours personnalisés de l'organisation.
GET/custom-courses/{'{'}id{'}'}custom-courses:readRécupérer un cours personnalisé unique avec ses éléments ordonnés.
POST/custom-coursescustom-courses:writeCréer un nouveau cours personnalisé.
PATCH/custom-courses/{'{'}id{'}'}custom-courses:writeMettre à jour les métadonnées et/ou remplacer la liste d'éléments.
DELETE/custom-courses/{'{'}id{'}'}custom-courses:writeDésactiver doucement un cours personnalisé.

Tous les chemins sont relatifs à https://api.limeplate.com/api/public/v1.

Le modèle d'élément

Chaque cours personnalisé contient une liste ordonnée d'éléments. Chaque élément est une référence à un sujet ou scénario du catalogue — voir Catalogue de contenu pour les identifiants.

ChampTypeSignification
itemTypestringSoit "topic" (un sujet de pratique comme sql-injection) soit "scenario" (un scénario en mode apprentissage).
itemIdstringL'id catalogue du sujet ou scénario.
orderIndexintegerOrdre d'affichage basé sur zéro dans l'interface apprenant. Les valeurs plus basses apparaissent en premier.

Sur PATCH, omettez le champ items pour laisser les éléments intacts, ou envoyez une liste de remplacement complète pour écraser. Il n'y a pas de mise à jour d'élément partielle — renvoyez la séquence entière dans l'ordre que vous voulez qu'elle soit stockée.

Lister les cours personnalisés

Renvoie une entrée par cours personnalisé actif dans l'organisation, triées par mise à jour la plus récente.

GET /api/public/v1/custom-courses
Authorization: Bearer scs_live_…

Réponse

[
  {
    "id": "8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02",
    "name": "Backend Onboarding — Q2",
    "description": "Required reading for new backend hires.",
    "icon": "shield",
    "color": "#3b82f6",
    "itemCount": 6,
    "usageCount": 12,
    "createdByUserId": "1a2b3c4d-5e6f-7081-9203-4d5e6f708192",
    "createdByName": "Jane Smith",
    "createdAt": "2026-04-10T09:22:14Z",
    "updatedAt": "2026-05-18T15:01:47Z"
  }
]

Exemple

curl -sS \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/custom-courses

Récupérer un cours personnalisé

Renvoie le cours avec ses éléments ordonnés développés. resolvedTitle est le titre humainement lisible du sujet ou scénario sous-jacent au moment de la lecture — pratique pour rendre sans une seconde recherche de catalogue.

GET /api/public/v1/custom-courses/{customCourseId}
Authorization: Bearer scs_live_…

Réponse

{
  "id": "8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02",
  "name": "Backend Onboarding — Q2",
  "description": "Required reading for new backend hires.",
  "icon": "shield",
  "color": "#3b82f6",
  "items": [
    {
      "id": "c1d2e3f4-5060-7081-9203-4d5e6f708192",
      "itemType": "topic",
      "itemId": "sql-injection",
      "resolvedTitle": "SQL Injection",
      "orderIndex": 0
    },
    {
      "id": "d2e3f405-6070-8192-0304-5e6f70819203",
      "itemType": "scenario",
      "itemId": "auth-bypass-walkthrough",
      "resolvedTitle": "Auth Bypass Walkthrough",
      "orderIndex": 1
    },
    {
      "id": "e3f40506-7081-9203-0405-6f7081920304",
      "itemType": "topic",
      "itemId": "xss",
      "resolvedTitle": "Cross-Site Scripting",
      "orderIndex": 2
    }
  ],
  "usageCount": 12,
  "createdByUserId": "1a2b3c4d-5e6f-7081-9203-4d5e6f708192",
  "createdByName": "Jane Smith",
  "createdAt": "2026-04-10T09:22:14Z",
  "updatedAt": "2026-05-18T15:01:47Z"
}

Exemple

curl -sS \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/custom-courses/8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02

Créer un cours personnalisé

Crée un cours et renvoie la vue détail. L'organisation de la clé API possède le nouveau cours ; l'utilisateur qui a émis la clé est enregistré comme créateur.

POST /api/public/v1/custom-courses
Authorization: Bearer scs_live_…
Content-Type: application/json

Corps de requête

{
  "name": "Backend Onboarding — Q2",
  "description": "Required reading for new backend hires.",
  "icon": "shield",
  "color": "#3b82f6",
  "items": [
    { "itemType": "topic",    "itemId": "sql-injection",          "orderIndex": 0 },
    { "itemType": "scenario", "itemId": "auth-bypass-walkthrough", "orderIndex": 1 },
    { "itemType": "topic",    "itemId": "xss",                    "orderIndex": 2 }
  ]
}

name est requis et doit être unique dans l'organisation. description, icon et color sont optionnels — color prend toute chaîne hex CSS. items peut être vide à la création ; vous pouvez le peupler plus tard via PATCH.

Réponse

Même forme que Récupérer un cours personnalisé.

Exemple

curl -sS -X POST \
  -H "Authorization: Bearer $SCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Backend Onboarding — Q2",
    "description": "Required reading for new backend hires.",
    "icon": "shield",
    "color": "#3b82f6",
    "items": [
      { "itemType": "topic", "itemId": "sql-injection", "orderIndex": 0 },
      { "itemType": "topic", "itemId": "xss",           "orderIndex": 1 }
    ]
  }' \
  https://api.limeplate.com/api/public/v1/custom-courses

Mettre à jour un cours personnalisé

Tous les champs de la requête sont optionnels. Passez uniquement les champs que vous voulez modifier. Envoyer items remplace toute la liste d'éléments — pour réordonner, renvoyez chaque élément avec de nouvelles valeurs orderIndex.

PATCH /api/public/v1/custom-courses/{customCourseId}
Authorization: Bearer scs_live_…
Content-Type: application/json

Corps de requête

{
  "name": "Backend Onboarding — Q3",
  "items": [
    { "itemType": "topic",    "itemId": "sql-injection", "orderIndex": 0 },
    { "itemType": "topic",    "itemId": "ssrf",          "orderIndex": 1 },
    { "itemType": "scenario", "itemId": "jwt-tampering", "orderIndex": 2 }
  ]
}

Réponse

L'objet détail mis à jour.

Exemple

curl -sS -X PATCH \
  -H "Authorization: Bearer $SCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Backend Onboarding — Q3" }' \
  https://api.limeplate.com/api/public/v1/custom-courses/8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02

Supprimer un cours personnalisé

Désactive doucement le cours. Il cesse d'apparaître dans GET /custom-courses et dans les interfaces apprenant. Les affectations existantes qui référençaient le cours continuent de suivre la progression historique mais ne sont pas livrées aux nouveaux destinataires.

DELETE /api/public/v1/custom-courses/{customCourseId}
Authorization: Bearer scs_live_…

Réponse

{ "message": "Custom course deactivated" }

Exemple

curl -sS -X DELETE \
  -H "Authorization: Bearer $SCH_API_KEY" \
  https://api.limeplate.com/api/public/v1/custom-courses/8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02

Attribuer un cours personnalisé

Un cours personnalisé n'est pas livré aux apprenants tant qu'il n'est pas attribué. Utilisez Affectations avec targetType: "custom-course" et targetId définis sur l'id du cours personnalisé :

curl -sS -X POST \
  -H "Authorization: Bearer $SCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "assigneeType": "user",
    "assigneeId": "1a2b3c4d-5e6f-7081-9203-4d5e6f708192",
    "contentArea": "practice",
    "targetType": "custom-course",
    "targetId": "8b1f0c2e-3a45-4d99-9a7e-2c5e1b3a8f02",
    "deadline": "2026-06-15T00:00:00Z",
    "isMandatory": true
  }' \
  https://api.limeplate.com/api/public/v1/assignments

L'apprenant voit les éléments dans l'ordre orderIndex. Les sujets de pratique et les scénarios d'apprentissage sont suivis sous leurs points de terminaison de progression respectifs — voir Progression.