{"openapi":"3.0.3","info":{"title":"Pulse MDM API","version":"1.0.0","description":"Contrat public de l’API REST OpenMDM pour intégrer Pulse.","x-audience":"public-integrators"},"paths":{"/apk-details/lookup":{"post":{"tags":["ApkDetails"],"summary":"Résolution batch des noms et icônes d'applications Quest/Meta","description":"Proxy vers le back interface web (`/apk-details/lookup`). Reçoit une liste de packageNames et retourne les noms et URLs d'images disponibles pour les APK enregistrés. Endpoint public — ne nécessite pas de JWT.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"packageNames":{"type":"array","items":{"type":"string"}}}},"example":{"packageNames":["string"]}}}},"responses":{"200":{"description":"Liste des résultats (packageName + name + imageUrl)."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Erreur lors du proxy vers le back interface web."}},"security":[],"operationId":"postApkDetailsLookup"}},"/apk-details/image/{packageName}":{"get":{"tags":["ApkDetails"],"summary":"Image WebP d'une application Quest/Meta","description":"Proxy vers le back interface web (`GET /apk-details/image/:packageName`). Récupère l'image associée au package côté serveur et la retourne au casque. Endpoint public — ne nécessite pas de JWT.\n","security":[],"operationId":"getApkDetailsImagePackageName","responses":{"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/contents/{contentId}/all":{"delete":{"tags":["Contents"],"summary":"Supprimer un contenu sur tous les devices","parameters":[{"in":"path","name":"contentId","required":true,"schema":{"type":"string"},"description":"Identifiant du contenu a retirer (application, video ou fichier)."}],"responses":{"200":{"description":"Le contenu a ete supprime des devices concernes.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur lors de la suppression."}},"operationId":"deleteContentsContentIdAll","description":"Supprimer un contenu sur tous les devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/contents/{contentId}":{"delete":{"tags":["Contents"],"summary":"Supprimer un contenu sur une liste de devices","parameters":[{"in":"path","name":"contentId","required":true,"schema":{"type":"string"},"description":"Identifiant du contenu (application, video ou fichier)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"devicesId":{"type":"array","items":{"type":"string"}}},"required":["devicesId"]},"example":{"devicesId":["string"]}}}},"responses":{"200":{"description":"Statut de suppression.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"deleteContentsContentId","description":"Supprimer un contenu sur une liste de devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/contents/applications/{contentId}":{"put":{"tags":["Contents"],"summary":"Mettre a jour une application sur tous les devices concernés","parameters":[{"in":"path","name":"contentId","required":true,"schema":{"type":"string"},"description":"Identifiant de l application a mettre a jour."},{"in":"query","name":"models","required":false,"schema":{"type":"array","items":{"type":"string"},"style":"form","explode":false},"description":"Filtre optionnel sur les modeles de devices (nom du type)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Champs a mettre a jour sur l application cible (ex version, url, packageName, expirationDate).","properties":{"expirationDate":{"type":"string","format":"date-time","nullable":true,"example":"2026-12-31T23:59:59.000Z","description":"Instant ISO 8601 complet avec fuseau (Z ou +/-HH:MM). Les dates seules, timestamps sans fuseau et chaines vides sont rejetes. Null ou champ absent supprime la limite."}}},"example":{"expirationDate":"2026-12-31T23:59:59.000Z"}}}},"responses":{"200":{"description":"Mise a jour effectuee.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur lors de la mise a jour."}},"operationId":"putContentsApplicationsContentId","description":"Mettre a jour une application sur tous les devices concernés. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/contents/videos/{contentId}":{"put":{"tags":["Contents"],"summary":"Mettre a jour une video sur tous les devices concernes","parameters":[{"in":"path","name":"contentId","required":true,"schema":{"type":"string"},"description":"Identifiant du contenu video (champ id dans settings.videos), tel qu utilise sur l interface web. L objet video embarque contient aussi idDetailContent (reference a la fiche contenu)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Champs a mettre a jour sur la video cible (ex title, idDetailContent, url, posterUrl, vignetteUrl, isStereoscopic, projectionType, formatType, synopsis, description, expirationDate).","properties":{"idDetailContent":{"type":"string","nullable":true,"description":"Reference a la fiche contenu, null ou omis si absent."},"title":{"type":"string"},"url":{"type":"string"},"posterUrl":{"type":"string"},"vignetteUrl":{"type":"string"},"isStereoscopic":{"type":"boolean"},"projectionType":{"type":"string","enum":["flat","sphere","dome","full_dome","cube"]},"formatType":{"type":"string","enum":["2D","3D_Side_By_Side","3D_Over_Under"]},"synopsis":{"type":"string"},"description":{"type":"string"},"expirationDate":{"type":"string","format":"date-time","nullable":true,"example":"2026-12-31T23:59:59.000Z","description":"Instant ISO 8601 complet avec fuseau (Z ou +/-HH:MM). Les dates seules, timestamps sans fuseau et chaines vides sont rejetes. Null ou champ absent supprime la limite."}}},"example":{"idDetailContent":"string","title":"string","url":"string","posterUrl":"string","vignetteUrl":"string","isStereoscopic":false,"projectionType":"flat","formatType":"2D","synopsis":"string","description":"string","expirationDate":"2026-12-31T23:59:59.000Z"}}}},"responses":{"200":{"description":"Mise a jour effectuee.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur lors de la mise a jour."}},"operationId":"putContentsVideosContentId","description":"Mettre a jour une video sur tous les devices concernes. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/settings-catalog":{"get":{"tags":["Devices"],"summary":"Catalogue de paramètres applicable à ce device","description":"Renvoie le sous-catalogue de paramètres réellement applicables au device cible,\nen se basant sur la marque détectée à partir de son `type.brand`. Si la marque\nn'est pas reconnue (Pico, HTC, Meta), retombe sur le catalogue `generic`.\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Sous-catalogue + marque détectée.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BrandCatalog"},{"type":"object","properties":{"deviceId":{"type":"string"},"detectedBrand":{"type":"string","enum":["pico","htc","meta","generic"]},"rawBrand":{"type":"string","nullable":true}}}]}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getDevicesDeviceIdSettingsCatalog"}},"/devices/whatiam":{"post":{"tags":["Devices"],"summary":"Identifier le type d appareil a partir du modele","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"product":{"type":"string"}}},"example":{"name":"string","product":"string"}}}},"responses":{"200":{"description":"Type du device retourne ou cree."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Type inconnu."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesWhatiam","description":"Identifier le type d appareil a partir du modele. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices":{"get":{"tags":["Devices"],"summary":"Lister les casques accessibles","description":"Liste paginée des casques du credential, plus ceux des flottes que la plateforme lui a ouvertes (`fleetAccess`, par exemple la flotte Pulse). Le détail d'un casque se lit avec `GET /devices/{deviceId}`.\n","parameters":[{"in":"query","name":"enterpriseId","required":false,"description":"Restreint la liste à une seule entreprise accessible : celle du credential ou une flotte ouverte. Toute autre entreprise donne un 403.","schema":{"type":"string"}},{"in":"query","name":"page","required":false,"description":"Page demandée, à partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"in":"query","name":"limit","required":false,"description":"Nombre de casques par page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Page de casques.","content":{"application/json":{"schema":{"type":"object","properties":{"page":{"type":"integer","description":"Page renvoyée."},"limit":{"type":"integer","description":"Nombre maximal de casques par page."},"total":{"type":"integer","description":"Nombre total de casques accessibles pour ce filtre."},"items":{"type":"array","description":"Casques de la page, triés par identifiant.","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifiant du casque."},"label":{"type":"string","nullable":true,"description":"Nom du casque."},"description":{"type":"string","nullable":true,"description":"Description libre du casque."},"androidId":{"type":"string","nullable":true,"description":"Identifiant Android, absent tant que l'enrôlement n'est pas terminé."},"enterprise":{"type":"string","description":"Entreprise propriétaire du casque : celle du credential ou une flotte ouverte."},"isArchived":{"type":"boolean","description":"Casque archivé."},"replacedBy":{"type":"string","nullable":true,"description":"Casque qui le remplace après un ré-enrôlement."},"lastHeartbeatAt":{"type":"string","format":"date-time","nullable":true,"description":"Dernier signal de vie reçu du casque."}}}}}}}}},"400":{"description":"Paramètre invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token rattaché à aucune entreprise, ou entreprise hors de son périmètre."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevices"},"post":{"tags":["Devices"],"summary":"Enroller un device via token Android Management","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enrollmentToken","androidId"],"properties":{"enrollmentToken":{"type":"string"},"androidId":{"type":"string"}}},"example":{"enrollmentToken":"string","androidId":"string"}}}},"responses":{"200":{"description":"Device enrole."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Token ou androidId manquant."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevices","description":"Enroller un device via token Android Management. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"patch":{"tags":["Devices"],"summary":"Mettre a jour plusieurs devices (Bulk Update)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"label":{"type":"string"},"license":{"type":"object","properties":{"level":{"type":"string"},"status":{"type":"string"},"alertDate":{"type":"string","format":"date-time"}}}}},"example":{"devicesId":["string"],"label":"string","license":{"level":"string","status":"string","alertDate":"2026-01-01T12:00:00.000Z"}}}}},"responses":{"200":{"description":"Tableau des resultats par device."},"400":{"description":"Tableau devicesId manquant."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevices","description":"Mettre a jour plusieurs devices (Bulk Update). Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/stats/connectivity":{"post":{"tags":["Devices"],"summary":"Historique de connectivité des appareils (courbes d'uptime)","description":"Agrège les logs d'appareils pour tracer la disponibilité dans le temps et calculer l'uptime par appareil.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"granularity":{"type":"string","enum":["day","week","month"],"default":"day"},"maxGapMinutes":{"type":"integer","description":"Fenêtre de présence autour d'un log (défaut 20 min)"}}},"example":{"deviceIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","granularity":"day","maxGapMinutes":0}}}},"responses":{"200":{"description":"Historique calculé."},"400":{"description":"Paramètre invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesStatsConnectivity"}},"/devices/stats/activity":{"post":{"tags":["Devices"],"summary":"Statistiques d'activité des appareils (basées sur les lectures)","description":"Top appareils par lectures/durée, appareils jamais utilisés et inactifs depuis N jours.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"inactiveDays":{"type":"integer","description":"Seuil d'inactivité en jours (défaut 30)"}}},"example":{"deviceIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","inactiveDays":0}}}},"responses":{"200":{"description":"Stats activité calculées."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesStatsActivity"}},"/devices/stats/fleet":{"post":{"tags":["Devices"],"summary":"KPIs agrégés de la flotte en un seul appel","description":"Vue d'ensemble complète - disponibilité, batterie, stockage, modèles, licences, versions MDM et OS.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"},"description":"Restreindre l'analyse à certains appareils (optionnel)"}}},"example":{"deviceIds":["string"]}}}},"responses":{"200":{"description":"Fleet stats calculées."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesStatsFleet"}},"/devices/stats/apps":{"post":{"tags":["Devices"],"summary":"Statistiques de déploiement des applications, vidéos et fichiers","description":"Compare les contenus affectés aux inventaires réellement remontés par les appareils afin de calculer la couverture installée et la distribution des versions.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"},"description":"Restreindre l'analyse à certains appareils (optionnel)"}}},"example":{"deviceIds":["string"]}}}},"responses":{"200":{"description":"Stats de déploiement calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDeploymentStatsResponse"}}}},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesStatsApps"}},"/devices/stats/health":{"post":{"tags":["Devices"],"summary":"Historique santé batterie et stockage de la flotte","description":"Retourne l'état courant de santé par appareil (batteryHealth, niveaux, usage stockage) et un snapshot de l'état global. Les tendances (batteryTrend, storageTrend) et le time-series complet nécessitent une collection d'historisation dédiée (non encore disponible).\n","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"granularity":{"type":"string","enum":["day","week","month"],"default":"day"}}},"example":{"deviceIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","granularity":"day"}}}},"responses":{"200":{"description":"Health history computed."},"400":{"description":"Paramètre invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesStatsHealth"}},"/devices/{deviceId}/stream-status":{"get":{"tags":["Devices"],"summary":"Recuperer ou s abonner au statut de streaming d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Statut actuel (JSON) ou flux SSE si `Accept: text/event-stream`."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getDevicesDeviceIdStreamStatus","description":"Recuperer ou s abonner au statut de streaming d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/is-available":{"get":{"tags":["Devices"],"summary":"Connaître la disponibilite d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"query","name":"refresh","schema":{"type":"boolean"},"description":"Force une verification en temps reel aupres du device."}],"responses":{"200":{"description":"Etat de disponibilite retourne."},"400":{"description":"Identifiant invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdIsAvailable","description":"Connaître la disponibilite d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/is-available/{isAvailable}":{"post":{"tags":["Devices"],"summary":"Forcer l etat de disponibilite d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"path","name":"isAvailable","required":true,"schema":{"type":"boolean"},"description":"Paramètre isAvailable transmis dans path."}],"responses":{"200":{"description":"Etat mis a jour."},"400":{"description":"Parametre invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesDeviceIdIsAvailableIsAvailable","description":"Forcer l etat de disponibilite d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/androidid/{androidid}":{"get":{"tags":["Devices"],"summary":"Recuperer un device par Android ID","parameters":[{"in":"path","name":"androidid","required":true,"schema":{"type":"string"},"description":"Paramètre androidid transmis dans path."}],"responses":{"200":{"description":"Device retourne."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesAndroididAndroidid","description":"Recuperer un device par Android ID. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/updates":{"get":{"tags":["Devices"],"summary":"Suivre en SSE les mises a jour d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Flux SSE des changements sur le device."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdUpdates","description":"Suivre en SSE les mises a jour d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/events":{"get":{"tags":["Devices"],"summary":"Consulter l historique des evenements d un device","description":"Retourne les evenements d inventaire, de deploiement, de commande et de cycle de vie du device, tries du plus recent au plus ancien. L historique est conserve pendant 180 jours.","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"query","name":"type","required":false,"description":"Filtrer sur un type d evenement exact.","schema":{"type":"string"}},{"in":"query","name":"from","required":false,"description":"Debut inclus de la plage temporelle.","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"to","required":false,"description":"Fin incluse de la plage temporelle.","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"page","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","required":false,"description":"Nombre d evenements par page, limite a 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Page d evenements du device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceEventPage"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdEvents"}},"/devices/{deviceId}":{"get":{"tags":["Devices"],"summary":"Recuperer un device par ID","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Device trouve avec son inventaire et le statut de ses contenus.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Device"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceId","description":"Recuperer un device par ID. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"put":{"tags":["Devices"],"summary":"Mettre a jour les meta donnees d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"androidId":{"type":"string"},"macAddress":{"type":"string","pattern":"^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$"},"type":{"type":"object"},"mdmInfo":{"type":"object"},"label":{"type":"string"},"licence":{"type":"object"},"downloads":{"type":"array","items":{"$ref":"#/components/schemas/DownloadTask"}},"installedPackages":{"type":"array","items":{"$ref":"#/components/schemas/InstalledPackage"}},"contentPresence":{"type":"array","items":{"$ref":"#/components/schemas/ContentPresence"}},"events":{"type":"array","maxItems":500,"items":{"$ref":"#/components/schemas/DeviceEventInput"}}}},"example":{"androidId":"string","macAddress":"string","type":{},"mdmInfo":{},"label":"string","licence":{},"downloads":[{"downloadId":0,"url":"string","dir":"string","fileName":"string","totalBytes":0,"lastBytes":0,"status":"PENDING","progress":0,"speed":0,"typeFile":"Video","startTime":0,"associatedObject":{}}],"installedPackages":[{"packageName":"string","versionCode":0,"versionName":"string"}],"contentPresence":[{"contentId":"string","type":"application","packageName":"string","present":false,"sizeBytes":0,"installed":false,"installedVersionCode":0,"expectedVersionCode":0,"managedPaths":["string"]}],"events":[{"eventId":"string","type":"string","timestamp":0,"payload":{}}]}}}},"responses":{"200":{"description":"Device mis a jour et evenements acquittes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceHeartbeatResponse"}}}},"400":{"description":"Donnees invalides."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"413":{"description":"Le lot depasse la limite de 500 evenements."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesDeviceId","description":"Mettre a jour les meta donnees d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"delete":{"tags":["Devices"],"summary":"Supprimer un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Device supprime."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"description":"Supprime l'appareil. Son activité reste dans les statistiques (`/stats/activity/devices`) : une fiche figée de son identité (libellé, androidId, modèle, dates) est conservée et un événement `DEVICE_DELETED` est historisé.","operationId":"deleteDevicesDeviceId"},"patch":{"tags":["Devices"],"summary":"Mettre a jour un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string"},"license":{"type":"object"}}},"example":{"label":"string","license":{}}}}},"responses":{"200":{"description":"Device mis a jour."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesDeviceId","description":"Mettre a jour un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/lookup":{"post":{"tags":["Devices"],"summary":"Recuperer plusieurs devices par IDs","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"}},"strict":{"type":"boolean"}}},"example":{"ids":["string"],"strict":false}}}},"responses":{"200":{"description":"Liste des devices trouves et informations sur les IDs invalides."},"400":{"description":"Tableau ids manquant ou vide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Trop d IDs demandes."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesLookup","description":"Recuperer plusieurs devices par IDs. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/license":{"get":{"tags":["Devices"],"summary":"Recuperer la license d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"License retournee."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdLicense","description":"Recuperer la license d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/temporary-verification-code":{"get":{"tags":["Devices"],"summary":"Generer un code de verification temporaire","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Code genere."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable ou deja enrole."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdTemporaryVerificationCode","description":"Generer un code de verification temporaire. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/manual-enrollment":{"post":{"tags":["Devices"],"summary":"Enroller un device via code manuel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","androidId"],"properties":{"code":{"type":"integer"},"androidId":{"type":"string"}}},"example":{"code":0,"androidId":"string"}}}},"responses":{"200":{"description":"Device enrole."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Code ou androidId manquant."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Aucun device enrole ou erreur serveur."}},"operationId":"postDevicesManualEnrollment","description":"Enroller un device via code manuel. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/unenroll":{"post":{"tags":["Devices"],"summary":"Désenrôler un appareil et lancer le nettoyage à distance","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Commande envoyee avec succés."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesDeviceIdUnenroll","description":"Désenrôler un appareil et lancer le nettoyage à distance. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/configure":{"put":{"tags":["Devices"],"summary":"Configurer un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceSettings"},"example":{"kioskMode":false,"developerSettingsAllowed":false,"applications":[{"id":"string","idDetailContent":"string","packageName":"string","url":"string","codeVersion":0,"obbUrl":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"videos":[{"id":"string","idDetailContent":"string","title":"string","url":"string","posterUrl":"string","vignetteUrl":"string","isStereoscopic":false,"projectionType":"flat","formatType":"2D","synopsis":"string","description":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"files":[{"id":"string","name":"string","url":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"packages":["string"],"wifi":[{"ssid":"string","password":"string"}],"video360":[{}],"volume":0,"isOfflineEnabled":false,"isContentDownloadAllowed":false,"isLanDiscoveryEnabled":false,"isScreensharingEnabled":false,"isLanIntercomEnabled":false,"display":{"brightness":0,"refreshRate":60,"ipdMm":58,"passthroughEnabled":false,"guardianEnabled":false,"boundaryConfirmDialog":false,"bootAnimationEnabled":false,"chargingAnimationEnabled":false},"audio":{"multimedia":0,"notification":0,"alarm":0,"system":0},"power":{"screenOffDelaySec":0,"autoSleepDelaySec":0,"autoSleepOnTakeoff":false,"powerKeyShort":"sleep","powerKeyLong":"sleep","scheduledStartup":"string","scheduledShutdown":"string"},"system":{"countryCode":"string","locale":"string","timezone":"string","autoTime":false,"ntpServer":"string","lockScreenEnabled":false,"lockScreenPasscodeEnabled":false,"showAppQuitConfirmDialog":false,"killBackgroundVrApp":false,"keepAlivePackages":["string"],"allowUnknownSources":false,"developerOptionsEnabled":false,"defaultLauncherPackage":"string"},"security":{"usbEnabled":false,"usbFileTransferEnabled":false,"usbDebuggingEnabled":false,"usbTetheringEnabled":false,"bluetoothEnabled":false,"bluetoothTetheringEnabled":false,"wifiTetheringEnabled":false,"microphoneEnabled":false,"locationEnabled":false,"screenCastEnabled":false,"screenshotAllowed":false,"cameraEnabled":false,"factoryResetProtection":false},"tracking":{"eyeTrackingEnabled":false,"faceTrackingEnabled":false,"handTrackingEnabled":false,"bodyTrackingEnabled":false,"trackingOrigin":"eye","sixDof":false,"controllerVibration":false},"shortcuts":{"recordEnabled":false,"castEnabled":false,"captureEnabled":false,"settingsEnabled":false,"recenterEnabled":false,"backEnabled":false,"fitEnabled":false},"network":{"wifiEnabled":false,"wifiP2pEnabled":false,"otaPolicy":"auto","otaServerUrl":"string","globalProxy":{"use":false,"host":"string","port":0,"byPass":"string"}}}}}},"responses":{"200":{"description":"Configuration appliquee et retour du device."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"422":{"description":"Configuration invalide ou conflit de package Android.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageConflictError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesDeviceIdConfigure","description":"Configurer un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/configure":{"put":{"tags":["Devices"],"summary":"Configurer plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","settings"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"settings":{"$ref":"#/components/schemas/DeviceSettings"}}},"example":{"devicesId":["string"],"settings":{"kioskMode":false,"developerSettingsAllowed":false,"applications":[{"id":"string","idDetailContent":"string","packageName":"string","url":"string","codeVersion":0,"obbUrl":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"videos":[{"id":"string","idDetailContent":"string","title":"string","url":"string","posterUrl":"string","vignetteUrl":"string","isStereoscopic":false,"projectionType":"flat","formatType":"2D","synopsis":"string","description":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"files":[{"id":"string","name":"string","url":"string","deployment":{"contentId":"string","type":"application","packageName":"string","status":"ASSIGNED","progress":0,"installedVersionCode":0,"expectedVersionCode":0,"computedAt":"2026-01-01T12:00:00.000Z"}}],"packages":["string"],"wifi":[{"ssid":"string","password":"string"}],"video360":[{}],"volume":0,"isOfflineEnabled":false,"isContentDownloadAllowed":false,"isLanDiscoveryEnabled":false,"isScreensharingEnabled":false,"isLanIntercomEnabled":false,"display":{"brightness":0,"refreshRate":60,"ipdMm":58,"passthroughEnabled":false,"guardianEnabled":false,"boundaryConfirmDialog":false,"bootAnimationEnabled":false,"chargingAnimationEnabled":false},"audio":{"multimedia":0,"notification":0,"alarm":0,"system":0},"power":{"screenOffDelaySec":0,"autoSleepDelaySec":0,"autoSleepOnTakeoff":false,"powerKeyShort":"sleep","powerKeyLong":"sleep","scheduledStartup":"string","scheduledShutdown":"string"},"system":{"countryCode":"string","locale":"string","timezone":"string","autoTime":false,"ntpServer":"string","lockScreenEnabled":false,"lockScreenPasscodeEnabled":false,"showAppQuitConfirmDialog":false,"killBackgroundVrApp":false,"keepAlivePackages":["string"],"allowUnknownSources":false,"developerOptionsEnabled":false,"defaultLauncherPackage":"string"},"security":{"usbEnabled":false,"usbFileTransferEnabled":false,"usbDebuggingEnabled":false,"usbTetheringEnabled":false,"bluetoothEnabled":false,"bluetoothTetheringEnabled":false,"wifiTetheringEnabled":false,"microphoneEnabled":false,"locationEnabled":false,"screenCastEnabled":false,"screenshotAllowed":false,"cameraEnabled":false,"factoryResetProtection":false},"tracking":{"eyeTrackingEnabled":false,"faceTrackingEnabled":false,"handTrackingEnabled":false,"bodyTrackingEnabled":false,"trackingOrigin":"eye","sixDof":false,"controllerVibration":false},"shortcuts":{"recordEnabled":false,"castEnabled":false,"captureEnabled":false,"settingsEnabled":false,"recenterEnabled":false,"backEnabled":false,"fitEnabled":false},"network":{"wifiEnabled":false,"wifiP2pEnabled":false,"otaPolicy":"auto","otaServerUrl":"string","globalProxy":{"use":false,"host":"string","port":0,"byPass":"string"}}}}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Configuration invalide ou conflit de package Android.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageConflictError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesConfigure","description":"Configurer plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/metadata/{namespace}":{"put":{"tags":["Devices"],"summary":"Ecrire un blob de metadata namespace sur plusieurs devices (bulk)","description":"Metadonnees opaques namespacees par client, transportees jusqu'au casque (LAN GET /my). Convention reservee : namespace peut contenir la cle `group` = { id, label, color? }.","parameters":[{"in":"path","name":"namespace","required":true,"schema":{"type":"string"},"description":"Paramètre namespace transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","value"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"value":{"type":"object"}}},"example":{"devicesId":["string"],"value":{}}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesMetadataNamespace"}},"/devices/{deviceId}/metadata/{namespace}":{"put":{"tags":["Devices"],"summary":"Ecrire le blob de metadata d'un namespace sur un device (remplacement)","description":"Le body JSON remplace entierement le blob du namespace. Le casque est notifie via le push device-config existant. Convention reservee : cle `group` = { id, label, color? }.","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"path","name":"namespace","required":true,"schema":{"type":"string"},"description":"Paramètre namespace transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"},"example":{}}}},"responses":{"200":{"description":"Metadata ecrite et retour du device."},"400":{"description":"Namespace ou valeur invalide (INVALID_NAMESPACE, INVALID_VALUE, VALUE_TOO_LARGE)."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesDeviceIdMetadataNamespace"},"delete":{"tags":["Devices"],"summary":"Retirer un namespace de metadata d'un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"path","name":"namespace","required":true,"schema":{"type":"string"},"description":"Paramètre namespace transmis dans path."}],"responses":{"200":{"description":"Namespace retire et retour du device."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"deleteDevicesDeviceIdMetadataNamespace","description":"Retirer un namespace de metadata d'un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/command":{"put":{"tags":["Devices"],"summary":"Envoyer une commande a un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceCommand"},"example":{"event":"string","message":{}}}}},"responses":{"200":{"description":"Reponse de la commande."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device injoignable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesDeviceIdCommand","description":"Envoyer une commande a un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/stream-quality":{"put":{"tags":["Devices"],"summary":"Changer la qualite du streaming d un device","description":"Envoie une commande `set-quality` au device pour modifier le profil du stream en cours.\nLes valeurs techniques sont resolues par le casque selon son materiel et le transport Web.\nLe device repond avec les parametres effectivement appliques.\nLe device doit etre en ligne pour que la commande aboutisse.\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Identifiant du device"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["qualityProfile"],"properties":{"qualityProfile":{"type":"string","enum":["OPTIMIZED","HIGH_FIDELITY"],"description":"Intention de qualite a appliquer au stream","example":"HIGH_FIDELITY"}}},"example":{"qualityProfile":"HIGH_FIDELITY"}}}},"responses":{"200":{"description":"Qualite appliquee avec succes","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"requestedProfile":{"type":"string","enum":["OPTIMIZED","HIGH_FIDELITY"]},"appliedProfile":{"type":"string","enum":["OPTIMIZED","HIGH_FIDELITY"]},"transport":{"type":"string","enum":["LAN","WEB"]},"hardwareTier":{"type":"string","enum":["LEGACY","XR2_GEN1","XR2_GEN2","UNKNOWN"]},"width":{"type":"number","example":1920},"height":{"type":"number","example":1080},"fps":{"type":"number","example":30},"bitrateKbps":{"type":"number","example":4000},"fallbackReason":{"type":"string","nullable":true}}}}}}}},"400":{"description":"Profil invalide"},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device injoignable"},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur"}},"operationId":"putDevicesDeviceIdStreamQuality"}},"/devices/{deviceId}/resolve-mac":{"post":{"tags":["Devices"],"summary":"Résout la MAC de l'appareil via le routeur MikroTik de son entreprise","description":"Interroge la table ARP / les baux DHCP du MikroTik configuré sur l'entreprise, à partir de l'IP LAN connue de l'appareil, et stocke la MAC trouvée.\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"MAC résolue et enregistrée."},"400":{"description":"Pas d'IP LAN connue ou pas d'entreprise."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"MAC non résolue (MikroTik désactivé, injoignable ou à une adresse non publique, ou IP absente)."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postDevicesDeviceIdResolveMac"}},"/devices/command":{"put":{"tags":["Devices"],"summary":"Envoyer une commande a plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","settings"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"settings":{"$ref":"#/components/schemas/DeviceCommand"}}},"example":{"devicesId":["string"],"settings":{"event":"string","message":{}}}}}},"responses":{"200":{"description":"Reponses par device."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"putDevicesCommand","description":"Envoyer une commande a plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/files":{"patch":{"tags":["Devices"],"summary":"Ajouter des fichiers a plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","files"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"force":{"type":"boolean","description":"Force la reinstallation (re-ecrit l entree et notifie le device quel que soit son etat)."},"files":{"type":"array","items":{"type":"object","required":["url","name"],"properties":{"id":{"type":"string"},"url":{"type":"string"},"name":{"type":"string"},"destinationPath":{"type":"string","description":"Emplacement de depot optionnel sur le device (chemin relatif au dossier Pulse, ou chemin absolu best-effort)."}}}}}},"example":{"devicesId":["string"],"force":false,"files":[{"id":"string","url":"string","name":"string","destinationPath":"string"}]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesFiles","description":"Ajouter des fichiers a plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"delete":{"tags":["Devices"],"summary":"Supprimer des fichiers de plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","files"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"files":{"type":"array","items":{"type":"string"}}}},"example":{"devicesId":["string"],"files":["string"]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"deleteDevicesFiles","description":"Supprimer des fichiers de plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/videos":{"patch":{"tags":["Devices"],"summary":"Ajouter des videos a plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","videos"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"force":{"type":"boolean","description":"Force la reinstallation (re-ecrit l entree et notifie le device quel que soit son etat)."},"videos":{"type":"array","items":{"type":"object","required":["id","url"],"properties":{"id":{"type":"string"},"idDetailContent":{"type":"string","nullable":true,"description":"Reference a la fiche contenu, null ou omis si absent."},"title":{"type":"string"},"url":{"type":"string"},"posterUrl":{"type":"string"},"vignetteUrl":{"type":"string"},"isStereoscopic":{"type":"boolean"},"projectionType":{"type":"string","enum":["flat","sphere","dome","full_dome","cube"]},"formatType":{"type":"string","enum":["2D","3D_Side_By_Side","3D_Over_Under"]},"synopsis":{"type":"string"},"description":{"type":"string"}}}}}},"example":{"devicesId":["string"],"force":false,"videos":[{"id":"string","idDetailContent":"string","title":"string","url":"string","posterUrl":"string","vignetteUrl":"string","isStereoscopic":false,"projectionType":"flat","formatType":"2D","synopsis":"string","description":"string"}]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesVideos","description":"Ajouter des videos a plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"delete":{"tags":["Devices"],"summary":"Supprimer des videos de plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","videos"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"videos":{"type":"array","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"idDetailContent":{"type":"string","nullable":true,"description":"Identifiant de detail de contenu, null ou omis si absent en base"}}}}}},"example":{"devicesId":["string"],"videos":[{"id":"string","idDetailContent":"string"}]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"deleteDevicesVideos","description":"Supprimer des videos de plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/applications":{"patch":{"tags":["Devices"],"summary":"Ajouter des applications a plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","applications"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"force":{"type":"boolean","description":"Force la reinstallation (re-ecrit l entree et notifie le device quel que soit son etat)."},"applications":{"type":"array","items":{"type":"object","required":["packageName","url","codeVersion"],"properties":{"id":{"type":"string"},"packageName":{"type":"string"},"url":{"type":"string"},"codeVersion":{"type":"number"}}}}}},"example":{"devicesId":["string"],"force":false,"applications":[{"id":"string","packageName":"string","url":"string","codeVersion":0}]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesApplications","description":"Ajouter des applications a plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"delete":{"tags":["Devices"],"summary":"Supprimer des applications de plusieurs devices","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["devicesId","applications"],"properties":{"devicesId":{"type":"array","items":{"type":"string"}},"applications":{"type":"array","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"idDetailContent":{"type":"string","nullable":true,"description":"Identifiant de detail de contenu, null ou omis si absent en base"}}}}}},"example":{"devicesId":["string"],"applications":[{"id":"string","idDetailContent":"string"}]}}}},"responses":{"200":{"description":"Resultats par device."},"400":{"description":"Corps invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"deleteDevicesApplications","description":"Supprimer des applications de plusieurs devices. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/packages":{"patch":{"tags":["Devices"],"summary":"Remplacer la liste des packages a maintenir","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}},"example":["string"]}}},"responses":{"200":{"description":"Packages mis a jour."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesDeviceIdPackages","description":"Remplacer la liste des packages a maintenir. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/wifi":{"patch":{"tags":["Devices"],"summary":"Ajouter des reseaux Wi-Fi au device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","required":["ssid","password"],"properties":{"ssid":{"type":"string"},"password":{"type":"string"}}}},"example":[{"ssid":"string","password":"string"}]}}},"responses":{"200":{"description":"Wifi ajoute."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesDeviceIdWifi","description":"Ajouter des reseaux Wi-Fi au device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."},"get":{"tags":["Devices"],"summary":"Recuperer la configuration Wi-Fi d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Liste des reseaux configures."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdWifi","description":"Recuperer la configuration Wi-Fi d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/files/browse":{"get":{"tags":["Devices"],"summary":"Parcourir le systeme de fichiers de l appareil","description":"Liste en temps reel (via Ably) le contenu d un dossier de l appareil. Sans `path`, renvoie les racines disponibles (stockage partage, dossier Pulse, dossier prive app, volumes amovibles). Le perimetre reel reste borne par le scoped storage Android. Pour recuperer le contenu d un fichier, utiliser la route LAN du device `http://<deviceIp>:<port>/file/raw?path=<absolutePath>`.\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"query","name":"path","required":false,"schema":{"type":"string"},"description":"Chemin absolu du dossier a lister. Absent => racines de depart."},{"in":"query","name":"offset","required":false,"schema":{"type":"integer"},"description":"Index de depart pour la pagination."},{"in":"query","name":"limit","required":false,"schema":{"type":"integer"},"description":"Nombre max d entrees renvoyees (defaut 500, borne)."}],"responses":{"200":{"description":"Reponse du device { success, data }. `data` = { path, parent, entries[], total, truncated }. Chaque entree = { name, absolutePath, isDirectory, sizeBytes, lastModified, canRead }.\n"},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device injoignable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdFilesBrowse"}},"/devices/{deviceId}/logs/stream":{"get":{"tags":["Devices"],"summary":"Flux de logs de l appareil en direct (SSE)","description":"Ouvre un flux Server-Sent Events (text/event-stream) qui relaie en temps reel les lignes de logcat de l appareil. Le casque ne capture les logs que pendant qu au moins un client est connecte (demarrage/arret a la demande via Ably). Chaque evenement `data:` contient un lot de lignes `{ lines: string[], ts: number }`.\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."},{"in":"query","name":"priority","required":false,"schema":{"type":"string","enum":["V","D","I","W","E"]},"description":"Niveau minimum logcat (V=tout ... E=erreurs). Defaut V."}],"responses":{"200":{"description":"Flux SSE ouvert.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdLogsStream"}},"/devices/{deviceId}/sdk/stream":{"get":{"tags":["Devices"],"summary":"Flux d etat Pulse SDK en direct (SSE)","description":"Ouvre un flux Server-Sent Events qui relaie l etat du Pulse SDK du casque en temps reel - SCHEMA (a la connexion de l app et sur resynchronisation), DELTA (variables, throttles 5 Hz), presence SDK_ONLINE/SDK_OFFLINE. Le casque n emet que pendant qu au moins un client est connecte (demarrage/arret a la demande via Ably).\n","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Flux SSE ouvert.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getDevicesDeviceIdSdkStream"}},"/devices/{deviceId}/networks-available":{"patch":{"tags":["Devices"],"summary":"Mettre a jour les reseaux disponibles detectes","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"ssid":{"type":"string"},"level":{"type":"number"},"frequency":{"type":"number"}}}},"example":[{"ssid":"string","level":0,"frequency":0}]}}},"responses":{"200":{"description":"Reseaux enregistres."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesDeviceIdNetworksAvailable","description":"Mettre a jour les reseaux disponibles detectes. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/devices/{deviceId}/current-content":{"patch":{"tags":["Devices"],"summary":"Mettre a jour le contenu courant d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","description":"Objet currentContent ou vide/null pour effacer."},"example":{}}}},"responses":{"200":{"description":"Contenu courant mis a jour ou efface."},"400":{"description":"Champ type manquant ou invalide."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"patchDevicesDeviceIdCurrentContent","description":"Mettre a jour le contenu courant d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/enterprises/enrollment":{"post":{"tags":["Enterprises"],"summary":"Generer un token d enrollment pour l entreprise courante","description":"Utilise le bearer courant pour generer un token et un device associe. Le corps peut contenir des donnees additionnelles.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"additionalData":{"type":"string","description":"Donnee additionnelle transmise a Android Management."}}},"example":{"additionalData":"string"}}}},"responses":{"200":{"description":"Token d enrollment genere."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Entreprise non trouvee pour le bearer courant."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur lors de la creation du token."}},"operationId":"postEnterprisesEnrollment"}},"/enterprises/{id}":{"get":{"tags":["Enterprises"],"summary":"Recuperer une entreprise par ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Paramètre id transmis dans path."}],"responses":{"200":{"description":"Entreprise trouvee."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token rattaché à aucune entreprise."},"404":{"description":"Entreprise inexistante, ou autre que celle du token."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"description":"Un token d'entreprise ne lit que sa propre entreprise, sans ses tokens API. Le credential plateforme (Pulse Web) lit toute entreprise, `tokens` compris.\n","operationId":"getEnterprisesId"},"put":{"tags":["Enterprises"],"summary":"Mettre a jour une entreprise","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Paramètre id transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Nom de l'entreprise.","minLength":3,"maxLength":100},"description":{"type":"string","description":"Description libre de l'entreprise. Une chaîne vide l'efface."},"policy":{"type":"string","description":"Politique Android Management sérialisée en JSON. Elle doit contenir `applications[0].managedConfiguration`, où le serveur inscrit l'identifiant de l'entreprise."},"mikrotik":{"type":"object","description":"Routeur MikroTik de l'entreprise, qui sert à résoudre la MAC des appareils. Seules les clés fournies sont modifiées.","properties":{"enabled":{"type":"boolean","description":"Active la résolution MAC par ce routeur."},"host":{"type":"string","description":"Adresse publique du routeur (nom ou IP). Une adresse privée, locale ou réservée est refusée."},"port":{"type":"integer","description":"Port de l'API REST du routeur. Par défaut 443 en HTTPS, 80 en HTTP.","minimum":1,"maximum":65535},"useTls":{"type":"boolean","description":"Appelle le routeur en HTTPS. Activé par défaut."},"allowSelfSigned":{"type":"boolean","description":"Accepte un certificat auto-signé. Activé par défaut."},"username":{"type":"string","description":"Utilisateur de l'API du routeur."},"password":{"type":"string","writeOnly":true,"description":"Mot de passe de l'API du routeur. Jamais renvoyé ; s'il est omis, il reste inchangé."}}},"fleetAccess":{"type":"array","items":{"type":"string"},"uniqueItems":true,"description":"Réservé au credential plateforme. Entreprises dont celle-ci voit et pilote aussi les casques, comme les siens, par exemple la flotte Pulse. Une liste vide retire l'accès."}}},"example":{"name":"string","description":"string","policy":"string","mikrotik":{"enabled":false,"host":"string","port":1,"useTls":false,"allowSelfSigned":false,"username":"string","password":"string"},"fleetAccess":["string"]}}}},"responses":{"200":{"description":"Entreprise mise a jour."},"400":{"description":"Champ invalide : type, politique, hôte MikroTik non public, ou `fleetAccess` incorrect (l'entreprise elle-même, une entreprise inconnue, un doublon)."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token rattaché à aucune entreprise, ou `fleetAccess` envoyé par un autre token que la plateforme."},"404":{"description":"Entreprise inexistante, ou autre que celle du token."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"description":"Un token d'entreprise ne modifie que sa propre entreprise ; le credential plateforme modifie toute entreprise. Seuls les champs fournis sont modifiés.\n","operationId":"putEnterprisesId"}},"/enterprises":{"post":{"tags":["Enterprises"],"summary":"Creer une nouvelle entreprise et generer un bearer JWT","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":3,"maxLength":100},"expiresAt":{"type":"string","format":"date-time","description":"Date d expiration du token genere (facultatif)."}}},"example":{"name":"string","expiresAt":"2026-01-01T12:00:00.000Z"}}}},"responses":{"201":{"description":"Entreprise creee avec token associe."},"400":{"description":"Données invalides : nom, ou date d'expiration passée."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token autre que le credential plateforme."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"description":"Réservé au credential plateforme (Pulse Web). La réponse contient l'identifiant de la nouvelle entreprise (`id`) et son token API, dans `tokens`.\n","operationId":"postEnterprises"}},"/":{"get":{"tags":["General"],"summary":"Page d accueil serveur","description":"Retourne une page HTML simple avec un lien vers la documentation Pulse.","responses":{"200":{"description":"Page HTML de redirection vers la documentation."},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[],"operationId":"get"}},"/pulse-build":{"get":{"tags":["Build"],"summary":"Telecharger l APK de service Pulse","description":"Retourne le fichier `pulse-service.apk` a partir du dossier public/build.","responses":{"200":{"description":"Fichier APK renvoye en telechargement."},"500":{"description":"Erreur serveur lors de l envoi du fichier."}},"security":[],"operationId":"getPulseBuild"}},"/pulse-build/info":{"get":{"tags":["Build"],"summary":"Obtenir les informations du fichier APK","description":"Retourne les métadonnées du fichier `pulse-service.apk` (package, versionCode, versionName).","responses":{"200":{"description":"Informations sur l'APK.","content":{"application/json":{"schema":{"type":"object","properties":{"package":{"type":"string"},"versionCode":{"type":"integer"},"versionName":{"type":"string"}}}}}},"500":{"description":"Erreur serveur lors de la lecture des infos."}},"security":[],"operationId":"getPulseBuildInfo"}},"/pulse-build/{codeVersion}":{"get":{"tags":["Build"],"summary":"Telecharger l APK si une version plus recente existe","parameters":[{"in":"path","name":"codeVersion","required":true,"schema":{"type":"integer"},"description":"Version code actuelle du client pour comparer a la version du fichier."}],"responses":{"200":{"description":"Fichier APK renvoye lorsque la version distante est plus recente."},"400":{"description":"Version demandee invalide."},"404":{"description":"Aucune version plus recente disponible."},"500":{"description":"Erreur serveur lors de la lecture ou de l envoi."}},"security":[],"operationId":"getPulseBuildCodeVersion","description":"Telecharger l APK si une version plus recente existe. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings/new":{"post":{"tags":["Readings"],"summary":"Creer une lecture (reading)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["deviceId","contentId","startDate","uniqueId"],"properties":{"deviceId":{"type":"string"},"contentId":{"type":"string"},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"uniqueId":{"type":"string"}}},"example":{"deviceId":"string","contentId":"string","startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","uniqueId":"string"}}}},"responses":{"201":{"description":"Lecture creee."},"400":{"description":"Donnees invalides."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"postReadingsNew","description":"Creer une lecture (reading). Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings/{uniqueId}/events":{"put":{"tags":["Readings"],"summary":"Ajouter un evenement a une lecture","parameters":[{"in":"path","name":"uniqueId","required":true,"schema":{"type":"string"},"description":"Paramètre uniqueId transmis dans path."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["eventType","timestamp"],"properties":{"eventType":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"example":{"eventType":"string","timestamp":"2026-01-01T12:00:00.000Z"}}}},"responses":{"200":{"description":"Evenement ajoute."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur ou lecture introuvable."}},"operationId":"putReadingsUniqueIdEvents","description":"Ajouter un evenement a une lecture. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings/feed":{"get":{"tags":["Readings"],"summary":"Feed d'activite pagine (lectures individuelles)","description":"Retourne les lectures triees par date decroissante, paginées.","parameters":[{"in":"query","name":"page","schema":{"type":"integer","default":1},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer","default":20},"description":"Paramètre limit transmis dans query."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"deviceIds","schema":{"type":"array","items":{"type":"string"}},"description":"Paramètre deviceIds transmis dans query."},{"in":"query","name":"contentIds","schema":{"type":"array","items":{"type":"string"}},"description":"Paramètre contentIds transmis dans query."}],"responses":{"200":{"description":"Liste paginee des lectures triees par date decroissante."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getReadingsFeed"}},"/readings/{id}":{"get":{"tags":["Readings"],"summary":"Recuperer une lecture par ID ou uniqueId","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Paramètre id transmis dans path."}],"responses":{"200":{"description":"Lecture retournee."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Lecture non trouvee."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getReadingsId","description":"Recuperer une lecture par ID ou uniqueId. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings":{"post":{"tags":["Readings"],"summary":"Lister des lectures avec filtres","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"readingIds":{"type":"array","items":{"type":"string"}},"deviceIds":{"type":"array","items":{"type":"string"}},"contentIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"offset":{"type":"integer"},"limit":{"type":"integer"}}},"example":{"readingIds":["string"],"deviceIds":["string"],"contentIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","offset":0,"limit":0}}}},"responses":{"200":{"description":"Liste paginee des lectures (peut etre vide)."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postReadings","description":"Lister des lectures avec filtres. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings/stats":{"post":{"tags":["Readings"],"summary":"Statistiques de lectures par filtres","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"readingIds":{"type":"array","items":{"type":"string"}},"deviceIds":{"type":"array","items":{"type":"string"}},"contentIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"}}},"example":{"readingIds":["string"],"deviceIds":["string"],"contentIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z"}}}},"responses":{"200":{"description":"Statistiques retournees (peut etre vide)."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postReadingsStats","description":"Statistiques de lectures par filtres. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/readings/stats/advanced":{"post":{"tags":["Readings"],"summary":"Statistiques avancees de lectures","description":"Retourne un ensemble complet de statistiques:\n- Periode: duree totale, moyenne, min, max, devices uniques\n- Par contenu: duree totale/moyenne, taux de completion, nombre de seeks\n- Par device: lectures, duree, dernier contenu joue\n- Par jour/semaine/mois: nombre de lectures et duree totale\n- Sessions: moyenne de pauses et seeks par session\n","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"readingIds":{"type":"array","items":{"type":"string"}},"deviceIds":{"type":"array","items":{"type":"string"}},"contentIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"}}},"example":{"readingIds":["string"],"deviceIds":["string"],"contentIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z"}}}},"responses":{"200":{"description":"Statistiques avancees retournees."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postReadingsStatsAdvanced"}},"/readings/stats/heatmap":{"post":{"tags":["Readings"],"summary":"Heatmap des lectures par jour de semaine et heure","description":"Agrege les lectures par creneau horaire (0-23) et jour de la semaine\n(1=dimanche a 7=samedi).\nPermet de visualiser une matrice 7x24 des heures de pointe.\n","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"contentIds":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"}}},"example":{"deviceIds":["string"],"contentIds":["string"],"startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z"}}}},"responses":{"200":{"description":"Heatmap retournee."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postReadingsStatsHeatmap"}},"/readings/synchronize":{"post":{"tags":["Readings"],"summary":"Synchroniser un lot de lectures et evenements","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["readings"],"properties":{"readings":{"type":"array","items":{"type":"object","required":["reading","events"],"properties":{"reading":{"type":"object","required":["deviceId","contentId","startDate","uniqueId"],"properties":{"deviceId":{"type":"string"},"contentId":{"type":"string"},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"uniqueId":{"type":"string"}}},"events":{"type":"array","items":{"type":"object","required":["eventType","timestamp"],"properties":{"eventType":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}}}},"example":{"readings":[{"reading":{"deviceId":"string","contentId":"string","startDate":"2026-01-01T12:00:00.000Z","endDate":"2026-01-01T12:00:00.000Z","uniqueId":"string"},"events":[{"eventType":"string","timestamp":"2026-01-01T12:00:00.000Z"}]}]}}}},"responses":{"200":{"description":"Lectures synchronisees."},"400":{"description":"Requête invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postReadingsSynchronize","description":"Synchroniser un lot de lectures et evenements. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/settings-catalog":{"get":{"tags":["Settings catalog"],"summary":"Obtenir le catalogue complet des paramètres configurables","description":"Renvoie l'ensemble des paramètres exposés par l'API MDM Pulse, avec pour chacun :\nson type, ses bornes / valeurs possibles, sa valeur par défaut et la liste des marques\nde casques (Pico, HTC, Meta, generic) qui appliquent réellement ce paramètre.\n\nCet endpoint est destiné à alimenter une UI de configuration : la console peut\ngénérer dynamiquement les formulaires en fonction du modèle de casque ciblé.\n","responses":{"200":{"description":"Catalogue complet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsCatalog"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getSettingsCatalog"}},"/settings-catalog/{brand}":{"get":{"tags":["Settings catalog"],"summary":"Obtenir le sous-catalogue pour une marque","description":"Renvoie uniquement les paramètres réellement appliqués par les casques de la marque\ndemandée. Utile pour générer un formulaire ciblé pour un device dont on connaît la marque.\n","parameters":[{"in":"path","name":"brand","required":true,"schema":{"type":"string","enum":["pico","htc","meta","generic"]},"description":"Paramètre brand transmis dans path."}],"responses":{"200":{"description":"Sous-catalogue de la marque.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCatalog"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Marque inconnue."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getSettingsCatalogBrand"}},"/stats":{"get":{"tags":["Stats"],"summary":"Liste brute des logs d usage","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"page","schema":{"type":"integer","default":1},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer","default":10},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Liste paginee des requetes journalisees."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStats","description":"Liste brute des logs d usage. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stats/synthese":{"get":{"tags":["Stats"],"summary":"Synthese globale des requetes","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."}],"responses":{"200":{"description":"Statistiques agregees (totaux, top routes, complexite)."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStatsSynthese","description":"Synthese globale des requetes. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stats/routes":{"get":{"tags":["Stats"],"summary":"Routes les plus sollicitees","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"page","schema":{"type":"integer"},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Aggregation des routes par volume de requetes."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStatsRoutes","description":"Routes les plus sollicitees. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stats/devices":{"get":{"tags":["Stats"],"summary":"Statistiques par device","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"page","schema":{"type":"integer"},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Nombre de requetes par device."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStatsDevices","description":"Statistiques par device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stats/complexity":{"get":{"tags":["Stats"],"summary":"Scores de complexite moyens par entreprise","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"page","schema":{"type":"integer"},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Classement des complexites."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStatsComplexity","description":"Scores de complexite moyens par entreprise. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stats/requests":{"get":{"tags":["Stats"],"summary":"Nombre de requetes par entreprise","parameters":[{"in":"query","name":"enterpriseId","schema":{"type":"string"},"description":"Facultatif : seule l'entreprise du credential est acceptée (403 sinon). Les flottes partagées (`fleetAccess`) ne s'appliquent pas aux statistiques d'usage de l'API."},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre startDate transmis dans query."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"Paramètre endDate transmis dans query."},{"in":"query","name":"page","schema":{"type":"integer"},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Classement des entreprises par volume."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStatsRequests","description":"Nombre de requetes par entreprise. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/stream-history/event":{"post":{"tags":["Streaming"],"summary":"Enregistrer un evenement de streaming","description":"Utilise les callbacks (pathReady, pathClosed) pour ouvrir ou clore un stream associe a un device.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","path"],"properties":{"event":{"type":"string","enum":["pathReady","pathClosed"]},"path":{"type":"string","example":"stream/{deviceId}"},"origin":{"type":"string","description":"Source de l evenement (optionnel)."}}},"example":{"event":"pathReady","path":"stream/{deviceId}","origin":"string"}}}},"responses":{"200":{"description":"Stream cloture ou aucun stream a clore."},"201":{"description":"Stream ouvert et historise."},"400":{"description":"Parametres invalides."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"postStreamHistoryEvent"}},"/stream-history/{deviceId}":{"get":{"tags":["Streaming"],"summary":"Recuperer l historique de streaming d un device","parameters":[{"in":"path","name":"deviceId","required":true,"schema":{"type":"string"},"description":"Paramètre deviceId transmis dans path."}],"responses":{"200":{"description":"Historique classe par date de debut."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Device introuvable."},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur serveur."}},"operationId":"getStreamHistoryDeviceId","description":"Recuperer l historique de streaming d un device. Vérifiez l’organisation cible et les identifiants des ressources avant l’envoi."}},"/contents/{contentId}/revocations":{"get":{"tags":["Contents"],"summary":"Suivre les retraits d'un contenu sur la flotte","description":"Repond a « ce contenu est-il encore detenu par des appareils apres sa demande de retrait ? » en une requete, sans enumerer la flotte. La reponse ne contient que les revocations du contenu demande.","parameters":[{"in":"path","name":"contentId","required":true,"schema":{"type":"string"},"description":"Identifiant du contenu (application, video ou fichier)."},{"in":"query","name":"status","required":false,"schema":{"type":"string","enum":["pending","confirmed","cancelled_reassigned","closed_device_retired"]},"description":"Restreint aux revocations dans cet etat. Absent : tous les etats."},{"in":"query","name":"page","required":false,"schema":{"type":"integer","default":1,"minimum":1},"description":"Paramètre page transmis dans query."},{"in":"query","name":"limit","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":100},"description":"Paramètre limit transmis dans query."}],"responses":{"200":{"description":"Revocations du contenu, par appareil.","content":{"application/json":{"schema":{"type":"object","properties":{"contentId":{"type":"string"},"status":{"type":"string","nullable":true},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"deviceId":{"type":"string"},"label":{"type":"string"},"androidId":{"type":"string"},"isArchived":{"type":"boolean"},"revocations":{"type":"array","items":{"$ref":"#/components/schemas/ContentRevocation"}}}}}}}}}},"400":{"description":"Statut inconnu."},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getContentsContentIdRevocations"}},"/stats/activity":{"get":{"tags":["Stats"],"summary":"Résumé de l'activité de la flotte","description":"Totaux, compteurs par famille et chronologie par jour, semaine ou mois. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`.","parameters":[{"in":"query","name":"startDate","required":false,"description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure.","schema":{"type":"string","example":"2026-09-01"}},{"in":"query","name":"endDate","required":false,"description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure.","schema":{"type":"string","example":"2026-09-30"}},{"in":"query","name":"timezone","required":false,"description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté).","schema":{"type":"string","default":"UTC","example":"Europe/Paris"}},{"in":"query","name":"deviceIds[]","required":false,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST.","schema":{"type":"array","items":{"type":"string"},"maxItems":1000},"style":"form","explode":true},{"in":"query","name":"eventTypes[]","required":false,"description":"Types d'événements à retenir.","schema":{"type":"array","items":{"type":"string"},"maxItems":50},"style":"form","explode":true},{"in":"query","name":"contentId","required":false,"description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package.","schema":{"type":"string"}},{"in":"query","name":"packageName","required":false,"description":"Package à retenir.","schema":{"type":"string"}},{"in":"query","name":"enterpriseId","required":false,"description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403.","schema":{"type":"string"}},{"in":"query","name":"granularity","required":false,"description":"Découpage de la chronologie.","schema":{"type":"string","enum":["day","week","month"],"default":"day"}}],"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivitySummary"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getStatsActivity"},"post":{"tags":["Stats"],"summary":"Résumé de l'activité de la flotte (filtres dans le corps)","description":"Totaux, compteurs par famille et chronologie par jour, semaine ou mois. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`. Variante POST : mêmes filtres dans le corps JSON, pour les longues listes d'appareils. Les paramètres de l'URL restent lus, le corps l'emportant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-09-01","description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure."},"endDate":{"type":"string","example":"2026-09-30","description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure."},"timezone":{"type":"string","default":"UTC","example":"Europe/Paris","description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté)."},"deviceIds":{"type":"array","items":{"type":"string"},"maxItems":1000,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST."},"eventTypes":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Types d'événements à retenir."},"contentId":{"type":"string","description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package."},"packageName":{"type":"string","description":"Package à retenir."},"enterpriseId":{"type":"string","description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403."},"granularity":{"type":"string","enum":["day","week","month"],"default":"day","description":"Découpage de la chronologie."}}},"example":{"startDate":"2026-09-01","endDate":"2026-09-30","timezone":"Europe/Paris","granularity":"week"}}}},"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivitySummary"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"postStatsActivity"}},"/stats/activity/events":{"get":{"tags":["Stats"],"summary":"Activité par type d'événement","description":"Répartition par type d'événement, le plus fréquent d'abord. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`.","parameters":[{"in":"query","name":"startDate","required":false,"description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure.","schema":{"type":"string","example":"2026-09-01"}},{"in":"query","name":"endDate","required":false,"description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure.","schema":{"type":"string","example":"2026-09-30"}},{"in":"query","name":"timezone","required":false,"description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté).","schema":{"type":"string","default":"UTC","example":"Europe/Paris"}},{"in":"query","name":"deviceIds[]","required":false,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST.","schema":{"type":"array","items":{"type":"string"},"maxItems":1000},"style":"form","explode":true},{"in":"query","name":"eventTypes[]","required":false,"description":"Types d'événements à retenir.","schema":{"type":"array","items":{"type":"string"},"maxItems":50},"style":"form","explode":true},{"in":"query","name":"contentId","required":false,"description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package.","schema":{"type":"string"}},{"in":"query","name":"packageName","required":false,"description":"Package à retenir.","schema":{"type":"string"}},{"in":"query","name":"enterpriseId","required":false,"description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403.","schema":{"type":"string"}},{"in":"query","name":"page","required":false,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400.","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"in":"query","name":"limit","required":false,"description":"Taille de page, plafonnée à 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityEventTypePage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getStatsActivityEvents"},"post":{"tags":["Stats"],"summary":"Activité par type d'événement (filtres dans le corps)","description":"Répartition par type d'événement, le plus fréquent d'abord. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`. Variante POST : mêmes filtres dans le corps JSON, pour les longues listes d'appareils. Les paramètres de l'URL restent lus, le corps l'emportant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-09-01","description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure."},"endDate":{"type":"string","example":"2026-09-30","description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure."},"timezone":{"type":"string","default":"UTC","example":"Europe/Paris","description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté)."},"deviceIds":{"type":"array","items":{"type":"string"},"maxItems":1000,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST."},"eventTypes":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Types d'événements à retenir."},"contentId":{"type":"string","description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package."},"packageName":{"type":"string","description":"Package à retenir."},"enterpriseId":{"type":"string","description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403."},"page":{"type":"integer","minimum":1,"maximum":100000,"default":1,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Taille de page, plafonnée à 100."}}},"example":{"startDate":"2026-09-01","endDate":"2026-09-30","timezone":"Europe/Paris","page":1,"limit":50}}}},"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityEventTypePage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"postStatsActivityEvents"}},"/stats/activity/devices":{"get":{"tags":["Stats"],"summary":"Activité par appareil","description":"Répartition par appareil, le plus actif d'abord. Un appareil supprimé reste listé, décrit par sa fiche figée à la suppression. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`.","parameters":[{"in":"query","name":"startDate","required":false,"description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure.","schema":{"type":"string","example":"2026-09-01"}},{"in":"query","name":"endDate","required":false,"description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure.","schema":{"type":"string","example":"2026-09-30"}},{"in":"query","name":"timezone","required":false,"description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté).","schema":{"type":"string","default":"UTC","example":"Europe/Paris"}},{"in":"query","name":"deviceIds[]","required":false,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST.","schema":{"type":"array","items":{"type":"string"},"maxItems":1000},"style":"form","explode":true},{"in":"query","name":"eventTypes[]","required":false,"description":"Types d'événements à retenir.","schema":{"type":"array","items":{"type":"string"},"maxItems":50},"style":"form","explode":true},{"in":"query","name":"contentId","required":false,"description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package.","schema":{"type":"string"}},{"in":"query","name":"packageName","required":false,"description":"Package à retenir.","schema":{"type":"string"}},{"in":"query","name":"enterpriseId","required":false,"description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403.","schema":{"type":"string"}},{"in":"query","name":"page","required":false,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400.","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"in":"query","name":"limit","required":false,"description":"Taille de page, plafonnée à 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityDevicePage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getStatsActivityDevices"},"post":{"tags":["Stats"],"summary":"Activité par appareil (filtres dans le corps)","description":"Répartition par appareil, le plus actif d'abord. Un appareil supprimé reste listé, décrit par sa fiche figée à la suppression. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`. Variante POST : mêmes filtres dans le corps JSON, pour les longues listes d'appareils. Les paramètres de l'URL restent lus, le corps l'emportant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-09-01","description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure."},"endDate":{"type":"string","example":"2026-09-30","description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure."},"timezone":{"type":"string","default":"UTC","example":"Europe/Paris","description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté)."},"deviceIds":{"type":"array","items":{"type":"string"},"maxItems":1000,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST."},"eventTypes":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Types d'événements à retenir."},"contentId":{"type":"string","description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package."},"packageName":{"type":"string","description":"Package à retenir."},"enterpriseId":{"type":"string","description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403."},"page":{"type":"integer","minimum":1,"maximum":100000,"default":1,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Taille de page, plafonnée à 100."}}},"example":{"startDate":"2026-09-01","endDate":"2026-09-30","timezone":"Europe/Paris","page":1,"limit":50}}}},"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityDevicePage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"postStatsActivityDevices"}},"/stats/activity/contents":{"get":{"tags":["Stats"],"summary":"Activité par contenu","description":"Répartition par contenu avec taux d'échec. Une application est identifiée par son package, une vidéo ou un fichier par son identifiant. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`.","parameters":[{"in":"query","name":"startDate","required":false,"description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure.","schema":{"type":"string","example":"2026-09-01"}},{"in":"query","name":"endDate","required":false,"description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure.","schema":{"type":"string","example":"2026-09-30"}},{"in":"query","name":"timezone","required":false,"description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté).","schema":{"type":"string","default":"UTC","example":"Europe/Paris"}},{"in":"query","name":"deviceIds[]","required":false,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST.","schema":{"type":"array","items":{"type":"string"},"maxItems":1000},"style":"form","explode":true},{"in":"query","name":"eventTypes[]","required":false,"description":"Types d'événements à retenir.","schema":{"type":"array","items":{"type":"string"},"maxItems":50},"style":"form","explode":true},{"in":"query","name":"contentId","required":false,"description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package.","schema":{"type":"string"}},{"in":"query","name":"packageName","required":false,"description":"Package à retenir.","schema":{"type":"string"}},{"in":"query","name":"enterpriseId","required":false,"description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403.","schema":{"type":"string"}},{"in":"query","name":"page","required":false,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400.","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"in":"query","name":"limit","required":false,"description":"Taille de page, plafonnée à 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityContentPage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"getStatsActivityContents"},"post":{"tags":["Stats"],"summary":"Activité par contenu (filtres dans le corps)","description":"Répartition par contenu avec taux d'échec. Une application est identifiée par son package, une vidéo ou un fichier par son identifiant. Calculé sur les agrégats horaires de `DeviceEventHistory`, conservés sans limite de durée (l'historique brut expire après 180 jours). Un événement y apparaît dans la minute. Distinct des métriques d'usage de l'API servies par les autres routes `/stats`. Variante POST : mêmes filtres dans le corps JSON, pour les longues listes d'appareils. Les paramètres de l'URL restent lus, le corps l'emportant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","example":"2026-09-01","description":"Début inclus. Seul : depuis cette date jusqu'à maintenant. Une date sans heure commence à minuit dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Ramené au début de son heure."},"endDate":{"type":"string","example":"2026-09-30","description":"Fin incluse. Seule : tout l'historique jusqu'à cette date. Une date sans heure couvre toute la journée dans `timezone`, une date-heure sans décalage est une heure de `timezone`. Étendue à la fin de son heure."},"timezone":{"type":"string","default":"UTC","example":"Europe/Paris","description":"Fuseau IANA des bornes et de la chronologie, insensible à la casse (`europe/paris` est accepté)."},"deviceIds":{"type":"array","items":{"type":"string"},"maxItems":1000,"description":"Appareils à retenir, 1000 au plus. En GET, l'URL plafonne vers 350 identifiants : au-delà, utiliser POST."},"eventTypes":{"type":"array","items":{"type":"string"},"maxItems":50,"description":"Types d'événements à retenir."},"contentId":{"type":"string","description":"Contenu à retenir. Pour une application, inclut aussi les événements de son package."},"packageName":{"type":"string","description":"Package à retenir."},"enterpriseId":{"type":"string","description":"Entreprise à couvrir : celle du credential par défaut, ou une flotte que la plateforme lui a ouverte (`fleetAccess`). Toute autre entreprise donne un 403."},"page":{"type":"integer","minimum":1,"maximum":100000,"default":1,"description":"Page demandée, à partir de 1. Au-delà de 100 000 : 400."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Taille de page, plafonnée à 100."}}},"example":{"startDate":"2026-09-01","endDate":"2026-09-30","timezone":"Europe/Paris","page":1,"limit":50}}}},"responses":{"200":{"description":"Statistiques calculées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityContentPage"}}}},"400":{"description":"Paramètre invalide (date, fuseau, granularité, identifiant, page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"401":{"description":"Jeton absent ou invalide.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Entreprise ou appareil hors du périmètre du credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityError"}}}},"429":{"description":"Trop de requêtes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erreur interne du serveur.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"operationId":"postStatsActivityContents"}}},"components":{"schemas":{"DeviceSettings":{"type":"object","properties":{"kioskMode":{"type":"boolean","description":"Valeur de kioskMode."},"developerSettingsAllowed":{"type":"boolean","description":"Valeur de developerSettingsAllowed."},"applications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"idDetailContent":{"type":"string","nullable":true},"packageName":{"type":"string"},"url":{"type":"string"},"codeVersion":{"type":"number"},"obbUrl":{"type":"string","nullable":true},"deployment":{"$ref":"#/components/schemas/ContentStatusSnapshot"}}},"description":"Valeur de applications."},"videos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"idDetailContent":{"type":"string","nullable":true,"description":"Reference a la fiche contenu, null ou omis si absent."},"title":{"type":"string"},"url":{"type":"string"},"posterUrl":{"type":"string"},"vignetteUrl":{"type":"string"},"isStereoscopic":{"type":"boolean"},"projectionType":{"type":"string","enum":["flat","sphere","dome","full_dome","cube"]},"formatType":{"type":"string","enum":["2D","3D_Side_By_Side","3D_Over_Under"]},"synopsis":{"type":"string"},"description":{"type":"string"},"deployment":{"$ref":"#/components/schemas/ContentStatusSnapshot"}}},"description":"Valeur de videos."},"files":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"deployment":{"$ref":"#/components/schemas/ContentStatusSnapshot"}}},"description":"Valeur de files."},"packages":{"type":"array","items":{"type":"string"},"description":"Valeur de packages."},"wifi":{"type":"array","items":{"type":"object","properties":{"ssid":{"type":"string"},"password":{"type":"string"}}},"description":"Valeur de wifi."},"video360":{"type":"array","items":{"type":"object"},"description":"Valeur de video360."},"volume":{"type":"number","minimum":0,"maximum":100,"description":"Alias historique de audio.multimedia."},"isOfflineEnabled":{"type":"boolean","description":"Valeur de isOfflineEnabled."},"isContentDownloadAllowed":{"type":"boolean","description":"Valeur de isContentDownloadAllowed."},"isLanDiscoveryEnabled":{"type":"boolean","description":"Valeur de isLanDiscoveryEnabled."},"isScreensharingEnabled":{"type":"boolean","description":"Valeur de isScreensharingEnabled."},"isLanIntercomEnabled":{"type":"boolean","description":"Valeur de isLanIntercomEnabled."},"display":{"type":"object","description":"Paramètres d'affichage (luminosité, refresh rate, IPD, passthrough, boundary).","properties":{"brightness":{"type":"integer","minimum":0,"maximum":100},"refreshRate":{"type":"integer","enum":[60,72,90,120]},"ipdMm":{"type":"number","minimum":58,"maximum":72},"passthroughEnabled":{"type":"boolean"},"guardianEnabled":{"type":"boolean"},"boundaryConfirmDialog":{"type":"boolean"},"bootAnimationEnabled":{"type":"boolean"},"chargingAnimationEnabled":{"type":"boolean"}}},"audio":{"type":"object","description":"Volumes par flux (0–100 chacun).","properties":{"multimedia":{"type":"integer","minimum":0,"maximum":100},"notification":{"type":"integer","minimum":0,"maximum":100},"alarm":{"type":"integer","minimum":0,"maximum":100},"system":{"type":"integer","minimum":0,"maximum":100}}},"power":{"type":"object","properties":{"screenOffDelaySec":{"type":"integer","minimum":0},"autoSleepDelaySec":{"type":"integer","minimum":0},"autoSleepOnTakeoff":{"type":"boolean"},"powerKeyShort":{"type":"string","enum":["sleep","shutdown","none"]},"powerKeyLong":{"type":"string","enum":["sleep","shutdown","menu","none"]},"scheduledStartup":{"type":"string","description":"Format HH:MM 24h"},"scheduledShutdown":{"type":"string","description":"Format HH:MM 24h"}},"description":"Valeur de power."},"system":{"type":"object","properties":{"countryCode":{"type":"string"},"locale":{"type":"string"},"timezone":{"type":"string"},"autoTime":{"type":"boolean"},"ntpServer":{"type":"string"},"lockScreenEnabled":{"type":"boolean"},"lockScreenPasscodeEnabled":{"type":"boolean"},"showAppQuitConfirmDialog":{"type":"boolean"},"killBackgroundVrApp":{"type":"boolean"},"keepAlivePackages":{"type":"array","items":{"type":"string"}},"allowUnknownSources":{"type":"boolean"},"developerOptionsEnabled":{"type":"boolean"},"defaultLauncherPackage":{"type":"string"}},"description":"Valeur de system."},"security":{"type":"object","properties":{"usbEnabled":{"type":"boolean"},"usbFileTransferEnabled":{"type":"boolean"},"usbDebuggingEnabled":{"type":"boolean"},"usbTetheringEnabled":{"type":"boolean"},"bluetoothEnabled":{"type":"boolean"},"bluetoothTetheringEnabled":{"type":"boolean"},"wifiTetheringEnabled":{"type":"boolean"},"microphoneEnabled":{"type":"boolean"},"locationEnabled":{"type":"boolean"},"screenCastEnabled":{"type":"boolean"},"screenshotAllowed":{"type":"boolean"},"cameraEnabled":{"type":"boolean"},"factoryResetProtection":{"type":"boolean"}},"description":"Valeur de security."},"tracking":{"type":"object","properties":{"eyeTrackingEnabled":{"type":"boolean"},"faceTrackingEnabled":{"type":"boolean"},"handTrackingEnabled":{"type":"boolean"},"bodyTrackingEnabled":{"type":"boolean"},"trackingOrigin":{"type":"string","enum":["eye","floor"]},"sixDof":{"type":"boolean"},"controllerVibration":{"type":"boolean"}},"description":"Valeur de tracking."},"shortcuts":{"type":"object","properties":{"recordEnabled":{"type":"boolean"},"castEnabled":{"type":"boolean"},"captureEnabled":{"type":"boolean"},"settingsEnabled":{"type":"boolean"},"recenterEnabled":{"type":"boolean"},"backEnabled":{"type":"boolean"},"fitEnabled":{"type":"boolean"}},"description":"Valeur de shortcuts."},"network":{"type":"object","properties":{"wifiEnabled":{"type":"boolean"},"wifiP2pEnabled":{"type":"boolean"},"otaPolicy":{"type":"string","enum":["auto","manual","disabled"]},"otaServerUrl":{"type":"string"},"globalProxy":{"type":"object","properties":{"use":{"type":"boolean"},"host":{"type":"string"},"port":{"type":"integer"},"byPass":{"type":"string"}}}},"description":"Valeur de network."}},"description":"Modèle de données DeviceSettings."},"InstalledPackage":{"type":"object","required":["packageName","versionCode"],"properties":{"packageName":{"type":"string","description":"Identifiant du package Android installe."},"versionCode":{"type":"integer","description":"Code de version installe."},"versionName":{"type":"string","nullable":true,"description":"Nom de version lisible, lorsqu il est disponible."}},"description":"Modèle de données InstalledPackage."},"ContentPresence":{"type":"object","required":["type","present"],"properties":{"contentId":{"type":"string","nullable":true,"description":"Nul pour une application presente sur le disque alors qu'elle n'est plus affectee : le repertoire des applications est indexe par packageName. Toujours renseigne pour une video ou un fichier."},"type":{"type":"string","enum":["application","video","file"],"description":"Valeur de type."},"packageName":{"type":"string","nullable":true,"description":"Valeur de packageName."},"present":{"type":"boolean","description":"Indique si le contenu attendu est present sur le stockage."},"sizeBytes":{"type":"integer","nullable":true,"description":"Valeur de sizeBytes."},"installed":{"type":"boolean","nullable":true,"description":"Valeur de installed."},"installedVersionCode":{"type":"integer","nullable":true,"description":"Valeur de installedVersionCode."},"expectedVersionCode":{"type":"integer","nullable":true,"description":"Valeur de expectedVersionCode."},"managedPaths":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Chemins geres encore presents, copies destinationPath comprises. Une copie residuelle suffit a considerer le contenu comme present, meme si le repertoire canonique a ete purge."}},"description":"Modèle de données ContentPresence."},"ContentStatusSnapshot":{"type":"object","required":["contentId","type","status","computedAt"],"properties":{"contentId":{"type":"string","description":"Valeur de contentId."},"type":{"type":"string","enum":["application","video","file"],"description":"Valeur de type."},"packageName":{"type":"string","description":"Valeur de packageName."},"status":{"type":"string","enum":["ASSIGNED","DOWNLOADING","INSTALLING","INSTALLED","OUTDATED","FAILED","MISSING","PENDING_UNINSTALL"],"description":"Etat calcule du deploiement sur cet appareil."},"progress":{"type":"number","description":"Valeur de progress."},"installedVersionCode":{"type":"integer","description":"Valeur de installedVersionCode."},"expectedVersionCode":{"type":"integer","description":"Valeur de expectedVersionCode."},"computedAt":{"type":"string","format":"date-time","description":"Date du dernier inventaire utilise pour calculer le statut."}},"description":"Modèle de données ContentStatusSnapshot."},"DeviceEventHistory":{"type":"object","required":["eventId","device","enterprise","timestamp","type","source","payload"],"properties":{"eventId":{"type":"string","description":"Valeur de eventId."},"device":{"type":"string","description":"Valeur de device."},"enterprise":{"type":"string","description":"Valeur de enterprise."},"timestamp":{"type":"string","format":"date-time","description":"Valeur de timestamp."},"type":{"type":"string","description":"Type stable de l evenement, par exemple PACKAGE_INSTALLED, DOWNLOAD_STATUS_CHANGED ou CONTENT_ASSIGNED."},"source":{"type":"string","enum":["device","api","system"],"description":"Valeur de source."},"actor":{"type":"string","nullable":true,"description":"Identifiant de l acteur pour une action issue de l API."},"payload":{"type":"object","additionalProperties":true,"description":"Valeur de payload."},"createdAt":{"type":"string","format":"date-time","description":"Valeur de createdAt."}},"description":"Modèle de données DeviceEventHistory."},"DeviceEventInput":{"type":"object","required":["type","timestamp"],"properties":{"eventId":{"type":"string","maxLength":128,"description":"Identifiant idempotent de l evenement. Un identifiant deterministe est derive pour les anciens clients qui l omettent."},"type":{"type":"string","maxLength":64,"description":"Valeur de type."},"timestamp":{"type":"number","description":"Instant de l evenement en millisecondes Unix."},"payload":{"type":"object","additionalProperties":true,"description":"Charge utile limitee a 16 Kio une fois serialisee."}},"description":"Modèle de données DeviceEventInput."},"DeviceHeartbeatResponse":{"allOf":[{"$ref":"#/components/schemas/Device"},{"type":"object","required":["acknowledgedEventIds","rejectedEvents"],"properties":{"acknowledgedEventIds":{"type":"array","description":"Identifiants des evenements durablement historises.","items":{"type":"string"}},"rejectedEvents":{"type":"array","description":"Evenements mal formes ignores sans bloquer le reste de la telemetrie.","items":{"type":"object","properties":{"index":{"type":"integer"},"reason":{"type":"string"}}}}}}],"description":"Modèle de données DeviceHeartbeatResponse."},"DeviceEventPage":{"type":"object","required":["page","limit","total","items"],"properties":{"page":{"type":"integer","description":"Valeur de page."},"limit":{"type":"integer","description":"Valeur de limit."},"total":{"type":"integer","description":"Valeur de total."},"items":{"type":"array","items":{"$ref":"#/components/schemas/DeviceEventHistory"},"description":"Valeur de items."}},"description":"Modèle de données DeviceEventPage."},"PackageConflictError":{"type":"object","required":["code","message","conflicts"],"properties":{"code":{"type":"string","enum":["PACKAGE_NAME_CONFLICT"],"description":"Valeur de code."},"message":{"type":"string","description":"Valeur de message."},"conflicts":{"type":"array","items":{"type":"object","required":["packageName","applications"],"properties":{"packageName":{"type":"string"},"applications":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"description":"Valeur de conflicts."}},"description":"Modèle de données PackageConflictError."},"AppDeploymentStatsResponse":{"type":"object","required":["message","data"],"properties":{"message":{"type":"string","description":"Valeur de message."},"data":{"$ref":"#/components/schemas/AppDeploymentStats","description":"Valeur de data."}},"description":"Modèle de données AppDeploymentStatsResponse."},"AppDeploymentStats":{"type":"object","required":["totalApps","totalVideos","totalFiles","totalDevices","applications","videos","files"],"properties":{"totalApps":{"type":"integer","description":"Valeur de totalApps."},"totalVideos":{"type":"integer","description":"Valeur de totalVideos."},"totalFiles":{"type":"integer","description":"Valeur de totalFiles."},"totalDevices":{"type":"integer","description":"Valeur de totalDevices."},"applications":{"type":"array","items":{"$ref":"#/components/schemas/ApplicationDeploymentStats"},"description":"Valeur de applications."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/ContentDeploymentStats"},"description":"Valeur de videos."},"files":{"type":"array","items":{"$ref":"#/components/schemas/ContentDeploymentStats"},"description":"Valeur de files."}},"description":"Modèle de données AppDeploymentStats."},"ApplicationDeploymentStats":{"type":"object","properties":{"packageName":{"type":"string","description":"Valeur de packageName."},"appIconUrl":{"type":"string","nullable":true,"description":"Valeur de appIconUrl."},"assignedOnDevices":{"type":"integer","description":"Valeur de assignedOnDevices."},"installedOnDevices":{"type":"integer","description":"Valeur de installedOnDevices."},"totalDevices":{"type":"integer","description":"Valeur de totalDevices."},"coveragePercent":{"type":"number","description":"Valeur de coveragePercent."},"versions":{"type":"array","items":{"type":"object","properties":{"codeVersion":{"type":"integer"},"count":{"type":"integer"}}},"description":"Valeur de versions."}},"description":"Modèle de données ApplicationDeploymentStats."},"ContentDeploymentStats":{"type":"object","properties":{"contentId":{"type":"string","description":"Valeur de contentId."},"title":{"type":"string","description":"Valeur de title."},"name":{"type":"string","description":"Valeur de name."},"posterUrl":{"type":"string","nullable":true,"description":"Valeur de posterUrl."},"assignedOnDevices":{"type":"integer","description":"Valeur de assignedOnDevices."},"installedOnDevices":{"type":"integer","description":"Valeur de installedOnDevices."},"totalDevices":{"type":"integer","description":"Valeur de totalDevices."},"coveragePercent":{"type":"number","description":"Valeur de coveragePercent."}},"description":"Modèle de données ContentDeploymentStats."},"DownloadTask":{"type":"object","properties":{"downloadId":{"type":"number","description":"Valeur de downloadId."},"url":{"type":"string","description":"Valeur de url."},"dir":{"type":"string","description":"Valeur de dir."},"fileName":{"type":"string","description":"Valeur de fileName."},"totalBytes":{"type":"number","description":"Valeur de totalBytes."},"lastBytes":{"type":"number","description":"Valeur de lastBytes."},"status":{"type":"string","enum":["PENDING","DOWNLOADING","PAUSED","COMPLETED","FAILED","UNKNOWN","QUEUED","RUNNING","INSTALLING","CANCELLED"],"description":"Valeur de status."},"progress":{"type":"number","description":"Valeur de progress."},"speed":{"type":"number","description":"Valeur de speed."},"typeFile":{"type":"string","enum":["Video","APK","Image","obb","Other"],"description":"Valeur de typeFile."},"startTime":{"type":"number","description":"Valeur de startTime."},"associatedObject":{"type":"object","description":"Valeur de associatedObject."}},"description":"Modèle de données DownloadTask."},"DeviceCommand":{"type":"object","required":["event"],"properties":{"event":{"type":"string","description":"Evenement envoye au device."},"message":{"type":"object","description":"Charge utile associee a l evenement."}},"description":"Modèle de données DeviceCommand."},"Device":{"type":"object","properties":{"_id":{"type":"string","description":"Valeur de _id."},"macAddress":{"type":"string","description":"Valeur de macAddress."},"serialNumber":{"type":"string","description":"Valeur de serialNumber."},"settings":{"$ref":"#/components/schemas/DeviceSettings","description":"Valeur de settings."},"unenrollmentStatus":{"type":"object","properties":{"status":{"type":"string","enum":["pending","success","failed","none"]}},"description":"Valeur de unenrollmentStatus."},"downloads":{"type":"array","items":{"$ref":"#/components/schemas/DownloadTask","requestDate":{"type":"string","format":"date-time"},"executionDate":{"type":"string"}},"description":"Valeur de downloads."},"installedPackages":{"type":"array","description":"Inventaire versionne des packages Android installes.","items":{"$ref":"#/components/schemas/InstalledPackage"}},"contentPresence":{"type":"array","description":"Presence sur disque des contenus affectes.","items":{"$ref":"#/components/schemas/ContentPresence"}},"contentStatuses":{"type":"array","description":"Statut calcule de chaque contenu affecte.","items":{"$ref":"#/components/schemas/ContentStatusSnapshot"}},"inventoryUpdatedAt":{"type":"string","format":"date-time","nullable":true,"description":"Date du dernier inventaire recu du device."},"pendingContentRevocations":{"type":"array","description":"Retraits demandes dont la suppression n a pas encore ete prouvee par le casque.","items":{"$ref":"#/components/schemas/ContentRevocationDirective"}}},"description":"Modèle de données Device."},"SettingDescriptor":{"type":"object","properties":{"key":{"type":"string","description":"Clé canonique (dot-path), ex `display.brightness`."},"group":{"type":"string","enum":["display","audio","power","system","security","tracking","shortcuts","network","kiosk","wifi","apps","content"],"description":"Valeur de group."},"label":{"type":"string","description":"Valeur de label."},"description":{"type":"string","description":"Valeur de description."},"type":{"type":"string","enum":["boolean","integer","float","string","enum","object","array"],"description":"Valeur de type."},"enumValues":{"type":"array","items":{},"description":"Valeur de enumValues."},"min":{"type":"number","description":"Valeur de min."},"max":{"type":"number","description":"Valeur de max."},"step":{"type":"number","description":"Valeur de step."},"unit":{"type":"string","description":"Valeur de unit."},"defaultValue":{"description":"Valeur de defaultValue."},"brands":{"type":"array","items":{"type":"string","enum":["pico","htc","meta","generic"]},"description":"Valeur de brands."},"requiresDeviceOwner":{"type":"boolean","description":"Valeur de requiresDeviceOwner."},"requiresModel":{"type":"array","items":{"type":"string"},"description":"Valeur de requiresModel."},"requiresReboot":{"type":"boolean","description":"Valeur de requiresReboot."},"experimental":{"type":"boolean","description":"Valeur de experimental."}},"description":"Modèle de données SettingDescriptor."},"BrandCatalog":{"type":"object","properties":{"brand":{"type":"string","enum":["pico","htc","meta","generic"],"description":"Valeur de brand."},"displayName":{"type":"string","description":"Valeur de displayName."},"knownModels":{"type":"array","items":{"type":"string"},"description":"Valeur de knownModels."},"settings":{"type":"array","items":{"$ref":"#/components/schemas/SettingDescriptor"},"description":"Valeur de settings."}},"description":"Modèle de données BrandCatalog."},"SettingsCatalog":{"type":"object","properties":{"version":{"type":"string","description":"Valeur de version."},"groups":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"}}},"description":"Valeur de groups."},"settings":{"type":"array","items":{"$ref":"#/components/schemas/SettingDescriptor"},"description":"Valeur de settings."},"brands":{"type":"array","items":{"$ref":"#/components/schemas/BrandCatalog"},"description":"Valeur de brands."}},"description":"Modèle de données SettingsCatalog."},"ContentRevocation":{"type":"object","description":"Suivi d'un retrait de contenu. L'enregistrement survit au retrait lui-meme : le calcul de statut n'itere que sur le contenu affecte, donc retirer le contenu detruirait l'information que l'on veut suivre.","required":["revocationId","contentId","contentType","requestedAt","status"],"properties":{"revocationId":{"type":"string","description":"Generation opaque du retrait. Une confirmation ne vaut que pour cette generation : un rapport decrivant un retrait anterieur ne peut pas confirmer un retrait ulterieur du meme contenu."},"contentId":{"type":"string","description":"Valeur de contentId."},"contentType":{"type":"string","enum":["application","video","file"],"description":"Valeur de contentType."},"packageName":{"type":"string","nullable":true,"description":"Valeur de packageName."},"requestedAt":{"type":"string","format":"date-time","description":"Valeur de requestedAt."},"status":{"type":"string","enum":["pending","confirmed","cancelled_reassigned","closed_device_retired"],"description":"pending : retrait demande, pas encore prouve. confirmed : le casque a prouve l'absence du contenu. cancelled_reassigned : le contenu a ete reaffecte avant la preuve. closed_device_retired : appareil desenrole, archive ou remplace, la preuve ne viendra jamais. Seul confirmed atteste une suppression."},"confirmedAt":{"type":"string","format":"date-time","nullable":true,"description":"Valeur de confirmedAt."},"confirmedBy":{"type":"string","enum":["state","event"],"nullable":true,"description":"state : deduit de l'inventaire complet remonte par le casque, chemin autoritaire. event : deduit d'un evenement de suppression, chemin rapide."},"closedAt":{"type":"string","format":"date-time","nullable":true,"description":"Valeur de closedAt."},"closedReason":{"type":"string","nullable":true,"description":"Valeur de closedReason."},"actorId":{"type":"string","nullable":true,"description":"Valeur de actorId."},"ambiguousSince":{"type":"string","format":"date-time","nullable":true,"description":"Date de la derniere desinstallation que le casque n'a pas su rattacher a un contenu, plusieurs contenus partageant le meme package. Aucune confirmation n'est prononcee dans ce cas."}}},"ContentRevocationDirective":{"type":"object","description":"Ordre de retrait servi au casque tant que la revocation est en attente. C'est la seule correspondance dont dispose le casque entre un package desinstalle et son contenu, celui-ci ayant quitte sa configuration.","required":["revocationId","contentType","contentId","requestedAt"],"properties":{"revocationId":{"type":"string","description":"Valeur de revocationId."},"contentType":{"type":"string","enum":["application","video","file"],"description":"Valeur de contentType."},"contentId":{"type":"string","description":"Valeur de contentId."},"packageName":{"type":"string","nullable":true,"description":"Valeur de packageName."},"requestedAt":{"type":"string","format":"date-time","description":"Valeur de requestedAt."}}},"ActivityError":{"type":"object","description":"Erreur des statistiques d'activité.","required":["message"],"properties":{"message":{"type":"string","example":"startDate must be before endDate","description":"Motif du refus, en anglais."}}},"ActivityCounters":{"type":"object","description":"Compteurs d'activité communs au résumé, aux appareils et aux contenus.","properties":{"events":{"type":"integer","description":"Nombre d'événements retenus par les filtres."},"commands":{"type":"object","description":"Commandes envoyées aux appareils et leur issue.","properties":{"issued":{"type":"integer","description":"Commandes émises."},"completed":{"type":"integer","description":"Commandes terminées, quelle que soit leur issue."},"succeeded":{"type":"integer","description":"Commandes réussies."},"failed":{"type":"integer","description":"Commandes en échec."},"unreachable":{"type":"integer","description":"Commandes restées sans réponse, appareil injoignable."}}},"downloads":{"type":"object","description":"Téléchargements de contenus sur les appareils.","properties":{"started":{"type":"integer","description":"Téléchargements démarrés. Reste à 0 tant que le casque n'historise pas la mise en file."},"completed":{"type":"integer","description":"Téléchargements réussis."},"failed":{"type":"integer","description":"Téléchargements en échec."},"cancelled":{"type":"integer","description":"Téléchargements annulés."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les issues connues (réussis + échecs), `null` sans issue."}}},"installations":{"type":"object","description":"Installations d'APK menées par le service MDM.","properties":{"started":{"type":"integer","description":"Installations démarrées."},"completed":{"type":"integer","description":"Installations réussies."},"failed":{"type":"integer","description":"Installations en échec."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les installations terminées, `null` sans issue."}}},"inventory":{"type":"object","description":"Changements d'inventaire observés sur les appareils.","properties":{"installed":{"type":"integer","description":"Packages apparus."},"updated":{"type":"integer","description":"Packages mis à jour."},"uninstalled":{"type":"integer","description":"Packages désinstallés."}}},"assignments":{"type":"object","description":"Affectations de contenus décidées depuis Pulse.","properties":{"assigned":{"type":"integer","description":"Contenus affectés ou réaffectés."},"updated":{"type":"integer","description":"Contenus mis à jour."},"removed":{"type":"integer","description":"Contenus retirés."}}}}},"ActivitySummary":{"type":"object","description":"Résumé de l'activité de la flotte sur la période.","properties":{"source":{"type":"string","enum":["device-event-history"],"description":"Origine des statistiques, distincte des métriques d'usage de l'API (`RequestLog`)."},"scope":{"type":"object","description":"Périmètre effectivement couvert, déduit du credential.","properties":{"enterpriseId":{"type":"string","description":"Entreprise couverte : celle du credential, ou la flotte demandée avec `enterpriseId`."}}},"period":{"type":"object","description":"Période effectivement couverte.","properties":{"startDate":{"type":"string","format":"date-time","nullable":true,"description":"Début effectif de la période, ramené au début de son heure."},"endDate":{"type":"string","format":"date-time","nullable":true,"description":"Fin effective de la période, étendue à la fin de son heure."},"timezone":{"type":"string","example":"Europe/Paris","description":"Fuseau des bornes et de la chronologie, sous sa forme canonique."},"granularity":{"type":"string","enum":["day","week","month"]}}},"filters":{"type":"object","description":"Filtres appliqués, sous leur forme normalisée.","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"eventTypes":{"type":"array","items":{"type":"string"}},"contentId":{"type":"string","nullable":true},"packageName":{"type":"string","nullable":true}}},"events":{"type":"integer","description":"Nombre d'événements retenus par les filtres."},"commands":{"type":"object","description":"Commandes envoyées aux appareils et leur issue.","properties":{"issued":{"type":"integer","description":"Commandes émises."},"completed":{"type":"integer","description":"Commandes terminées, quelle que soit leur issue."},"succeeded":{"type":"integer","description":"Commandes réussies."},"failed":{"type":"integer","description":"Commandes en échec."},"unreachable":{"type":"integer","description":"Commandes restées sans réponse, appareil injoignable."}}},"downloads":{"type":"object","description":"Téléchargements de contenus sur les appareils.","properties":{"started":{"type":"integer","description":"Téléchargements démarrés. Reste à 0 tant que le casque n'historise pas la mise en file."},"completed":{"type":"integer","description":"Téléchargements réussis."},"failed":{"type":"integer","description":"Téléchargements en échec."},"cancelled":{"type":"integer","description":"Téléchargements annulés."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les issues connues (réussis + échecs), `null` sans issue."}}},"installations":{"type":"object","description":"Installations d'APK menées par le service MDM.","properties":{"started":{"type":"integer","description":"Installations démarrées."},"completed":{"type":"integer","description":"Installations réussies."},"failed":{"type":"integer","description":"Installations en échec."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les installations terminées, `null` sans issue."}}},"inventory":{"type":"object","description":"Changements d'inventaire observés sur les appareils.","properties":{"installed":{"type":"integer","description":"Packages apparus."},"updated":{"type":"integer","description":"Packages mis à jour."},"uninstalled":{"type":"integer","description":"Packages désinstallés."}}},"assignments":{"type":"object","description":"Affectations de contenus décidées depuis Pulse.","properties":{"assigned":{"type":"integer","description":"Contenus affectés ou réaffectés."},"updated":{"type":"integer","description":"Contenus mis à jour."},"removed":{"type":"integer","description":"Contenus retirés."}}},"devicesWithEvents":{"type":"integer","description":"Appareils ayant au moins un événement sur la période."},"activeDevices":{"type":"integer","description":"Appareils ayant eux-mêmes émis un événement, s'étant connectés ou enrôlés. Une déconnexion ou une commande restée sans réponse ne suffit pas."},"launches":{"type":"object","nullable":true,"description":"Lancements de contenus. Toujours `null` : aucun événement de lancement n'est encore historisé."},"timeline":{"type":"array","description":"Périodes non vides, dans l'ordre chronologique.","items":{"type":"object","properties":{"bucket":{"type":"string","example":"2026-W36","description":"Jour (`2026-09-01`), semaine ISO (`2026-W36`) ou mois (`2026-09`)."},"events":{"type":"integer","description":"Événements de la période."},"devices":{"type":"integer","description":"Appareils distincts de la période."}}}}}},"ActivityEventType":{"type":"object","properties":{"type":{"type":"string","example":"DOWNLOAD_STATUS_CHANGED","description":"Type d'événement."},"events":{"type":"integer","description":"Événements de ce type."},"devices":{"type":"integer","description":"Appareils distincts concernés."},"firstEventAt":{"type":"string","format":"date-time","description":"Premier événement de l'entrée sur la période."},"lastEventAt":{"type":"string","format":"date-time","description":"Dernier événement de l'entrée sur la période."}},"description":"Modèle de données ActivityEventType."},"ActivityDevice":{"type":"object","properties":{"deviceId":{"type":"string","description":"Identifiant de l'appareil."},"status":{"type":"string","enum":["enrolled","archived","deleted"],"description":"`enrolled` : en service ; `archived` : remplacé par un nouvel enrôlement ; `deleted` : supprimé, décrit par sa fiche figée à la suppression."},"label":{"type":"string","nullable":true,"description":"Libellé, figé à la suppression pour un appareil supprimé. `null` pour un appareil supprimé avant l'existence des fiches."},"androidId":{"type":"string","nullable":true,"description":"Identifiant Android, figé à la suppression pour un appareil supprimé."},"deletedAt":{"type":"string","format":"date-time","nullable":true,"description":"Date de suppression, `null` si l'appareil existe encore ou si elle est inconnue."},"events":{"type":"integer","description":"Nombre d'événements retenus par les filtres."},"commands":{"type":"object","description":"Commandes envoyées aux appareils et leur issue.","properties":{"issued":{"type":"integer","description":"Commandes émises."},"completed":{"type":"integer","description":"Commandes terminées, quelle que soit leur issue."},"succeeded":{"type":"integer","description":"Commandes réussies."},"failed":{"type":"integer","description":"Commandes en échec."},"unreachable":{"type":"integer","description":"Commandes restées sans réponse, appareil injoignable."}}},"downloads":{"type":"object","description":"Téléchargements de contenus sur les appareils.","properties":{"started":{"type":"integer","description":"Téléchargements démarrés. Reste à 0 tant que le casque n'historise pas la mise en file."},"completed":{"type":"integer","description":"Téléchargements réussis."},"failed":{"type":"integer","description":"Téléchargements en échec."},"cancelled":{"type":"integer","description":"Téléchargements annulés."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les issues connues (réussis + échecs), `null` sans issue."}}},"installations":{"type":"object","description":"Installations d'APK menées par le service MDM.","properties":{"started":{"type":"integer","description":"Installations démarrées."},"completed":{"type":"integer","description":"Installations réussies."},"failed":{"type":"integer","description":"Installations en échec."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les installations terminées, `null` sans issue."}}},"inventory":{"type":"object","description":"Changements d'inventaire observés sur les appareils.","properties":{"installed":{"type":"integer","description":"Packages apparus."},"updated":{"type":"integer","description":"Packages mis à jour."},"uninstalled":{"type":"integer","description":"Packages désinstallés."}}},"assignments":{"type":"object","description":"Affectations de contenus décidées depuis Pulse.","properties":{"assigned":{"type":"integer","description":"Contenus affectés ou réaffectés."},"updated":{"type":"integer","description":"Contenus mis à jour."},"removed":{"type":"integer","description":"Contenus retirés."}}},"firstEventAt":{"type":"string","format":"date-time","description":"Premier événement de l'entrée sur la période."},"lastEventAt":{"type":"string","format":"date-time","description":"Dernier événement de l'entrée sur la période."}},"description":"Modèle de données ActivityDevice."},"ActivityContent":{"type":"object","properties":{"packageName":{"type":"string","nullable":true,"description":"Package de l'application, `null` pour une vidéo ou un fichier."},"contentIds":{"type":"array","items":{"type":"string"},"description":"Identifiants de contenu rencontrés pour cette entrée."},"devices":{"type":"integer","description":"Appareils distincts concernés."},"events":{"type":"integer","description":"Nombre d'événements retenus par les filtres."},"commands":{"type":"object","description":"Commandes envoyées aux appareils et leur issue.","properties":{"issued":{"type":"integer","description":"Commandes émises."},"completed":{"type":"integer","description":"Commandes terminées, quelle que soit leur issue."},"succeeded":{"type":"integer","description":"Commandes réussies."},"failed":{"type":"integer","description":"Commandes en échec."},"unreachable":{"type":"integer","description":"Commandes restées sans réponse, appareil injoignable."}}},"downloads":{"type":"object","description":"Téléchargements de contenus sur les appareils.","properties":{"started":{"type":"integer","description":"Téléchargements démarrés. Reste à 0 tant que le casque n'historise pas la mise en file."},"completed":{"type":"integer","description":"Téléchargements réussis."},"failed":{"type":"integer","description":"Téléchargements en échec."},"cancelled":{"type":"integer","description":"Téléchargements annulés."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les issues connues (réussis + échecs), `null` sans issue."}}},"installations":{"type":"object","description":"Installations d'APK menées par le service MDM.","properties":{"started":{"type":"integer","description":"Installations démarrées."},"completed":{"type":"integer","description":"Installations réussies."},"failed":{"type":"integer","description":"Installations en échec."},"failureRate":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Part des échecs parmi les installations terminées, `null` sans issue."}}},"inventory":{"type":"object","description":"Changements d'inventaire observés sur les appareils.","properties":{"installed":{"type":"integer","description":"Packages apparus."},"updated":{"type":"integer","description":"Packages mis à jour."},"uninstalled":{"type":"integer","description":"Packages désinstallés."}}},"assignments":{"type":"object","description":"Affectations de contenus décidées depuis Pulse.","properties":{"assigned":{"type":"integer","description":"Contenus affectés ou réaffectés."},"updated":{"type":"integer","description":"Contenus mis à jour."},"removed":{"type":"integer","description":"Contenus retirés."}}},"firstEventAt":{"type":"string","format":"date-time","description":"Premier événement de l'entrée sur la période."},"lastEventAt":{"type":"string","format":"date-time","description":"Dernier événement de l'entrée sur la période."}},"description":"Modèle de données ActivityContent."},"ActivityEventTypePage":{"type":"object","properties":{"source":{"type":"string","enum":["device-event-history"],"description":"Origine des statistiques, distincte des métriques d'usage de l'API (`RequestLog`)."},"scope":{"type":"object","description":"Périmètre effectivement couvert, déduit du credential.","properties":{"enterpriseId":{"type":"string","description":"Entreprise couverte : celle du credential, ou la flotte demandée avec `enterpriseId`."}}},"period":{"type":"object","description":"Période effectivement couverte.","properties":{"startDate":{"type":"string","format":"date-time","nullable":true,"description":"Début effectif de la période, ramené au début de son heure."},"endDate":{"type":"string","format":"date-time","nullable":true,"description":"Fin effective de la période, étendue à la fin de son heure."},"timezone":{"type":"string","example":"Europe/Paris","description":"Fuseau des bornes et de la chronologie, sous sa forme canonique."}}},"filters":{"type":"object","description":"Filtres appliqués, sous leur forme normalisée.","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"eventTypes":{"type":"array","items":{"type":"string"}},"contentId":{"type":"string","nullable":true},"packageName":{"type":"string","nullable":true}}},"page":{"type":"integer","description":"Page servie."},"limit":{"type":"integer","description":"Taille de page."},"total":{"type":"integer","description":"Nombre total d'entrées, pas d'événements."},"items":{"type":"array","description":"Entrées de la page.","items":{"$ref":"#/components/schemas/ActivityEventType"}}},"description":"Modèle de données ActivityEventTypePage."},"ActivityDevicePage":{"type":"object","properties":{"source":{"type":"string","enum":["device-event-history"],"description":"Origine des statistiques, distincte des métriques d'usage de l'API (`RequestLog`)."},"scope":{"type":"object","description":"Périmètre effectivement couvert, déduit du credential.","properties":{"enterpriseId":{"type":"string","description":"Entreprise couverte : celle du credential, ou la flotte demandée avec `enterpriseId`."}}},"period":{"type":"object","description":"Période effectivement couverte.","properties":{"startDate":{"type":"string","format":"date-time","nullable":true,"description":"Début effectif de la période, ramené au début de son heure."},"endDate":{"type":"string","format":"date-time","nullable":true,"description":"Fin effective de la période, étendue à la fin de son heure."},"timezone":{"type":"string","example":"Europe/Paris","description":"Fuseau des bornes et de la chronologie, sous sa forme canonique."}}},"filters":{"type":"object","description":"Filtres appliqués, sous leur forme normalisée.","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"eventTypes":{"type":"array","items":{"type":"string"}},"contentId":{"type":"string","nullable":true},"packageName":{"type":"string","nullable":true}}},"page":{"type":"integer","description":"Page servie."},"limit":{"type":"integer","description":"Taille de page."},"total":{"type":"integer","description":"Nombre total d'entrées, pas d'événements."},"items":{"type":"array","description":"Entrées de la page.","items":{"$ref":"#/components/schemas/ActivityDevice"}}},"description":"Modèle de données ActivityDevicePage."},"ActivityContentPage":{"type":"object","properties":{"source":{"type":"string","enum":["device-event-history"],"description":"Origine des statistiques, distincte des métriques d'usage de l'API (`RequestLog`)."},"scope":{"type":"object","description":"Périmètre effectivement couvert, déduit du credential.","properties":{"enterpriseId":{"type":"string","description":"Entreprise couverte : celle du credential, ou la flotte demandée avec `enterpriseId`."}}},"period":{"type":"object","description":"Période effectivement couverte.","properties":{"startDate":{"type":"string","format":"date-time","nullable":true,"description":"Début effectif de la période, ramené au début de son heure."},"endDate":{"type":"string","format":"date-time","nullable":true,"description":"Fin effective de la période, étendue à la fin de son heure."},"timezone":{"type":"string","example":"Europe/Paris","description":"Fuseau des bornes et de la chronologie, sous sa forme canonique."}}},"filters":{"type":"object","description":"Filtres appliqués, sous leur forme normalisée.","properties":{"deviceIds":{"type":"array","items":{"type":"string"}},"eventTypes":{"type":"array","items":{"type":"string"}},"contentId":{"type":"string","nullable":true},"packageName":{"type":"string","nullable":true}}},"page":{"type":"integer","description":"Page servie."},"limit":{"type":"integer","description":"Taille de page."},"total":{"type":"integer","description":"Nombre total d'entrées, pas d'événements."},"items":{"type":"array","description":"Entrées de la page.","items":{"$ref":"#/components/schemas/ActivityContent"}}},"description":"Modèle de données ActivityContentPage."},"ErrorResponse":{"type":"object","description":"Erreur standard de l’API.","required":["error"],"properties":{"error":{"type":"string","description":"Code d’erreur stable."},"message":{"type":"string","description":"Détails lisibles."},"requestId":{"type":"string","description":"Identifiant de corrélation pour le support."}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT de l’organisation envoyé avec `Authorization: Bearer <token>`."}}},"tags":[{"name":"ApkDetails","x-displayName":"Détails APK","description":"Métadonnées des applications Android."},{"name":"Contents","x-displayName":"Contenus","description":"Vidéos et applications déployées sur les appareils."},{"name":"Devices","x-displayName":"Appareils","description":"Gestion, configuration et commandes des casques."},{"name":"Enterprises","x-displayName":"Entreprises","description":"Enrôlement et paramètres au niveau organisation."},{"name":"General","x-displayName":"Général","description":"Endpoints transverses."},{"name":"Build","x-displayName":"Builds","description":"Artefacts et versions du service Android."},{"name":"Readings","x-displayName":"Lectures","description":"Enregistrement et statistiques des sessions de lecture."},{"name":"Settings catalog","x-displayName":"Catalogue de paramètres","description":"Descripteurs de paramètres par marque."},{"name":"Stats","x-displayName":"Statistiques","description":"Métriques de flotte, santé et connectivité."},{"name":"Streaming","x-displayName":"Streaming","description":"Partage d’écran et historique de stream."}],"servers":[{"url":"https://api.pulse-xr.com","description":"Production"}],"security":[{"bearerAuth":[]}]}